用定时器去除按键抖动

发布者:SerendipityLove最新更新时间:2025-02-14 来源: cnblogs关键字:定时器 手机看文章 扫描二维码
随时随地手机看文章

首先,我们要先搞明白两个问题:


1. 为什么要去抖动?


    按键所用开关为机械弹性开关,当机械触点断开,闭合时,由于机械触点的弹性作用,开关不会马上稳定地接通或者断开。因而在闭合及断开的瞬间总是伴随一连串的抖动。


2. linux中为什么要用定时器去抖?


    按键去抖动的方法主要有两种,一是硬件电路去抖动;另一种是软件延时去抖。而延时又一般分为两种,一种是for循环等待,另一种是定时器延时。在操作系统中,由于效率方面的原因,一般不允许使用for循环来等待,只能使用定时器。


定时器是用来流程:


1. 定义定时器变量


 1 使用struct timer_list结构定义一个定时器变量,

 2 struct timer_list {

 3     /*

 4      * All fields that change during normal runtime grouped to the

 5      * same cacheline

 6      */

 7     struct list_head entry;

 8     unsigned long expires;     //设置定时器超时时间

 9     struct tvec_base *base;

10 

11     void (*function)(unsigned long);   //定时器超时处理函数

12     unsigned long data;

13 

14     int slack;

15 

16 #ifdef CONFIG_TIMER_STATS

17     int start_pid;

18     void *start_site;

19     char start_comm[16];

20 #endif

21 #ifdef CONFIG_LOCKDEP

22     struct lockdep_map lockdep_map;

23 #endif

24 };

例:struct timer_list key_timer;


2. 初始化定时器


1 初始化定时器有两步:

2 1. init_timer;

3 2. 设置超时函数。

4 例:init_timer(&key_timer);

5       key_timer.function = key_timer_func;

 

3. add_timer注册定时器


 1 例:  add_timer(&key_timer); 


4. mod_timer启动定时器


1 例: 

2  /*jiffies为全局变量,表示当前的时间,在linux系统中1秒中有1000滴答,

3    即1秒jiffies增加1000,HZ代表一秒*/          

4     mod_timer(&key_timer, jiffies + 1*HZ);

 


以下为带定时器去抖的按键中断驱动程序


  1 #include

  2 #include

  3 #include

  4 #include

  5 #include

  6 #include

  7 #include   

  8 #include   

  9 #include

 10 

 11 #define GPH2CON 0xe0200c40

 12 #define GPH2DAT 0xe0200c44

 13 

 14 struct timer_list key_timer;

 15 unsigned *gpio_data;

 16 

 17 irqreturn_t key_irq(int irq, void * dev_id)

 18 {

 19     //1. 检测是否发生了按键中断

 20     

 21     

 22     //2. 清除已经发生的按键中断

 23     

 24     

 25     //3. 打印按键值

 26     

 27     /*启动定时器*/

 28     mod_timer(&key_timer, jiffies + HZ/50); //超时为20ms

 29     

 30     return 0;

 31 }

 32 

 33 

 34 /*超时函数*/

 35 void key_timer_func(unsigned long data)

 36 {

 37     key_val = readl(gpio_data) & 0x01;

 38         if(key_val == 0)

 39             printk('key_down!n');

 40 }

 41 

 42 

 43 int key_open (struct inode *inode, struct file *filp)

 44 {

 45     return 0;

 46 }

 47 

 48 

 49 void key_hw_init()

 50 {

 51     //unsigned int data; 

 52     unsigned int *gpio_config;

 53     unsigned int key_val;

 54     

 55     gpio_config = ioremap(GPH2CON, 4);

 56     data = readl(gpio_config);

 57     data &= ~0b1111;

 58     data |= 0b1111;

 59     writel(data,gpio_config);

 60     

 61     gpio_data = ioremap(GPH2DAT, 4);   

 62 }

 63 

 64 

 65 struct file_operations key_fops =

 66 {

 67         .open = key_open,

 68 };

 69 

 70 

 71 struct miscdevice key_miscdevice =

 72 {       

 73     /*MISC_DYNAMIC_MINOR代表动态分配次设备号,即由系统自动分配*/

 74     .minor = MISC_DYNAMIC_MINOR,

 75     .name = 'key_miscdev',

 76     .fops = &key_fops,

 77 };

 78 

 79 

 80 static int key_init()

 81 {

 82     /*注册混杂设备*/

 83     misc_register(&key_miscdevice);

 84     

 85     /*申请中断,如果内核中已有按键中断驱动,则需要把arch/arm/mach-s5pv210/mach-mini210.c文件的gpio_buttons定义的相关按键去掉,

 86      不然板子上的按键中断就已经被占用,不能注册中断*/

 87     /*注意:中断号这个参数应该用gpio_to_irq(S5PV210_GPH2(0)),假如用了IRQ_EINT16_31则按键驱动不会工作,我个人认为是内核代码写错了*/

 88     request_irq(gpio_to_irq(S5PV210_GPH2(0)), key_irq, IRQF_TRIGGER_FALLING, 'key_miscdev', 0);

 89     

 90     /*初始化定时器*/

 91     init_timer(&key_timer);

 92     key_timer.function = key_timer_func;

 93     

 94     /*注册定时器*/

 95     add_timer(&key_timer);

 96     

 97     

 98     return 0;

 99         

100 }

