本帖最后由 qq670300923 于 2016-8-14 20:53 编辑
昨天断网了
,时间过的真快,没想到已经来北京实训一个月了。(网正好是办的是一个月)好了不多说,下面来看看按键驱动(中断+工作队列+内核定时器去抖),是不是感觉有点多呢
。
1.首先写的是内核代码,也就不多说了(前面已经说了,不了解的可以看第二天)。
2.来看看我init里面的代码
- static int __init button_init(void)
- {
- int iRet=0;
- misc_register(&key_miscdev);
- key_hw_init();
- iRet = request_irq(205,key_int,IRQF_TRIGGER_FALLING,"zlg_key1",NULL);
- iRet = request_irq(204,key_int,IRQF_TRIGGER_FALLING,"zlg_key2",NULL);
- iRet = request_irq(196,key_int,IRQF_TRIGGER_FALLING,"zlg_key3",NULL);
- iRet = request_irq(197,key_int,IRQF_TRIGGER_FALLING,"zlg_key4",NULL);
- iRet = request_irq(198,key_int,IRQF_TRIGGER_FALLING,"zlg_key5",NULL);
- if(iRet==0)
- {
- printk("irq success\n");
- }
- else
- {
- printk("irq flast,tip:%d\n",iRet);
- }
- //创建工作
-
- INIT_WORK(&buttons_work,buttons_do_func);
- buttons_work.func = buttons_do_func;
-
- //初始化定时器
- init_timer(&buttons_timer);
- buttons_timer.function = buttons_do_timer;
-
- //注册一个定时器
- add_timer(&buttons_timer);
-
-
- return 0;
- }
复制代码首先是
misc_register(&key_miscdev)注册一个混杂设备,key_miscdev我就不多说了。(不知道可以看看我的第三天) 接在来就是硬件初始化了(这里是配置成外部中断模式),
按照这个配置寄存器,这个在数据手册的687页。(这个应该没有什么问题吧
)。下面就是request_irq这个函数了,
可以看看函数原型int request_irq(unsigned int irq,irq_handler_t handler,unsigned long flags, const char *devname, void *dev_id) 这个函数挺长的,这里的我本来应该是申请GPIO中断的,
(这个在数据手册的139页)
但是我申请的时候发现申请不了,可能是内核源码给GPIO中断再加了一次吧,实在没有办法,我就看看周立功他们给的源码,可以看到他们使用的是函数获得中断号,然后我就修改了一个下得到了我要的GPIO的中断号
,具体怎么是这个中断号我没有看,现在先直接拿来用吧。
irq_handler_t handler 这个是中断处理函数,这个再也熟悉不过了,写stm32这类芯片代码时都要用的。
unsigned long flags 表示中断的属性
const char *devnam 表示设备名字
void *dev_id 共享中断使用的(这没有用到,使用NULL)
接下来当然是INIT_WORK(&buttons_work,buttons_do_func);这个是初始化工作队列的我这里的工作队列是当中断来的时候可以让中断函数执行很少的代码,就相当于当中断来的时候,注册了一个任务(函数名buttons_do_func),等待调度,从而不会出现在中断函数里太久(linux运行是要触发中断)。
最后是 add_timer(&buttons_timer); 这个函数是相当于我们写裸机开发是我们使用的延时函数,这样是为了消除按键抖动的影响。
下面我就讲一下程序执行的过程(我就不画图表了哈),首先insomd加载模块 执行button_init这个函数,当我们按下按键是触发中断执行buttons_do_func,mod_timer(&buttons_timer, jiffies + (HZ /10)); 这个函数设置等待时间。当时间到时候操作系统调度进入buttons_do_timer函数。
可以看到我使用的短路器。按下上面的按键可以看下图效果