一。问题产生的过程
起初想用stm32做一个中断控制的4x4阵列键盘,利用的是PA0~PA7,八个I/O口。摁下按键对应的横(纵)线为接地为低电平。
识别方式为PA4~PA7设为上拉电阻输入,PA0~PA3设为推挽输出并将其复位(设为0)来保证无论对应横线上的按键是否按下恒为低电平。摁下按键后读取八个I/O口的值赋予a,然后将PA4~PA7、PA0~PA3状态翻转再读取八个I/O口的值赋予b,这时只需要将a与上b即可确定按下的是哪个键。然后将识别到的键按键的值显示再LED屏幕上。这时功能是能完全实现的:
由于项目需要让反馈更加明显(按下对应按键需要语音提示),且做出相应动作需要在对应中断函数中完成。于是我将PA4~PA7四个通道设为下降沿触发,中断函数为EXTI4_IRQHandler()和EXTI9_5_IRQHandler。并且添加了提示音函数。这时问题就产生了。
二。问题描述
设想上应该每次摁下按键都将进入中断函数,播放一次提示音并显示按下的按键值。可是显示一切正常,但提示音非常长已经超过了BUZZER_BEEP1()函数内设定的0.2秒。为搞清楚原因设置一个全局变量n来记录进入中断函数的次数:
结果发现每按一次n+2,也就是重复进入了中断函数。
三。问题发现与解决
由于是下降沿触发,这时对电平要求很高,电平波动或不匹配都可能造成系统误以为触发了中断从而进入中断函数。而我这里采用了推挽输出模式来保证对横(或纵)线四个I/O识别时不受纵(或横)线I/O口的影响。特别是每识别完四个对PA4~PA7、PA0~PA3状态进行了翻转,可能就是这时对电平产生了影响导致重复进入了中断函数。
解决办法:改变识别按键的逻辑,用于中断的通道避免采用推挽输出模式,或者尽量避免翻转,这可能导致中断触发的I/O口的状态改变。