51模块

您所在的位置:网站首页 单片机独立按键检测有延迟 51模块

51模块

2024-07-17 10:09| 来源: 网络整理| 查看: 265

51模块_按键检测 按键检测传统法带有标志位的按键识别法快速识别法简洁快速识别法(可识别长按)|建议使用

按键检测

按键检测步骤:

判断按下消抖(一般为5ms~10ms)等待按键松开(可略)检测松开 传统法

if 检测按键的按下, delay 来消抖, while 等待按键松开 。

程序:

sbit s4 = P3^3; //单独使用一个 I/O 口,则需要使用 sbit 进行位定义 void main() { while(1) { if(s4 == 0) //检测是否有键按下 { delay10ms(); //经过10ms的延时函数进行消抖 if(s4 == 0) //若P3^3仍然为低电平,则确实有键(s4)按下 { dspbuf[0]++; //第一位数码管的段码值 +1 while(!s4); //等待按键松开,等价于while(s4 == 0) } } display(); //数码管显示函数 } } //源码:https://blog.csdn.net/xiaocheng_sky/article/details/52124568

传统法使用了 whlie() 来等待按键松开,容易卡死程序,使后面的代码无法执行。

带有标志位的按键识别法

先定义一个 key_flag 作为按键标志位, if 检测按键的按下(当前按键与标识位 key_flag 对比), delay 来消抖,取反标识位 key_flag 的值,if 再次确认当前按键, 进行事件处理 , 通过mian函数的循环来检测按键的松开。 其中: 代码“key_flag = 1”的作用是:下次即便按键没有松手,程序跑完一圈之后,也不会再满足if((s4 == 0) && (!key_flag))的条件;同样,亦不会满足else if(s4 != 0)的条件,那么key_flag 不会被赋为0。综合以上情况,一次按键只会进行一次处理。当按键被释放后,以后的扫描则会满足else if(s4 != 0)的条件,那么key_flag 会被赋为0,则可以进行接下来的按键扫描了,如此反复…… 程序:

sbit s4 = P3^3; uchar key_flag = 0; //首先定义按键的标志位,并初始化为0 void key_scan() //按键扫描函数 { if((s4 == 0) && (!key_flag)) //如果有键按下,则条件成立(有键按下,则s4为0;而 !key_flag为1) { delay10ms(); //延时消抖 key_flag = 1; //把标志位置为1 if(s4 == 0) //如果确定有键按下 { dspbuf[0]++; //进行事件处理(数码管显示值加1) } } else if(s4 != 0) //未按下按键 { key_flag = 0; } } //源码:https://blog.csdn.net/xiaocheng_sky/article/details/52139480

以上可以避免使用 while 函数造成的卡程序,但依旧使用了 delay 函数进行延时消抖,不够高效。

快速识别法

知识点:符号“^”为“异或”的计算机语言。 如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0。

先定义三个标志位: key_now 、 key_flag 、 key_old 。 然后保证三个值的初始值与三个值的初始化状态相同。 下面程序中,当按键没按下时,now为1;flag为0;old为1。 当按键按下时,now为0;flag为(0 ^ 1) ^ 0 = 1;old为0;与没按下时不同。 当按键释放后,now为1;flag为(1 ^ 1) ^ 0 = 0;old为0;

uchar key_now = 1; //用处存储按键本次的状态(0表示按下,1表示未按下) uchar key_flag = 0; //按键是否按下的标志(0表示按键未被按下,1表示按键被按下) uchar key_old = 1; //用于存储按键上次的状态(0表示上次按下,1表示上次未按下) sbit s4 = P3^3; void key_scan() { key_now = s4; key_flag = (key_now ^ key_old) ^ key_flag; key_old = key_now; } //计算key_flag为1的次数,消抖 //源码:https://blog.csdn.net/xiaocheng_sky/article/details/52146083 简洁快速识别法(可识别长按)|建议使用

知识点1:c语言中&与&&的区别 &:按照位与操作,例如:0010&1101,结果为0000 &是java中的位逻辑运算: eg: 2&3=2; 分析如下: 2的二进制为10 ;3的二进制为11 ; 逻辑&之后为10 &&:短路与,表示如果两个条件都成立则执行之后的逻辑; 例如:if(a0&&b0),意思就是if a为0并且b为0的时候,进行下一步操作。 || 短路或。 A||B,只有当A为假的时候才会对B进行判断。若A为真,则不继续对B进行判断。 | 逻辑或。 A|B,会对A, B都进行判断 ! 逻辑非,当操作数为true时,返回false,否则返回true。

知识点2:位异或运算:A ^ 0xff。代表操作数A逐位和0xff异或,它的结果是~A。 任何数与全0异或,值不变。 任何数与全1异或,值取反。 任何数与自己异或,值为0。

先定义两个标志位: Trg 、 Cont 。 保证三个值的初始值与三个值的初始化状态相同。 下面程序中,当按键没按下时,ReadData = 1 ^ 0xff = 0x00 ; Trg = 0 & (0 ^ 0)= 0 ; Cont = 0。三值分别为0,0,0。 当按键按下时,ReadData = 0 ^ 0xff = 1 ;Trg = 1 & (1 ^ 0) = 1 ; Cont = 1。          三值分别为1,1,1。 当按键长按时,ReadData = 0 ^ 0xff = 1 ; Trg = 1 & (1 ^ 1) = 0; Cont = 1。        三值一直保持为1,0,1。 当按键释放后,ReadData = 1 ^ 0xff = 0 ;Trg = 0 & (0 ^ 0) = 0 ; Cont = 0。          三值分别为0,0,0。

unsigned char Trg; unsigned char Cont; void KeyRead( void ) { unsigned char ReadData = PINB ^ 0xff; // 1 Trg = ReadData & (ReadData ^ Cont); // 2 Cont = ReadData; // 3 }


【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3