在上一个帖子中,讲述了如何给led编写驱动程序,但是实现的功能比较单一,接下来我们要实现的功能是在上一个的基础上能够单独控制每一个led灯。
上一个帖子的链接: linux驱动之LED驱动_1
上一个帖子的驱动源码在:点击打开链接 测试源码在:点击打开链接
目的:
实现板子上每个led能够单独的控制。
方法:
0、通过次设备号来单独访问每个led
1、更改入口函数: 为每个led分配一个次设备号。
for(minor=0;minor<4;minor++)
{
firstdrv_class_dev[minor] = device_create(firstdrv_class,NULL,MKDEV(major,minor),NULL,"wq_led%d",minor);
if(unlikely(IS_ERR(firstdrv_class_dev[minor])))
return PTR_ERR(firstdrv_class_dev[minor]);
}
2、同理,更改出口地址:
for(minor=0;minor<4;minor++)
{
device_unregister(firstdrv_class_dev[minor]);
}
3、这样节点就挂上去了 会在/dev 里面 出现四个设备 分别是: wq_led0,wq_led1,wq_led2,wq_led3
4. 更改open 函数,增加单独设置每个led引脚的功能: 根据次设备号进行操作
int minor = MINOR(inode ->i_rdev);//获得次设备号
switch(minor)
{
case 0://GPB5 配置为输出
{
*gpbcon &=~(0x3<<(5*2));
*gpbcon |=(0x1<<(5*2));
break;
}
case 1://GPB6 配置为输出
{
*gpbcon &=~(0x3<<(6*2));
*gpbcon |=(0x1<<(6*2));
break;
}
case 2://GPB7 配置为输出
{
*gpbcon &=~(0x3<<(7*2));
*gpbcon |=(0x1<<(7*2));
break;
}
case 3://GPB8 配置为输出
{
*gpbcon &=~(0x3<<(8*2));
*gpbcon |=(0x1<<(8*2));
break;
}
}
5、更改 write 函数,根据用户空间传过来过来的数据和次设备号对led进行操作
int minor = MINOR(file->f_dentry->d_inode->i_rdev);//获得次设备号
copy_from_user(&val,buf,count);//从用户空间向内核空间拷贝数据
switch(minor)
{
case 0://GPB5
{
if(val == 1)//亮
{
*gpbdat &=~(1<<5);
}
else//灭
{
*gpbdat|=(1<<5);
}
break;
}
case 1://GPB6
{
if(val == 1)//亮
{
*gpbdat &=~(1<<6);
}
else//灭
{
*gpbdat|=(1<<6);
}
break;
}
case 2://GPB7
{
if(val == 1)//亮
{
*gpbdat &=~(1<<7);
}
else//灭
{
*gpbdat|=(1<<7);
}
break;
}
case 3://GPB8
{
if(val == 1)//亮
{
*gpbdat &=~(1<<8);
}
else//灭
{
*gpbdat|=(1<<8);
}
break;
}
}
详细代码:
驱动程序:点击打开链接
测试程序:点击打开链接