龙芯技术社区
直播中

jf_48561352

未满1年用户 30经验值
擅长:嵌入式技术
私信 关注
[2K系列]

【龙芯2K0300蜂鸟板试用】6 gpio控制relay字符驱动

gpio是最常用的也是最简单的驱动程序,在龙芯2k0300中,几乎所有的gpio引脚都可以做为gpio引脚使用(多数具备复用功能),此文通过控制gpio的输入,从而控制继电器relay,进而控制后端电路的开断。

硬件电路

gpio

蜂鸟的扩展引脚J9原理图如下所示,多数可用做复用功能,此时使用I2S的引脚来做gpio

QQ_1724550588799.png

继电器

继电器模块常用于控制高电流或高电压的电路

relay.gif

工作原理:

电磁线圈: 继电器内部包含一个电磁线圈,通常由绕制在绝缘芯片上的细导线组成。当通过线圈通电时,产生电磁场。

磁性吸引: 电磁场会使继电器中的铁芯(或磁性材料)受到磁性吸引,导致铁芯在电磁力的作用下移动。

触点操作: 铁芯的移动会导致机械部分的运动,最终使触点(开关)发生动作。继电器通常有常开(Normally Open,NO)和常闭(Normally Closed,NC)两组触点。

常闭触点: 在继电器未通电时处于闭合状态,当电磁线圈通电时,触点打开。

常开触点: 在继电器未通电时处于打开状态,当电磁线圈通电时,触点闭合。

电气隔离: 继电器的主要作用之一是提供电气隔离。通过电磁原理,可以在控制信号与被控制电路之间提供隔离,从而使得不同电路之间的电流不会相互影响。

驱动适配

设备树

配置gpio引脚,如上所述,使用J9-25引脚,由《引脚复用手册》可知,此引脚为gpio76,故配置如下

gpio_relay{
		compatible = "lx,gpio-relay";
		label = "relay";
		gpios = <&gpio 76 GPIO_ACTIVE_LOW>; //J9-25:cpu_i2s_mclk:gpio76
		status = "ok";
	};

驱动

平台设备

static const struct of_device_id relays_of_match[] = {
	{.compatible = "lx,gpio-relay"},
	{ }
};


static struct platform_driver lx_relays_driver = {
	.driver = {
		.name = "relays",
		.of_match_table = relays_of_match,
	},
	.probe = lx_relays_probe,
	.remove = lx_relays_remove,
};

probe

注册字符设备,创建class/device,引用设备树

static int lx_relays_probe(struct platform_device *dev)
{
	int ret = 0;
	pr_info("relays module probe\\\\r\\\\n");


	relaysdev.major = 0;
	if(relaysdev.major)
	{ 
		relaysdev.devid = MKDEV(relaysdev.major,0);
		ret = register_chrdev_region(relaysdev.devid,RELAYS_CNT,RELAYS_NAME);
	}else
	{
		ret = alloc_chrdev_region(&relaysdev.devid,0,RELAYS_CNT,RELAYS_NAME);
	}

	if(ret < 0)
	{
		pr_info("relays module fail devid\\\\r\\\\n");
		goto fail_devid;
	}else
	{
		relaysdev.major = MAJOR(relaysdev.devid);
		relaysdev.minor = MINOR(relaysdev.devid);
		pr_info("major:%d minor:%d \\\\r\\\\n",relaysdev.major,relaysdev.minor);
	}


	relaysdev.cdev.owner = THIS_MODULE;
	cdev_init(&relaysdev.cdev,&lx_relays_fops);
	cdev_add(&relaysdev.cdev,relaysdev.devid,RELAYS_CNT);

	relaysdev.class = class_create(THIS_MODULE,RELAYS_NAME);
	if(IS_ERR(relaysdev.device))
	{
		ret = PTR_ERR(relaysdev.device);
		goto fail_class;
	}

	relaysdev.device = device_create(relaysdev.class,NULL,relaysdev.devid,NULL,RELAYS_NAME);
	if(IS_ERR(relaysdev.device))
	{
		ret = PTR_ERR(relaysdev.device);
		goto fail_device;
	}


	relaysdev.nd = of_find_node_by_path("/gpio_relay");
	if(relaysdev.nd == NULL)
	{
		ret = -EINVAL;
		pr_info("relays module fail node\\\\r\\\\n");
		goto fail_nd;
	}

	relaysdev.relaysgpio = of_get_named_gpio(relaysdev.nd,"gpios",0);
	if(relaysdev.relaysgpio < 0)
	{
		ret = -EINVAL;
		printk("relays module fail gpio\\\\r\\\\n");
		goto fail_gpio;
	}

	gpio_request(relaysdev.relaysgpio,"gpios");
	gpio_direction_output(relaysdev.relaysgpio,0);

	return 0;

fail_gpio:
fail_nd:
	device_destroy(relaysdev.class,relaysdev.devid);
fail_device:
	class_destroy(relaysdev.class);
fail_class:
	unregister_chrdev_region(relaysdev.devid,RELAYS_CNT);
	cdev_del(&relaysdev.cdev);
fail_devid:
	return ret;
}

控制

控制引脚输出高低电平

ssize_t lx_relays_write (struct file *filp, const char __user *buf, size_t cnt, loff_t *ppos)

{
	struct lx_relays_dev *dev = (struct lx_relays_dev*)filp->private_data;

	int retval;
	unsigned char datebuf[1];

	

	retval=copy_from_user(datebuf,buf,cnt);
	if(retval < 0)
	{
		pr_info("kernel write failed\\\\r\\\\n");
		return -EFAULT;
	}   
	pr_info("write:%d\\\\n",datebuf[0]);
	if(datebuf[0] == RELAYS_ON)
	{
		gpio_set_value(dev->relaysgpio,0); 
	}else if(datebuf[0] == RELAYS_OFF)
	{
		gpio_set_value(dev->relaysgpio,1);
	}
	return 0;
}

应用测试

int main(int argc, char **argv)
{ 
	int fd; 
	int status; 
 
	if (argc != 2) 
	{ 
		printf("Usage: %s /dev/gpioled \\n", argv[0]); 
		return -1; 
	}
 
	fd = open(argv[1], O_RDWR); 
	if (fd == -1) 
	{ 
		printf("can not open file %s\\n", argv[1]); 
		return -1; 
	} 
 
	do
	{
		printf("please input:/0/1/q\\n");
		scanf("%d",&status);
		printf("%d\\n",status);
		if (status == 0)
		{
			write(fd, &status, 1); 
		}
		else if(status== 1)
		{
			write(fd, &status, 1);
		}
		else
		{
			printf("please error\\n");
		} 
	} while(1);
		
	close(fd); 
	return 0;
}

验证效果

加载驱动
QQ_1724597711448.png

运行应用
QQ_1724597766966.png

效果示例

效果

更多回帖

发帖
×
20
完善资料,
赚取积分