本帖最后由 gaoyang9992006 于 2023-9-7 13:18 编辑
按键是单片机交互中常用的元件,通常按键默认是通过上拉电阻拉高端口电平,另外一个引脚接地,当按下后拉低端口电压。只要检测这个拉低信号即可实现按键检测。
单个按键检测常用的手段有:扫描法;中断法。
扫描法通常被称为笨办法,让单片机主函数不停的去测试端口电压,当检测到端口为低电平的时候记作按键被按下,根据相关逻辑实现按键调节某个变量的应用。这种方法通常不可取,因为要系统一直来处理按键工作,增加了开销。同样的,这种方法也避免不了因为机械抖动产生的噪声干扰,可能一次按下会产生多次触发。
另外一种方法就是在中断里,检测IO的中断,当按键按下的瞬间会产生一个上升沿,当按键松手的那一刹那会产生一个下降沿。因此通常的做法是检测其中一个跳变产生的中断信号。这种做法通常也会因为机械抖动产生的干扰造成错误的多次判断。很多人这时候会进行消抖处理,通过软件延时判断等一系列的骚操作实现消除抖动的功能,这无疑增加了系统的开销,同时会让程序为此耽搁一段时间,虽然这段时间很短很短。
新方法:我们观察当我们使用按键的时候通常是想得到这样一个结果,我按下抬起一次算一次按键,只操作这么一次。这个情况我们可以发现这一完整过程包含了一个下降沿+一个上升沿,因此我们可以用这一完整的跳变过程作为判断一次有效按键的依据。
这需要使用到双边沿触发模式,也就是下降沿和上升沿都可以产生中断信号。
刚好我们的PIC单片机的IO具备这一功能,配置如下:
代码实现:
当按键按下,第一次中断触发后,我们要对第一次做一个标记,按键被按下过:bool SW_flag = 0;
当按键松开,第二次中断触发后,我们要判断第一次做的标记,如果存在清理它,并记录为一次有效按键操作。
- bool SW_flag = 0; //记录是否发生了下降沿中断
- bool SW_Button_active_flag =0; //有效按键激活标记
- void SW_Button_Interrupt_Handle(void)
- {
- if(SW_GetValue()==LOW)
- {
- SW_flag = 1;
- }
- else if( ( SW_GetValue()==HIGH ) && (SW_flag == 1) )
- {
- SW_Button_active_flag =1;
- SW_flag = 0;
- }
- }
最后我们将中断处理函数的指针传递给中断调用函数
SW_SetInterruptHandler(SW_Button_Interrupt_Handle);
经过测试,当无法出现一次完整的中断过程(下降沿+上升沿)按键不被激活,这样就避免了按下一次多次触发的尴尬局面。按键也变的更加稳定可靠了。
同样,在此基础上,如果启用一个定时器作为观察者,我们还可以实现按下时间长短触发不同的按键效果的操作,这里大家可以自行完成。
|