通常按键所用的开关都是机械弹性开关, 当机械触点断开, 闭合时, 由于机械触点的弹性作用, 一个按键开关在闭合时不会马上就稳定的接通, 在断开时也不会一下子彻底断开, 而是在闭合和断开的瞬间伴随了一连串的抖动, 如图 1 所示.
分析
按键稳定闭合时间长短是由操作人员决定的, 通常都会在 100ms 以上, 刻意快速按的话能达到 40-50ms 左右, 很难再低了. 抖动时间是由按键的机械特性决定的, 一般都会在 10ms 以内, 为了确保程序对按键的一次闭合或者一次断开只响应一次, 必须进行按键的消抖处理.
方法一
在绝大多数情况下, 我们是用软件即程序来实现消抖的. 最简单的消抖原理, 就是当检测到按键状态变化后, 先等待一个 10ms 左右的延时时间, 让抖动消失后再进行一次按键状态检测, 如果与刚才检测到的状态相同, 就可以确认按键已经稳定的动作了. 实际应用中, 这种做法局限性大 (实时性差).
方法二
启用一个定时中断, 每 2ms 进一次中断, 扫描一次按键状态并且存储起来, 连续扫描 8 次后, 看看这连续 8 次的按键状态是否是一致的. 8 次按键的时间大概是 16ms, 这 16ms 内如果按键状态一直保持一致, 那就可以确定现在按键处于稳定的阶段, 而非处于抖动的阶段, 如下图 2 所示.
代码片
- // 外部中断触发 (下降沿)
- void EXTI15_10_IRQHandler(void)
- {
- if ( RESET != EXTI_GetFlagStatus( EXTI_Line5 ) )
- {
- static u32 lasttime = 0;
- if( (g_tickCount - lasttime)> 100 )
- {
- T_1min_cnt = TIM2OpenTime;
- TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
- lasttime = g_tickCount;
- }
- EXTI_ClearITPendingBit( EXTI_Line5 );
- }
- }
- /* Tim2 部分中断服务函数 */
- void TIM2_IRQHandler(void)//250us
- {
- if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
- {
- T_250us_cnt++;
- if ( T2_250us_cnt>= 8 )//2ms IRQ
- {
- T2_250us_cnt = 0;
- static u8 Keybuf1 = 0xff,WG_AKeyBuf = 0xff;
- Keybuf1 = ( ( Keybuf1 << 1 ) | GPIO_ReadInputDataBit(GPIOG,GPIO_Pin_5) );// 缓存区左移 1 位, 并将当前值移入最低位
- if ( 0x00 == Keybuf1 )// 连续 8 次扫描都为 0, 即 16 毫秒内都检测到按下状态, 即认为按键按下
- {
- Key1Sta = 0;
- }
- else if ( 0xff == Keybuf1 )// 按键弹起
- {
- Key1Sta = 1;
- }
- else// 其它情况则说明按键状态尚未稳定, 则不对 KeySta 变量值进行更新
- //Key1Sta = 1;//default value
- }
- TIM_ClearITPendingBit(TIM2 , TIM_FLAG_Update);
- }
- }
来源: http://www.bubuko.com/infodetail-3133182.html