101 

102 

103 static void key_exit()

104 {

105     /*注销设备*/

106     misc_deregister(&key_miscdevice);

107 }

108 

109 

110 MODULE_LICENSE('GPL');

111 

112 module_init(key_init);

113 module_exit(key_exit);


关键字:定时器 引用地址:用定时器去除按键抖动

上一篇:ARM裸编程系列---UART
下一篇:TQ210搭载Android4.0.3系统构建之LED从驱动到HAL到JNI到应用程序(驱动篇)

推荐阅读最新更新时间:2026-03-19 11:22

mini2440 按键驱动添加定时器抖动
测试程序和Makefile同前面的实验一样的,这里只记录一下驱动的源代码就行了,改动不大,就是把唤醒进程和发送异步信号的操作移动到定时器的超时函数里面去了,这样做的目的是为了消除按键的机械抖动。 驱动源代码: #include linux/module.h #include linux/kernel.h #include linux/device.h #include linux/fs.h #include linux/init.h #include linux/delay.h #include linux/interrupt.h #include linux/irq.h #include linux/gp
[单片机]
STM32之系统时基定时器中如何完成按键抖动问题
在按键演示防抖动部分的主要思路是:利用系统定时器溢出间隔中断来延时防抖。这样做可以提高代码的执行效率。我们怎么去很好的利用这个系统定时器来延时呢?如果只是简单在系统定时器中断中置位延时标志位,没有任何意义,我们需要有一个标志位来允许置延时标志。第一次扫描到有按键按下时,延时标志肯定为空,那么在此置位一个标志位,来允许系统定时器中置位延时标志,就解决了这个问题。 软件的逻辑结构是:如果没有延时,则置位允许延时标志置位标志。首先是置位标志位,如果置位了,在系统定时器溢出中断中,就可以置位延时标志位。如果已经置位,处理按键值。 下面给出一个在按键处理中的对延时标志判断的处理。 if(key_bit & 0x02) //如果按键没有被处理
[单片机]
非常稳定可靠的单片机按键消抖程序,绝对不会产生抖动
#include reg52.h #define uint unsigned int #define uchar unsigned char sbit K1 = P1^0; void delay1ms(uint n) { uchar a,b,c,d; for(d=n;d 0;d--) for(c=1;c 0;c--) for(b=222;b 0;b--) for(a=12;a 0;a--); } void main() { uint i; if(K1==0) { delay1ms(10); if(K1==0) // {
[单片机]
按键处理与按键抖动例子
/***************************************************** 本程序的目标是这样的: 1:不使用INTn中断功能,按键接在普通IO上 2:由定时器T/C2每隔一段时间检测按键一次, 并具有防抖动功能 3:每点击按键一次,在按键松开后,变量A=A+1 4:如果按键按下后不放,则每隔 n ms 就做A=A+1运算一次 5:在按键按下期间,CPU除了处理按键外,还必须能正常运行主程序 6:本程序的系统时钟是1MHz *****************************************************/ #include #include #include
[单片机]
AVR单片机按键处理与按键抖动程序
AVR单片机按键处理与按键防抖动程序 #include mega48.h #include delay.h #include nokia3310.h unsigned char A,B; unsigned char n; bit step1, step2, step3,step4; //使用几个位变量记忆按键状态 / #include mega48.h #include delay.h #include nokia3310.h unsigned char A,B; unsigned char n; bit step1, step2, ste
[单片机]
89c51 c语言软件防抖动按键
仿真结果如下: #include reg51.h sbit SI=P1^4; sbit LED0=P3^0; void delay() { unsigned char i,j; for(i=0;i 100;i++) for(j=0;j 100;j++) ; } void main() { LED0=0; while(1) { if(SI==0) { delay(); //延时一段时间 if(SI==0) //再次确认是否有按键按下 LED0=1; //当有按键
[单片机]
MSP430按键采用中断也要消抖动
机械按键都有抖动,所以,为了消除按键的抖动,避免各种干扰引起的抖动产生误操作,所以,消抖就变得尤为重要。 #include "MSP430G2553.h" int ms,k,i; char key=0; void delay(int ms) { while(ms--) { for(i=0;i 120;i++); } } int main( void ) { // Stop watchdog timer to prevent time out reset WDTCTL = WDTPW + WDTHOLD; P1DIR |=BIT6+BIT0;
[单片机]
STM32定时器中断详解(HAL库实战讲解)
1、定时器简单介绍 以STM32F103C8T6中几个定时器为例: TIM1:这是一个高级定时器,不仅具备基本的定时中断功能,还拥有内外时钟源选择、输入捕获、输出比较、编码器接口以及主从触发模式等多种功能。这使得TIM1能够适用于各种复杂的应用场景,为开发者提供强大的时间控制和信号处理能力。 TIM2、TIM3和TIM4:这些是通用定时器,同样具有定时功能,但在功能上与高级定时器有所区别。通用定时器通常用于实现一些基本的定时任务,如LED闪烁、脉冲宽度测量等。 每个定时器都由一个**16位计数器、预分频器和自动重装寄存器的时基单元组成。**预分频器可以对时钟进行分频,计数器则对预分频后的时钟进行计数。当计数器的值达到设定值时,
[单片机]
STM32<font color='red'>定时器</font>中断详解(HAL库实战讲解)
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved