按键时序图
软件延时,如DelayXms(10),那么CPU在这10ms内就不能做其他任务,并行多任务是无法执行的。如按键按你的,oled显示显示你的。
如果按键不松开,那么松手等待,程序卡死在这,此时数码管不能进行动态刷新。
如果快速按下按键并松开,但数码管还是会熄灭再亮,这不符合要求。我们需要按键执行按键的任务,数码管不受按键任务的影响。
因此两个任务应该并行执行(计算机计算速度快)
阻塞延时按键消抖
两个问题:
1、采用delay函数,纯软件延时来实现软件消抖,这不利于实现并行多任务。
2、按键识别过程中,为了防止按键被多次触发,我们用了等待按键松开的while循环,这样加入我们按着按键不松开,程序无法执行其他的代码,这时候也是无法实现多任务的执行的。
如果我们项目中用到按键和显示,如果软件延时和松手等待不去掉,就无法执行多任务。
main.c
void main(){
while(1){
Key_Service();//若按键不松开,数码管就不刷新,无法显示
Dis_Service();
Display(); //动态刷新数码管
}
}
key.c(old)
if(!KEY1 || !KEY2||!KEY3||!KEY4){
DelayXms(10); //软件延时,CPU干不了其他的事情
if(!KEY1 || !KEY2||!KEY3||!KEY4)
{
if(!KEY1)
{
KeyNum = 1;
}
if(!KEY2)
{
KeyNum = 2;
}
if(!KEY3)
{
KeyNum = 3;
}
if(!KEY4)
{
KeyNum = 4;
}
}while(!KEY1 || !KEY2||!KEY3||!KEY4);//松手等待,CPU干不了其他的事情
}
非阻塞延时程序
main.c
void main(){
while(1){
Key_Service();
Dis_Service();
Display(); //动态刷新数码管
}
}
Key.c(new)
#include "Key.h"
#include "delay.h"
unsigned char key1_lock_flag;//自锁标志,为的是去掉松手等待
unsigned char key1_cnt;//非阻塞延时代替阻塞延时,需要用到变量累加
unsigned char key2_lock_flag;//自锁标志,为的是去掉松手等待
unsigned char key2_cnt;//非阻塞延时代替阻塞延时,需要用到变量累加
unsigned char key3_lock_flag;//自锁标志,为的是去掉松手等待
unsigned char key3_cnt;//非阻塞延时代替阻塞延时,需要用到变量累加
unsigned char key4_lock_flag;//自锁标志,为的是去掉松手等待
unsigned char key4_cnt;//非阻塞延时代替阻塞延时,需要用到变量累加
unsigned char Key_Scan(){
unsigned char KeyNum = 0;
//如果按键不稳定,产生抖动,当key1_cnt加到88,突然抖动,那么key1_cnt清零,重新计数,实现消抖的作用。
if(KEY1)//如果没有按键按下,按键处于高电平
{
//如果没有按键按下,则给他清零
key1_lock_flag = 0;//清零自锁标志
key1_cnt = 0; //清零计数标志
}
else if(!key1_lock_flag && KEY1 == 0){
key1_cnt++; //累计按键消抖延时次数,主循环while每执行一次,key1_cnt加一
if(key1_cnt > KEY_DE LAY_TIME)//KEY_DELAY_TIME的大小可以调节按键的灵敏度,取决于任务多少个,每个任务的执行时间是多少
{
key1_cnt = 0; //清零计数变量
key1_lock_flag = 1; //自锁标志置1,代表按键按下,防止按键多次触发
KeyNum = 1; //赋键值编码
}
}
if(KEY2)//如果没有按键按下,按键处于高电平
{
//如果没有按键按下,则给他清零
key2_lock_flag = 0;//清零自锁标志
key2_cnt = 0; //清零计数标志
}
else if(!key2_lock_flag && KEY2 == 0){
key2_cnt++; //累计按键消抖延时次数
if(key2_cnt > KEY_DE LAY_TIME)//KEY_DELAY_TIME的大小可以调节按键的灵敏度
{
key2_cnt = 0; //清零计数变量
key2_lock_flag = 1; //自锁标志置1,代表按键按下,防止按键多次触发
KeyNum = 1; //赋键值编码
}
}
if(KEY3)//如果没有按键按下,按键处于高电平
{
//如果没有按键按下,则给他清零
key3_lock_flag = 0;//清零自锁标志
key3_cnt = 0; //清零计数标志
}
else if(!key3_lock_flag && KEY3 == 0){
key3_cnt++; //累计按键消抖延时次数
if(key3_cnt > KEY_DE LAY_TIME)//KEY_DELAY_TIME的大小可以调节按键的灵敏度
{
key3_cnt = 0; //清零计数变量
key3_lock_flag = 1; //自锁标志置1,代表按键按下,防止按键多次触发
KeyNum = 1; //赋键值编码
}
}
if(KEY4)//如果没有按键按下,按键处于高电平
{
//如果没有按键按下,则给他清零
key4_lock_flag = 0;//清零自锁标志
key4_cnt = 0; //清零计数标志
}
else if(!key4_lock_flag && KEY1 == 0){
key4_cnt++; //累计按键消抖延时次数
if(key4_cnt > KEY_DE LAY_TIME)//KEY_DELAY_TIME的大小可以调节按键的灵敏度
{
key4_cnt = 0; //清零计数变量
key4_lock_flag = 1; //自锁标志置1,代表按键按下,防止按键多次触发
KeyNum = 1; //赋键值编码
}
}
}