定时器消抖实验

定时器消抖

上一章我们学习了EPIT定时器,定时器设置好定时时间,然后CPU就可以做其他事情去了,定时时间到了以后就会触发中断,然后在中断中做相应的处理即可。因此,我们可以借助定时器来实现消抖,按键采用中断驱动方式,当按键按下以后触发按键中断,在按键中断中开启一个定时器,定时周期为10ms,当定时时间到了以后就会触发定时器中断,最后在定时器中断处理函数中读取按键的值,如果按键值还是按下状态那就表示这是一次有效的按键。

在图19.1.1中t1~t3这一段时间就是按键抖动,是需要消除的。设置按键为下降沿触发,因此会在t1、t2和t3这三个时刻会触发按键中断,每次进入中断处理函数都会重新开器定时器中断,所以会在t1、t2和t3这三个时刻开器定时器中断。但是t1~t2和t2~t3这两个时间段是小于我们设置的定时器中断周期(也就是消抖时间,比如10ms),所以虽然t1开启了定时器,但是定时器定时时间还没到呢t2时刻就重置了定时器,最终只有t3时刻开启的定时器能完整的完成整个定时周期并触发中断,我们就可以在中断处理函数里面做按键处理了,这就是定时器实现按键防抖的原理,Linux里面的按键驱动用的就是这个原理!

1、配置按键IO中断

配置按键所使用的IO,因为要使用到中断驱动按键,所以要配置IO的中断模式。

2、初始化消抖用的定时器

消抖要用定时器来完成,所以需要初始化一个定时器,这里使用上一章讲解的EPIT1定时器,也算是对EPIT1定时器的一次巩固。定时器的定时周期为10ms,也可根据实际情况调整定时周期。

3、编写中断处理函数

需要编写两个中断处理函数:按键对应的GPIO中断处理函数和EPIT1定时器的中断处理函数。在按键的中断处理函数中主要用于开启EPIT1定时器,EPIT1的中断处理函数才是重点,按键要做的具体任务都是在定时器EPIT1的中断处理函数中完成的,比如控制蜂鸣器打开或关闭。

1 #include "bsp_key.h"
2 #include "bsp_gpio.h"
3 #include "bsp_int.h"
4 #include "bsp_beep.h"
5 #include "bsp_keyfilter.h"
6 
7 /*
8 * @description  : 按键初始化
9 * @param  : 无
10 * @return  : 无
11 */
12 void filterkey_init(void)
13 { 
14 gpio_pin_config_t key_config;
15 
16 /* 1、初始化IO */
17 IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0);
18 IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0xF080);
19 
20 /* 2、初始化GPIO为中断 */
21 key_config.direction = kGPIO_DigitalInput;
22 key_config.interruptMode = kGPIO_IntFallingEdge;
23 key_config.outputLogic = 1;
24 gpio_init(GPIO1, 18, &key_config);
25 
26 /* 3、 使能GPIO中断,并且注册中断处理函数 */
27 GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn); 
28 system_register_irqhandler(GPIO1_Combined_16_31_IRQn, 
       (system_irq_handler_t)gpio1_16_31_irqhandler, 
       NULL);
29 
30 gpio_enableint(GPIO1, 18);  /* 使能GPIO1_IO18的中断功能  */
31 filtertimer_init(66000000/100); /* 初始化定时器,10ms    */
32 }
33 
34 /*
35 * @description  : 初始化用于消抖的定时器,默认关闭定时器
36 * @param - value  : 定时器EPIT计数值
37 * @return  : 无
38 */
39 void filtertimer_init(unsigned int value)
40 {
41 EPIT1->CR = 0;  /* 先清零  */
42 EPIT1->CR = (1<<24 | 1<<3 | 1<<2 | 1<<1);
43 EPIT1->LR = value;  /* 计数值   */
44 EPIT1->CMPR = 0;  /* 比较寄存器为0 */
45 
46 /* 使能EPIT1中断并注册中断处理函数*/
47 GIC_EnableIRQ(EPIT1_IRQn); 
48 system_register_irqhandler(EPIT1_IRQn, 
      (system_irq_handler_t)filtertimer_irqhandler, 
       NULL); 
49 }
50 
51 /*
52 * @description : 关闭定时器
53 * @param  : 无
54 * @return  : 无
55 */
56 void filtertimer_stop(void)
57 {
58 EPIT1->CR &= ~(1<<0);  /* 关闭定时器  */
59 }
60 
61 /*
62 * @description : 重启定时器
63 * @param – value : 定时器EPIT计数值
64 * @return  : 无
65 */
66 void filtertimer_restart(unsigned int value)
67 {
68 EPIT1->CR &= ~(1<<0);  /* 先关闭定时器  */
69 EPIT1->LR = value;  /* 计数值  */
70 EPIT1->CR |= (1<<0);  /* 打开定时器  */
71 }
72 
73 /*
74 * @description  : 定时器中断处理函数 
75 * @param  : 无
76 * @return  : 无
77 */
78 void filtertimer_irqhandler(void)
79 { 
80 static unsigned char state = OFF;
81 
82 if(EPIT1->SR & (1<<0))   /* 判断比较事件是否发生  */
83 {
84 filtertimer_stop();    /* 关闭定时器  */
85 if(gpio_pinread(GPIO1, 18) == 0) /* KEY0按下  */
86 {
87 state = !state;
88 beep_switch(state);  /* 反转蜂鸣器  */
89 }
90 }
91 EPIT1->SR |= 1<<0;  /* 清除中断标志位  */
92 }
93 
94 /*
95 * @description  : GPIO中断处理函数
96 * @param  : 无
97 * @return  : 无
98 */
99 void gpio1_16_31_irqhandler(void)
100 { 
101 filtertimer_restart(66000000/100); /* 开启定时器   */
102 gpio_clearintflags(GPIO1, 18);  /* 清除中断标志位  */
103 }

1 #include "bsp_clk.h"
2 #include "bsp_delay.h"
3 #include "bsp_led.h"
4 #include "bsp_beep.h"
5 #include "bsp_key.h"
6 #include "bsp_int.h"
7 #include "bsp_keyfilter.h"
8 
9 /*
10 * @description : main函数
11 * @param : 无
12 * @return : 无
13 */
14 int main(void)
15 {
16  unsigned char state = OFF;
17 
18  int_init();  /* 初始化中断(一定要最先调用!)  */
19  imx6u_clkinit();  /* 初始化系统时钟  */
20  clk_enable();  /* 使能所有的时钟  */
21  led_init();  /* 初始化led   */
22  beep_init();  /* 初始化beep   */
23  filterkey_init();  /* 带有消抖功能的按键    */
24 
25  while(1) 
26  { 
27   state = !state;
28  led_switch(LED0, state);
29  delay(500);
30  }
31 
32  return 0;
33 }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值