完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
电子发烧友论坛|
|
|
相关推荐
1个回答
|
|
|
思路:利用定时器间隔扫描按键驱动函数,定时器间隔时间则可以作为消抖时间,从而实现消抖过程而不用延时函数消抖。比如定时器设计5MS中断一次:2次中断则检测一次按键值,若按键值不为0xff(根据经验06章节讲的按键延时消抖方法设计的按键编码来更改的,按键没有按下则值为0xff,按下的话返回对应的按键编码值:0 - 4)则存取按键值为第一次按键扫描值,进入第二层状态,否则还是继续间隔扫描,检测按键值不为0xff时再存入按键值;在第二层状态中:再过两次中断(10MS)再次扫描按键,如果此次按键值等于第一次按键扫描值,则确定了有按键按下,进入第三层状态;在第三层状态中:再过两次中断判断按键有无松开,若是没有,则累加计时,若计时超过长按时间(自己设置的多久算长按),则做一个变量累加计时,这个计时则是判断长按多久要设置加的值快速加一,若按键松开,则判断计时时间是否小于按键长按时间,若小于长按时间则算是短按。 --总结:其实按键状态机无非就是依靠多个标志变量判断当前按键所处状态,对于有时许处理要求的任务来说,状态设计一定是重点。
#define RB1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) #define RB2 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8) #define RB3 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) #define RB4 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_2) typedef struct{ u8 KEY_VALUE; //使用数据后及时清除到 0xff !!! JUDGE_ENUM IS_Key_ShortPress; //使用数据后及时清除到FAUSE状态!!! JUDGE_ENUM IS_Key_LongPress; //判断长按否? 不需要人为清除 JUDGE_ENUM IS_Key_LongFresh; //长按刷新,长按多久按键计算快速累加或累减一次使用数据后及时清除到FAUSE状态!!!! JUDGE_ENUM IS_Key_Touch; //按键是否按下 }KEYSCANF_TypeDef; extern KEYSCANF_TypeDef KEYSCANF_Structure; /********************当前设置的按键扫描中断为 5MS************/ #define KEY_LONGSTATUS_Time 800000/GENERAL_TIM_SetUs // 多久算长按 #define KEY_EliShaking_Time 10000/GENERAL_TIM_SetUs // 按键消抖值 #define Key_LongTimeSet 100000/GENERAL_TIM_SetUs //按键长按后多久更新一次 比如长按后加一,本设置为多久加一
/** * @说明 按键编码函数 * @参数 none * @返回值 0xff ; 1 - 4 */ uint8_t Key_Scan(void) { uint8_t key_value = 0xff; if(RB1 == 0){ key_value = 1; } if(RB2 == 0){ key_value = 2; } if(RB3 == 0){ key_value = 3; } if(RB4 == 0){ key_value = 4; } return key_value; } /** * @说明 按键状态机函数 * @参数 none * @返回值 None * @注意 1.按键状态机只做出 状态, 但不消除状态 2.KEYSCANF_Structure.KEY_VALUE ,KEYSCANF_Structure.IS_Key_ShortPress 被使 用后需要人为复位0xff,FAUSE,这样才能保证每一次的状态都能被处理 3.Key_Interrup()函数需要放入定时器中断,且中断时间小于10MS,最好为10的公约数:如1,2,5MS 例程: @1: 按键初始化放入main.c @2: 中断放入函数 extern void Key_Interrup(void); void TIM4_IRQHandler(void) { Key_Interrup(); } @3:按键处理函数 void KEY_Proc(void) { static u8 i = 0; if(KEYSCANF_Structure.KEY_VALUE != 0xff) // There are remaining parking spaces { switch(KEYSCANF_Structure.KEY_VALUE) { case 1: if(KEYSCANF_Structure.IS_Key_ShortPress == TRUE) { KEYSCANF_Structure.IS_Key_ShortPress = FAUSE; //!!!手动清除短按标志位 短按处理自制函数(); } break; case 2: if(KEYSCANF_Structure.IS_Key_LongPress == TRUE) { 长按处理自制函数(); } break; case 3: if(KEYSCANF_Structure.IS_Key_LongPress == TRUE) { if(KEYSCANF_Structure.IS_Key_LongFresh == TRUE) { KEYSCANF_Structure.IS_Key_LongFresh = FAUSE; //手动清除快速按键刷新标志位 长按处理快速累加/累减自制函数(); } } break; } KEYSCANF_Structure.KEY_VALUE = 0xff; //在此清除的目的在于 不至于在状态机中有按键值,而在按键处理函数检测时已经被状态机刷新销毁,上面switch判断后才能清除! } } * @包含出处 #include "bsp_key_statemachine.h" */ u8 keyCheck = 0; uint8_t keyState = 0; uint16_t keyPrev = 0xff; //上一次的键值 u32 keyLongCheck = 0; u16 Key_LongTime = 0; u8 keyCountTime = 0; KEYSCANF_TypeDef KEYSCANF_Structure = {0xff,FAUSE,FAUSE,FAUSE,FAUSE}; void Key_Interrup(void) { uint8_t keyPress = 0xff; keyCountTime ++; if(keyCountTime >= KEY_EliShaking_Time) //消抖完成 { keyCountTime = 0; keyCheck = 1; } if(keyCheck == 1) { keyCheck = 0; keyPress = Key_Scan(); switch(keyState) { case 0://按键未按下态 if(keyPress != 0xff)//表示有按键按下 { keyPrev = keyPress; //记录当前按键状态 keyState = 1; } else { keyState = 0; } break; case 1://表示有按键按下,判断当前值和上一次的值是否一样,若不一样则为抖动! if(keyPress == keyPrev)//不是抖动 { keyState = 2; }else{ keyState = 0; //是抖动!返回上一层 keyPrev = 0xff; } break; case 2: if(keyPress != keyPrev)//表示按键已松开,只有长按状态被清除,长按计时结束,短按状态不清除,等待用户使用并清除 { if(keyLongCheck < KEY_LONGSTATUS_Time) //短按 { KEYSCANF_Structure.IS_Key_ShortPress = TRUE; KEYSCANF_Structure.KEY_VALUE = keyPrev; } KEYSCANF_Structure.IS_Key_LongPress = FAUSE; keyPrev = 0xff; keyState = 0; // 按键结束返回初始状态机 keyLongCheck = 0; //长按计时清0 Key_LongTime = 0; }else{ keyLongCheck++; if(keyLongCheck >= KEY_LONGSTATUS_Time)//按下时间超过 长按时间 { if(KEY_LONGSTATUS_Time > 65535) keyLongCheck = KEY_LONGSTATUS_Time; KEYSCANF_Structure.KEY_VALUE = keyPrev;//返回值标记哪个按键 KEYSCANF_Structure.IS_Key_ShortPress = FAUSE; KEYSCANF_Structure.IS_Key_LongPress = TRUE; } } break; default : break; } } if(KEYSCANF_Structure.IS_Key_LongPress == TRUE) //按键长按 刷新,进行长按快速累减或累加使用 { Key_LongTime ++; if(Key_LongTime >= Key_LongTimeSet) { Key_LongTime = 0; KEYSCANF_Structure.IS_Key_LongFresh = TRUE; } } } |
|
|
|
|
只有小组成员才能发言,加入小组>>
1599 浏览 0 评论
imx6ull 和 lan8742 工作起来不正常, ping 老是丢包
4738 浏览 0 评论
4229 浏览 9 评论
3822 浏览 16 评论
4398 浏览 1 评论
4210浏览 3评论
2379浏览 0评论
3393浏览 0评论
1158浏览 0评论
2843浏览 0评论
/9
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-12-2 02:18 , Processed in 0.741210 second(s), Total 74, Slave 54 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖
1827