三行代码
注意:和NE555连用的时候可能会出现一些奇奇怪怪的问题
uchar cont,trg; //triger触发 continue连续
void KeyScan()
{
uchar ReadData = PINB^0xff;
trg = ReadData&(ReadData^cont);
cont = ReadData;
}
原理
(1) 没有按键的时候
端口为0xff,ReadData读端口并且异或,很显然,就是 0x00 了。
Trg = ReadData & (ReadData ^ Cont); (初始状态下,Cont也是为0的)很简单的数学计算,因为ReadData为0,则它和任何数“相与”,结果也是为0的。
Cont = ReadData; 保存Cont 其实就是等于ReadData,为0;
结果就是:
ReadData = 0;
Trg = 0;
Cont = 0;
(2) 第一次PB0按下的情况
端口数据为0xfe,ReadData读端口并且异或,很显然,就是 0x01 了。
Trg = ReadData & (ReadData ^ Cont); 因为这是第一次按下,所以Cont是上次的值,应为为0。那么这个式子的值也不难算,也就是 Trg = 0x01 & (0x01^0x00) = 0x01
Cont = ReadData = 0x01;
结果就是:
ReadData = 0x01;
Trg = 0x01;Trg只会在这个时候对应位的值为1,其它时候都为0
Cont = 0x01;
(3) PB0按着不松(长按键)的情况
端口数据为0xfe,ReadData读端口并且异或是 0x01 了。
Trg = ReadData & (ReadData ^ Cont); 因为这是连续按下,所以Cont是上次的值,应为为0x01。那么这个式子就变成了 Trg = 0x01 & (0x01^0x01) = 0x00
Cont = ReadData = 0x01;
结果就是:
ReadData = 0x01;
Trg = 0x00;
Cont = 0x01;
因为现在按键是长按着,所以MCU会每个一定时间(20ms左右)不断的执行这个函数,那么下次执行的时候情况会是怎么样的呢?
ReadData = 0x01;这个不会变,因为按键没有松开
Trg = ReadData & (ReadData ^ Cont) = 0x01 & (0x01 ^ 0x01) = 0 ,只要按键没有松开,这个Trg值永远为 0 !!!
Cont = 0x01;只要按键没有松开,这个值永远是0x01!!
(4) 按键松开的情况
端口数据为0xff,ReadData读端口并且异或是 0x00 了。
Trg = ReadData & (ReadData ^ Cont) = 0x00 & (0x00^0x01) = 0x00
Cont = ReadData = 0x00;
结果就是:
ReadData = 0x00;
Trg = 0x00;
Cont = 0x00;
很显然,这个回到了初始状态,也就是没有按键按下的状态。
这个代码完美解决了延时消抖的问题,而且代码简洁方便,实用性很高,因为三行代码相当于是检测按键的状态来判断按键是否有按下,所以我们可以不用中断来写按键,下面我就放上我用51写的不用中断的按键扫描实验。有长按键和短按键的扫描。
网上关于三行代码的资料很多,我在这里只是当一个搬运工,有些见解颇偏,欢迎各位高人指点。
独立按键实验代码
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar cont,trg;
static uchar k;
//三行代码实现按键扫描
void keyscan()
{
uchar ReadData = P3^0xff;
trg = ReadData&(ReadData^cont);
cont = ReadData;
}
void Delay100ms() //@11.0592MHz
{
unsigned char i, j;
i = 180;
j = 73;
do
{
while (--j);
} while (--i);
k++;
}
//按键功能
void keyfun()
{
if(trg & 0x01)
{
P1=~0x01;
}
else if(trg & 0x02)
{
P1=~0x02;
}
else if(trg & 0x04)
{
P1=~0x04;
}
else if(cont & 0x01)
{
Delay100ms();
if(k == 20)//长按键
{
P1=0xff;
k=0;
}
}
}
void main()
{
while(1)
{
keyscan();
keyfun();
}
}