完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
定时器可以在中断里处理抖动
比如按键中断里,按键参数会进行跳变,所以要等待数值的稳定时候,才进行上报 我们可以把数值设置的大一点,模仿机械跳变,这样就可以看得出来,定时器真的被使用了 驱动编写 给每个按键提供定时器 在结构体里放入定时器 初始化定时器 1.给每个定时器设置,触发函数,并且为出发的函数提供数据 setup_timer(&buttons.timer, x6818_buttons_timer,(unsigned long)&buttons); 2. 设置第一次的定时器超时时间 3. 把定时器进行添加 定时器函数编写 当到时间就可以触发定时器了,在里面进行按键的读取 触发定时器 我们在中断函数里触发定时器,所以先触发中断函数 中断函数里,设置超时时间,要是一直按就会延长超时时间,直到没有中断产生,才会触发定时器 这里设置了 HZ/5 = 1s/5 200ms 的延时,我们只要按的快,就不会读取值,为了测试定时器有没有用 测试结果 按的快就当作抖动消掉,还是不错的 源码 button_drv.ko #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define DEVICE_NAME "gecBt" //设备名字 //按键结构体 struct button_desc { int gpio; int number; char *name; struct timer_list timer; }; //按键的管脚,编号,名字 static struct button_desc buttons[] = { { (PAD_GPIO_B + 9 ), 0, "KEY0" },//B9 { (PAD_GPIO_A + 28), 1, "KEY1" },//A28 { (PAD_GPIO_B + 30), 2, "KEY2" },//volup//B30 { (PAD_GPIO_B + 31), 3, "KEY3" },//voidn//B31 //{ (PAD_GPIO_B + 9 ), 3, "KEY3" },//B9 }; //赋按键的初始值 static volatile char key_values[] = { 0, 0, 0, 0 }; //等待队列申请 static DECLARE_WAIT_QUEUE_HEAD(button_waitq); static volatile int ev_press = 0; /************************************************* *定时器 *************************************************/ //static void x6818_buttons_timer(unsigned long _data) static irqreturn_t button_interrupt(int irq, void *dev_id) { struct button_desc *bdata = (struct button_desc *)dev_id; //struct button_desc *bdata = (struct button_desc *)_data; printk("will mod timer "); mod_timer(&bdata->timer, jiffies + HZ/5);//1s/50 return IRQ_HANDLED; } /************************************************* *按键中断 *************************************************/ //static irqreturn_t button_interrupt(int irq, void *dev_id) static void x6818_buttons_timer(unsigned long _data) { //struct button_desc *bdata = (struct button_desc *)dev_id; struct button_desc *bdata = (struct button_desc *)_data; int down; int number; unsigned tmp; tmp = gpio_get_value(bdata->gpio); /* active low */ down = tmp; pr_err("KEY %d: %08x ", bdata->number, down); number = bdata->number; if (down == (key_values[number])) { key_values[number] = '0' + down; ev_press = 1; wake_up_interruptible(&button_waitq); } //return IRQ_HANDLED; } /************************************************* *按键初始化 *************************************************/ static int x6818_buttons_init(void) { int irq; int i; int err = 0; //每个按键 都设置 为双边向沿 触发模式 for (i = 0; i < ARRAY_SIZE(buttons); i++) { if (!buttons.gpio) continue; gpio_free(buttons.gpio); setup_timer(&buttons.timer, x6818_buttons_timer, (unsigned long)&buttons); //buttons.timer.expires = ~0;//初始化定时器时间 add_timer(&buttons.timer); irq = gpio_to_irq(buttons.gpio); pr_err("irq = %.2d ",irq); err = request_irq(irq, button_interrupt, IRQ_TYPE_EDGE_BOTH, buttons.name, (void *)&buttons); if (err) { pr_err("irq = %.2d is failed ",i); break; } } //中断申请失败的时候,释放中断 if (err) { i--; for (; i >= 0; i--) { if (!buttons.gpio) continue; irq = gpio_to_irq(buttons.gpio); disable_irq(irq); free_irq(irq, (void *)&buttons); del_timer_sync(&buttons.timer); } return -EBUSY; } ev_press = 1; return 0; } static int x6818_buttons_open(struct inode *inode, struct file *file) { return 0; } /************************************************* *按键释放 *************************************************/ static int x6818_buttons_close(struct inode *inode, struct file *file) { int irq, i; for (i = 0; i < ARRAY_SIZE(buttons); i++) { if (!buttons.gpio) continue; irq = gpio_to_irq(buttons.gpio); free_irq(irq, (void *)&buttons); del_timer_sync(&buttons.timer); } return 0; } /************************************************* *按键读取值 *************************************************/ static int x6818_buttons_read(struct file *filp, char __user *buff, size_t count, loff_t *offp) { unsigned long err; if (!ev_press) { if (filp->f_flags & O_NONBLOCK) return -EAGAIN; else{ pr_err("wai_enven********************* "); wait_event_interruptible(button_waitq, ev_press); pr_err("OK********************************* "); } } ev_press = 0; err = copy_to_user((void *)buff, (const void *)(&key_values), min(sizeof(key_values), count)); return err ? -EFAULT : min(sizeof(key_values), count); } /************************************************* *按键的头 *************************************************/ static unsigned int x6818_buttons_poll( struct file *file, struct poll_table_struct *wait) { unsigned int mask = 0; poll_wait(file, &button_waitq, wait); if (ev_press) mask |= POLLIN | POLLRDNORM; return mask; } /************************************************* *文件操作集 *************************************************/ static struct file_operations dev_fops = { .owner = THIS_MODULE, .open = x6818_buttons_open, .release = x6818_buttons_close, .read = x6818_buttons_read, //.poll = x6818_buttons_poll, }; /************************************************* *杂项设备 *************************************************/ static struct miscdevice misc = { .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = &dev_fops, }; /******************************************************************** *驱动的初始化函数--->从内核中申请资源(内核、中断、设备号、锁....) ********************************************************************/ static int __init button_dev_init(void) { int ret; ret = misc_register(&misc); x6818_buttons_init(); pr_err(DEVICE_NAME" initialized "); return ret; } /***************************************************************** *驱动退出函数 --->将申请的资源还给内核 *****************************************************************/ static void __exit button_dev_exit(void) { misc_deregister(&misc); } module_init(button_dev_init); //驱动的入口函数会调用一个用户的初始化函数 module_exit(button_dev_exit); //驱动的出口函数会调用一个用户的退出函数 //驱动的描述信息: #modinfo *.ko , 驱动的描述信息并不是必需的。 MODULE_AUTHOR("ZOROE@GEC"); //驱动的作者 MODULE_DESCRIPTION("Butoons of driver"); //驱动的描述 MODULE_LICENSE("GPL"); //遵循的协议 原作者:鸭鸭打瞌睡 |
|
相关推荐
1个回答
|
|
不懂帮顶
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
迅为RK3568开发板EMMC镜像导出打包update.img
403 浏览 0 评论
飞凌嵌入式-ELFBOARD 硬件知识分享-ELF 2电源电路讲解
1004 浏览 0 评论
1713 浏览 0 评论
飞凌嵌入式ElfBoard ELF 1板卡-mfgtools烧录流程介绍之烧写所需镜像
1511 浏览 0 评论
飞凌嵌入式ElfBoard ELF 1板卡-mfgtools烧录流程之烧写方法
956 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-26 17:53 , Processed in 0.734759 second(s), Total 75, Slave 58 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号