赞
踩
按键消抖:使用定时器每10ms的中断来实现消抖,因为按键的抖动查不到在5-10ms之间,所以使用定时器跳过这10ms的抖动
按键的单按键,双击按键和长按键使用定时器轮询4个按键+状态机的方式实现
使用定时器6来实现每10ms轮询4个按键
开启定时器中断
- struct key
- {
- uint8_t keyJudge; //按键状态机的状态
- bool keyState; //按键电平状态
- bool keySingle; //单击按键
- bool keyDouble; //双击按键
- bool keyLong; //长按按键
- int keyTime; //用于按键计时
- bool keyUp; //检测按键抬起的一瞬间,可用于长按抬手盘判断
- bool keyDown; //检测按键按下的一瞬间
- };
-
- //按键初始化
- struct key keys[4] = {{0,1,0,0,0,0,0,0},{0,1,0,0,0,0,0,0},{0,1,0,0,0,0,0,0},{0,1,0,0,0,0,0,0}};
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//定时器的中断回调处理函数
- {
- if(htim->Instance == TIM6)
- {
- //每10ms获取一次按键状态
- keys[0].keyState = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
- keys[1].keyState = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
- keys[2].keyState = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
- keys[3].keyState = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
-
- //使用for循环轮询4个按键
- for(int i = 0;i<4;i++)
- {
- switch(keys[i].keyJudge) //每个按键所处的状态
- {
- case 0: //按键空闲状态:等待按键按下
- {
- if(keys[i].keyState==0) //按键按下,进入下一个状态
- {
- keys[i].keyJudge=1;
- }
- }
- break;
- case 1: //按键按下消抖状态
- {
- if(keys[i].keyState==0) //确认按键按下,进入下一个状态
- {
- keys[i].keyJudge = 2;
- }else{
- keys[i].keyJudge = 0; //按键抖动,回到上一个状态
- }
- }
- break;
- case 2: //判断是否是长按键
- {
- if(keys[i].keyState==0)
- {
- keys[i].keyTime++; //按键按下时,每10ms加1
- if(keys[i].keyTime>=100) //按键长按超过1s(10ms*100),确认是长按键
- {
- keys[i].keyLong = 1;
- keys[i].keyJudge=0;
- keys[i].keyTime=0;
- }
- }else{ //按键松手
- keys[i].keyJudge=3;
- }
- }
- break;
- case 3: //判断是单击还是双击
- {
- if(keys[i].keyState==1) //如果按键确认松手,进入下一个状态
- {
- if(keys[i].keyTime<100)
- {
- keys[i].keyTime=0;
- keys[i].keyJudge=4;
- }
- }else{ //按键抖动,回到上一个状态
- keys[i].keyJudge=2;
- }
- }
- break;
- case 4: //判断是单击还是双击的状态
- {
- if(keys[i].keyState==1)
- {
- keys[i].keyTime++; //按键松手是开始计时
- if(keys[i].keyTime>=40) //如果松手超过400ms还没有再次按下按键
- {
- keys[i].keySingle=1; //单击按键标志位置1
- keys[i].keyJudge = 0;
- keys[i].keyTime = 0;
- }
- }else{ //在400ms内检测到按键再次按下,进入下一个状态
- keys[i].keyJudge = 5;
- }
- }
- break;
- case 5: //按键二次按下消抖
- {
- if(keys[i].keyState==0)
- {
- if(keys[i].keyTime<40) //确认是双按键或者长按,进入下一个状态
- {
- keys[i].keyTime = 0;
- keys[i].keyJudge = 6;
- }
- }else{ //按键抖动,回到上一个状态
- keys[i].keyJudge = 4;
- }
- }
- break;
- case 6: //按键第二次按下判断是否是长按
- {
- if(keys[i].keyState==0)
- {
- keys[i].keyTime++;
- if(keys[i].keyTime>=100) //按键按下超过1s,这次按键操作归为长按
- {
- keys[i].keyLong = 1;
- keys[i].keyJudge=0;
- keys[i].keyTime=0;
- }
- }else{ //按键松手
- keys[i].keyJudge = 7;
- }
- }
- break;
- case 7: //按键松手消抖
- {
- if(keys[i].keyState==1) //按键确认松手
- {
- if(keys[i].keyTime<100) //按键不是长按键,则是双击按键
- {
- keys[i].keyDouble = 1;
- }
- keys[i].keyJudge = 0;
- keys[i].keyTime = 0;
- }else{
- keys[i].keyJudge = 6;
- }
- }
- break;
-
- }
- }
- }
- }
-
- //main函数测试三个按键模式
- if(keys[3].keySingle) //单击,LED1点亮
- {
- LED1_ON;
- keys[3].keySingle = 0;
- }
- if(keys[3].keyDouble) //双击,LED1熄灭
- {
- LED1_OFF;
- keys[3].keyDouble = 0;
- }
- if(keys[3].keyLong) //长按,LED1不断翻转
- {
- LED1_TOGGLE;
- keys[3].keyLong = 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。