按键是非常常用的小外设,要么配上外部中断,要么直接接I/O口扫描状态,我这边因为端口不够就用了ADC功能。
先讲短按
每个按键对应不同的电压值,没有按键按下时ADC输入通道接的是5V,按下之后我设计了以下几种情况:
1.SW1 0V
2.SW2 2.5V
3.SW3 3.3V
4.SW4 3.8V
理论上配置完ADC模块,开启ADC转换,在每次ADC转换完成触发中断的时候就可以根据采集值确认按键是哪个了。
但是存在一个问题,比如说我按下ESC键,电压下降是一个过程,如果它下降到3.3v的时候一次采集就完成,那采集的值不就错了吗。
所以需要消抖,我这里消抖的方式是这样:
关于短按:
1.设置一个大小为2的数组KEY[2]
2.KEY[0]用于存最新的值,KEY[1]用于缓存上一次的值
3.如果有键按下,如果KEY[0]和KEY[1]之间的差值(无论哪个大)大于100(这个数可根据不同的ADC采样的精度自己调整),则代表按键并不稳定
4.将KEY[1]的值更新为KEY[0],等待下一次中断
5.直到KEY[1]和KEY[0]的差值小于100,代表按键稳定,可进行按键状态判断(此处置一个状态稳定flag)
6.等到按键松开时进行keystatus按键状态的修改
关于长按:
我在SW2这个按键上做了简单的长按功能
1.设置一个keylong做累加统计,一个keylong_flag作为进入长按状态的标志
2.当采集值稳定在SW2的范围时(不必等检测到按键松开)keylong++
3.当keylong的值大于设定(比如500)且keylong_flag==0(第一次进入长按)时,keystatus切换为SW2,并且将keylong清零,keylong_flag=1
4.第二次进入长按时,可将keylong的比较值设定小一些,让长按带来的效果切换更好一些
5.一旦按键松开,将keylong和keylong_flag清零
具体代码如下:
这个是从我自己写的项目中摘抄的部分,本来还有一些处理,但是和这个内容无关就删去了