用定时器实现按键消抖

发布时间:2024-07-31  

   

消除抖动的实现方法

在发生中断后,延时一段时间(抖动时间t),再去读取按键值;

这里实现这段延时的方法就是使用定时器;

当按键发生中断时,启动定时器,定时器延时t秒后,再读取键值。

   

实例

driver.c

1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12
13
14 static int major;
15
16 static struct class *myKey_class;
17 static struct class_device *myKey_class_dev;
18
19 volatile unsigned long *gpfcon;
20 volatile unsigned long *gpfdat;
21
22 volatile unsigned long *gpgcon;
23 volatile unsigned long *gpgdat;
24
25 //static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
26 //static volatile int ev_press = 0;
27
28 static struct fasync_struct *button_fasyncq;
29
30 //定义原子变量,并初始化为1
31 static atomic_t canOpen = ATOMIC_INIT(1);
32
33 //定义一个定时器
34 static struct timer_list buttons_timer;
35
36 //normal:1; press:0;
37 static unsigned char keyVal = 0;
38
39 struct pin_desc {
40         unsigned int pin;
41         unsigned int key_val;
42 };
43
44 /*
45 * 按键按下键值为0x01,...; 松开键值为0x81,...
46 */
47 struct pin_desc pins_desc[3] = {
48         {S3C2410_GPF0, 0x01},
49         {S3C2410_GPF2, 0x02},        
50         {S3C2410_GPG11, 0x03},        
51 };
52
53 struct pin_desc *irq_pd;
54
55 static int myKey_open(struct inode *inode, struct file *file);
56 static int myKey_close(struct inode *inode, struct file *file);
57 static ssize_t myKey_read(struct file *file, char __user *buf, size_t size, loff_t *ppos);
58 static int myKey_fasync(int fd, struct file *filp, int on);
59
60
61 static struct file_operations myKey_fops = {
62         .open = myKey_open,
63         .read = myKey_read,
64         .owner = THIS_MODULE,
65         .release = myKey_close,
66         .fasync = myKey_fasync,
67 };
68
69
70 static irqreturn_t handle_buttons(int irq, void *pin_dc)
71 {
72         /* 每次发生中断,10ms后启动定时器,定时器超时,再读取键值,实现按键消抖 */
73         irq_pd = (struct pin_desc*)pin_dc;
74         mod_timer(&buttons_timer, jiffies+HZ/100);        //修改定时器超时时间,启动定时器
75
76         return IRQ_RETVAL(IRQ_HANDLED);
77 }
78
79
80 static int myKey_open(struct inode *inode, struct file *file)
81 {
82         /*
83          *当原子变量为1时,驱动程序处于空闲状态,可被打开,否则打开失败并返回
84          */
85         if (!atomic_dec_and_test(&canOpen))        //atomic_dec_and_test――原子变量自减,结果为0返回ture,否则返回false                                                
86         {
87                                                                 //atomic_inc――原子变量自加
88                 atomic_inc(&canOpen);        //恢复原子变量为原来值
89                 return -EBUSY;
90         }
91
92         request_irq(IRQ_EINT0, handle_buttons, IRQT_BOTHEDGE, "S2", &pins_desc[0]);
93         request_irq(IRQ_EINT2, handle_buttons, IRQT_BOTHEDGE, "S3", &pins_desc[1]);
94         request_irq(IRQ_EINT19, handle_buttons, IRQT_BOTHEDGE, "S5", &pins_desc[2]);
95         
96         return 0;
97 }
98
99
100 static int myKey_close(struct inode *inode, struct file *file)
101 {
102         atomic_inc(&canOpen);        //关闭驱动,恢复原子变量默认值
103
104         free_irq(IRQ_EINT0, &pins_desc[0]);
105         free_irq(IRQ_EINT2, &pins_desc[1]);
106         free_irq(IRQ_EINT19, &pins_desc[2]);
107
108         return 0;
109 }
110
111 int myKey_fasync(int fd, struct file *filp, int on)
112 {        
113         printk("driver: fasync_initn");
114         fasync_helper(fd, filp, on, &button_fasyncq);
115
116         return 0;
117 }
118
119 static ssize_t myKey_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
120 {
121         //无中断进入休眠
122         //wait_event_interruptible(button_waitq, ev_press);
123
124         //ev_press = 0;        //清除中断发生标志
125         copy_to_user(buf, &keyVal, 1);
126         return 0;
127 }
128
129
130 void handle_buttons_timer(unsigned long data)
131 {
132         unsigned int kval;
133         struct pin_desc *pinDesc = irq_pd;
134
135         //定时器初次初始化完成,超时处理,此时并未发生过按键中断
136         if (!pinDesc)
137         {
138                 return;
139         }
140
141         kval = s3c2410_gpio_getpin(pinDesc->pin);
142         if (kval)        //松开
143         {
144                 keyVal = 0x80 | pinDesc->key_val;
145         }
146         else {                //按下
147                 keyVal = pinDesc->key_val;
148         }
149
150         //唤醒休眠进程
151         //ev_press = 1;        //中断发生标志
152         //wake_up_interruptible(&button_waitq);
153
154         kill_fasync(&button_fasyncq, SIGIO, POLL_IN);
155 }
156
157
158 static int __init myKey_init(void)
159 {
160         /* 初始化定时器 */
161         init_timer(&buttons_timer);
162         buttons_timer.expires = 0;        //设置定时器超时,默认初始化完成后进入休眠
163         buttons_timer.function = handle_buttons_timer;        //注册定时器超时处理函数
164         add_timer(&buttons_timer);
165
166         /* 物理地址映射成虚拟地址 */
167         gpfcon = (volatile unsigned long*)ioremap(0x56000050, 16);
168         gpfdat = gpfcon + 1;
169
170         gpgcon = (volatile unsigned long*)ioremap(0x56000060, 16);
171         gpgdat = gpgcon + 1;
172
173         major = register_chrdev(0, "myKey", &myKey_fops);
174         
175         myKey_class = class_create(THIS_MODULE, "myKeyclass");
176         myKey_class_dev = class_device_create(myKey_class, NULL, MKDEV(major, 0), NULL, "myKey");
177
178         return 0;
179 }
180
181 static void __exit myKey_exit(void)
182 {
183         /* 释放虚拟地址映射 */
184         iounmap(0x56000050);
185         iounmap(0x56000060);
186
187         unregister_chrdev(major, "myKey");
188
189         class_device_unregister(myKey_class_dev);
190         class_destroy(myKey_class);
191         return;
192 }

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

    常我们采用软件延时的方法就可以解决抖动问题。 1、单片机中按键消抖程序 1.1 单片机中,比如 STM32 中,一般的方法(最简单的方法) 软件消抖程序: if(GPIO_ReadInputDataBit(GPIOA......
    key单片机按键抖动; 1 //write by:cyt  2 //Time:2017-2-10  3 //Porject Name:key shake_destory  4 #include  5......
    这些单片机按键设计方案,请拿好,不谢!;在单片机系统里,按键是常见的输入设备,在本文中介绍几种按键硬件、软件设计方面的技巧。一般的在按键的设计上,一般有四种方案。 一是GPIO口直接检测单个按键......
    工程师。这个必须掌握。(下文将介绍)。 第二个就是“分层屏蔽的设计思想”即分层思想。下面用扫描键盘程序例子作为引子,引出今天说的东西。 问题的提出 单片机学习板一般为了简单起见,将按键分配的很好,例如......
    实验知道,这个一时间大概在5-10ms。所在在做单片机与按键相关的系统时必须考虑消抖的环节。按键消抖的方法有两种,一个是硬件方法 一个是软件的方法,而从节约成本和尽量简化硬件电路的角度出发,一般是采用在程序中加上消抖......
    根线,我们将 这 8 根线连接到单片机的 8 个 I/O 口上,通过程序扫描键盘就可检测 16 个 键。 矩阵按键的消抖 1.检查按键是否按下 由原理图可知,独立按键和矩阵按键是有所不同的。独立按键的各个按键......
    被按下 { delay_ms(2);//按键消抖 ......
    (2);//按键消抖 ......
    51单片机制作简易电风扇定时控制器;自己的床头风扇的机械定时器坏掉了,准备51单片机给设计了一个.程序在实验板初步调试通过,等待元件寄到就可以做板子了,只是有点浪费单片机的资源。 一,设计......
    ,非常实用。下面,我们将详细介绍如何在STM32单片机上实现一个按键切换两个程序。一、 STM32单片机按键切换原理为了实现按键切换两个程序,我们首先需要了解STM32单片机按键的工作原理。STM32......

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>