布景
只需运用单片机,按键检测基本上是一定要完成的功用。按键检测要好用,最重要的是实时和去抖。初学者往往会在主循环调用按键检测程序(实时)并使用延时去抖(精确)。这种在主循环内延时的做法对整个程序十分不友好,也十分不高效。因而,本篇就我自己完成的一个检测按键并可判别按键是否长短按的程序做个介绍和记载。
正文
在硬件衔接上,按键一端衔接在一般IO口上,另一端接地,IO装备为内部弱上拉。
在软件上,先装备一个5ms守时器并翻开中止,每进入该守时中止则置位一次标志位“key_handle”。接着在主循环调用一个“scan_key()”函数,判别“key_handle”标志位是否在守时器内被置位,若被置位则将该位复位并读取衔接按键的IO口值。
此刻,“scan_key()”函数内分为按键按下和松开两个分支:
按键按下,则计数值“longkey”每隔5ms自加一次,因为这个分支每隔5ms才会进入履行一次;
按键铺开,则先判别“longkey”的值,若“longkey”的值换算出来代表按键按下时刻在10ms-1s内,(10ms是去抖值,1s是与短按与长按的分界点。)则判别按键为短按;若“longkey”的值大于1s,则判别按键为长按。并将按键状况赋值给按键状况变量“keybuf”。一起,因为此刻按键现已铺开,因而“longkey”的值要置位“0”等候用户下次按下按键并履行从“0”开端的自加操作。
若程序又一次进入按键检测代码段,阐明一切功用块代码现已获悉key状况,有对key感兴趣的代码段也必定现已进行过相应处理,因而此刻要及时将“keybuf”置为无按键按下状况以此来同步实践按键状况。
实践代码如下:
void scan_key(void){ unsigned char key_status;
if((longkey == 0) (keybuf != _KEYNULL)){ // 在keybuf被标记为长按或短按后,若是按键现已松开,
// 则在主循环跑完一次后,及时将按键状况标记为无按键按下。
keybuf = _KEYNULL;
} if(key_handle == _ON) { //5ms进入一次
key_handle = _OFF; // 复位5ms标志位
key_status = GPIO_ReadInputDataBit(KEYRESET_GPIO_PORT, KEYRESET_GPIO_PIN); if(key_status == 0) { //按下按键
longkey++;
} else { // 松开按键
if((longkey >= 3) (longkey = 100) ){ // 15ms – 1s
keybuf = _SHORTKEY;
} else if(longkey >= 200) { // 2s
keybuf = _LONGKEY;
} else {
keybuf = _KEYNULL;// 若为扰动,按键状况也该为无按键按下
}
longkey = 0;
}
}
}
弥补:
和Tony~Liu评论了下,发现其实还有功率更高,占用CPU更少的按键检测方法。
在硬件上,按键衔接在具有外部中止的IO口上,按键衔接在该IO口上的脚外部上拉,按键另一端接地。
在软件上,衔接按键的IO口装备为双边缘中止,一起装备一个1ms守时器中止。当按键按下时,触发外部中止,在外部中止内判别IO口电平,以此确认此为上升沿仍是下降沿。下降沿则代表按键按下,开端计时,上升沿则代表按键松开,中止计时。上升沿中止时,在中止内置位“key_handle”,主循环在判别到“key_handle”被置位后,则开端判别计时器时刻,若是时刻在10ms-1s内,(10ms是去抖值,1s是与短按与长按的分界点。)则判别按键为短按;若时刻大于1s,则判别按键为长按。详细施行也很简单,在此就不再贴代码,仅仅说说这种思维。
至此,记载结束
- STM32单片机中文官网
- STM32单片机官方开发工具
- STM32单片机参阅规划