使用定时器进行按键消抖

.如何消去按键抖动

通过定时器延时10ms,然后每当按键进入中断时就更新定时器延时10ms,若延时10ms到了说明已经过了抖动范围,然后再打印按键电平信息

两个全局变量:

jiffies: 是系统时钟,全局变量,默认每隔10ms加1

HZ:是每S的频率,通过系统时钟换算出来,比如每隔10ms加1,那么HZ就等于100,

1s等于HZ,jiffies+HZ/100意思jiffies+1s/100=jiffies+1000ms/100 =jiffies+10ms所以每个10s加一

.定时器结构体和函数介绍

定时器结构体timer_list:

timer_list常用结构体成员

(1)data         //传递到*function超时处理函数的参数,可以通过参数来获取信息
(2)expires     //定时器到期的时间,当expires小于等于jiffies时,这个定时器便到期并调用定时器超时处理函数,然后就不会再调用了,
                     比如要使用10ms后到期,赋值(jiffies+HZ/100)即可
(3)void (*function)(unsigned long)     //定时器超时处理函数。

定时器常用函数:

init_timer(struct timer_list*) //定时器初始化结构体函数,

add_timer(struct timer_list*) //往系统添加定时器,告诉内核有个定时器结构体

mod_timer(struct timer_list *, unsigned long jiffier_timerout) //修改定时器的超时时间为jiffies_timerout,

                                                                                               当expires小于等于jiffies时,便调用定时器超时处

imer_pending(struct timer_list *) //定时器状态查询,如果在系统的定时器列表中则返回1,否则返回0;

del_timer(struct timer_list*) //删除定时器,在本驱动程序出口函数sixth_drv_exit()里添加

修改驱动程序实现定时器消抖动

1首先定义一个定时器结构体:

static struct timer_list buttons_timer; //定义定时器结构体

2在init入口函数中初始化定时器结构体:

init_timer(&buttons_timer); //初始化结构体

/*成员.data未使用

不需要定时器到期时间,所以成员.expires无需初始化,默认为0,由于小于等于jiffies,会进入一次定时器超时函数*/

buttons_timer. function= buttons_timer_ function;

add_timer(&buttons_timer); //告诉内核,有一个定时器

在exit出口函数中删除定时器:

del_timer(&buttons_timer); //删除定时器

4定义全局变量*irq_dev_id,然后在中断服务函数中获取dev_id

struct pin_desc *irq_dev_id ; //定义全局变量获取dev_id

修改中断服务函数:

static irqreturn_t buttons_irq (int irq, void *dev_id) //中断服务函数

{

       irq_dev_id =(struct pin_desc *)dev_id; //获取引脚描述结构体

       /*每产生一次中断,则更新定时器10ms超时 */

       mod_timer(&buttons_timer, jiffies+HZ/100);

        return IRQ_RETVAL(IRQ_HANDLED);

}

5当10ms超时到了,进入定时器超时函数,处理*irq_dev_id来判断是哪个按键按下的

static void buttons_timer_function(unsigned long data) //定时器超时函数

{

             unsigned int pin_val=0;

              if(!irq_dev_id) //初始化时,由于定时器.expires成员=0,会进入一次,若irq_dev_id为0则退出

             {

                    printk("expires: timer out\n");

                  return ;

              }

            pin_val=s3c2410_gpio_getpin(irq_dev_id->pin); //获取按键值

           if(pin_val)

           {                   /*按下 (下降沿),清除0x80*/

                           key_val=irq_dev_id->pin_status&0xef;

      }
      else
      {      
                 /*没有按下(上升沿),加上0x80*/
                   key_val=irq_dev_id->pin_status|0x80;
       }
       even_press=1;                                        //退出等待队列
       wake_up_interruptible(&button_wait);                //唤醒 中断
       kill_fasync(&button_async, SIGIO, POLL_IN);        //发送SIGIO信号给应用层
}

 

 

 

 

 

 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在STM32中,我们可以使用定时器中断来实现按键消抖。具体的实现步骤如下: 1. 配置GPIO引脚为输入模式,并使能GPIO时钟。 2. 配置定时器,使其以一定的频率产生中断。在定时器中断服务函数中,检测GPIO引脚的状态,并进行消抖操作。 3. 消抖操作可以通过设置一个计数器来实现。如果检测到GPIO引脚状态发生变化,就将计数器清零,并重新开始计数。只有当计数器达到一定的阈值后才认为按键已经被按下。 下面是一个简单的示例代码,仅供参考: ```c #include "stm32f10x.h" #define KEY_GPIO_PIN GPIO_Pin_0 #define KEY_GPIO_PORT GPIOA #define KEY_GPIO_CLK RCC_APB2Periph_GPIOA #define DEBOUNCE_COUNT 10 static uint16_t keyState = GPIO_Pin_0; static uint16_t debounceCount = 0; void TIM2_IRQHandler(void) { if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { // Clear the interrupt flag TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // Read the key state uint16_t state = GPIO_ReadInputDataBit(KEY_GPIO_PORT, KEY_GPIO_PIN); // Debounce the key if (state == keyState) { debounceCount = 0; } else { debounceCount++; if (debounceCount >= DEBOUNCE_COUNT) { keyState = state; debounceCount = 0; } } } } int main(void) { // Enable GPIO clock RCC_APB2PeriphClockCmd(KEY_GPIO_CLK, ENABLE); // Configure GPIO as input with pull-up GPIO_InitTypeDef gpio; gpio.GPIO_Pin = KEY_GPIO_PIN; gpio.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(KEY_GPIO_PORT, &gpio); // Enable TIM2 clock RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // Configure TIM2 for 1ms interrupt TIM_TimeBaseInitTypeDef tim; tim.TIM_Period = 999; tim.TIM_Prescaler = SystemCoreClock / 1000000 - 1; tim.TIM_ClockDivision = TIM_CKD_DIV1; tim.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &tim); // Enable TIM2 update interrupt TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); // Start TIM2 TIM_Cmd(TIM2, ENABLE); // Enable TIM2 interrupt NVIC_EnableIRQ(TIM2_IRQn); while (1) { // Do something else } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值