该按钮可以说是51单片机项目开发的重要组成部分,是51单片机IO端口输入的重要方式。我们可以通过按下按钮来控制微控制器执行相应的程序,以获得所需的效果。 51单片机的键输入主要有两种。一种是独立密钥。每个键对应一个IO端口,该端口通过循环或中断检测。当键的数量很少时,通常使用此方法。如果按键数量很大,则会为每个按键分配一个IO端口,这将占用大量资源,因此有一个矩阵键盘。矩阵键盘通过单片机扫描键盘的每一行和每一列,并通过行和列唯一地确定键的数目。下面介绍这两种方法。
1个独立按钮
Proteus仿真电路图
图片中的按键通过P 1. 0〜P 1. 3输入,四个LED灯连接到P.0〜P 2. 3,按下不同的键,对应于不同的LED灯,步骤如下:
#include unsigned char num;
void main()
{
TMOD=0x01;
TH0 = (65536-917)/256;//1000/1.09
TL0 = (65536-917)%256;;
EA=1;
ET0=1;
TR0=1;
P1=0xff;
P2=0x00;
while(1){
if(num==20){
num=0;
switch(P1){
case ~0x01:
P2=~0x01;
break;
case ~0x02:
P2=~0x02;
break;
case ~0x04:
P2=~0x04;
break;
case ~0x08:
P2=~0x08;
break;
defult:
break;
}
}
}
}
void Timer0() interrupt 1
{
TH0 = (65536-917)/256;
TL0 = (65536-917)%256;
num++;
}
使用定时器0中断的形式,定时器0每1ms产生一次中断,num加1,并且在while循环中判断num = 20时,定时20ms,读取P1的状态,并判断P1判断的值是按下按钮并且相应的LED灯点亮。效果图如下:
独立键非常简单。我认为您有比我更好的例子(例如,具有防抖功能)。今天的重点是矩阵键盘。
2个矩阵键盘检测
Proteus仿真电路图
这里,16个键按4 * 4排列,矩阵键盘的每一行都连接到P 3. 0〜P 3. 3;矩阵键盘的每一列都连接到P 3. 4〜P 3. 7。扫描原理大致如下:首先将P30设置为零,其余设置为1(P3-0xfe),然后读取P3端口的状态。如果P3!= 0xfe(此处高四位将改变,第四位保持不变),则表明已按下某个键,并且该键必须是第一行中的键。然后去判断P3端口的状态,如果按下第一个按钮(左上角),它应该是P 3. 4 = 0,刚才P 3. 0 = 0,那么P3的状态port是P3 = 0xee,依此类推,按下第一行中的第二,第三和第四按钮,分别对应于P3 = 0xde,P3 = 0xbe,P3 = 0x7e。这样,您可以确定按下了哪个按钮。如果P3 = 0xfe,则表示第一行中没有按下按钮。然后采用相同的方法,将P3 = 0xfd设置为判断第二行是否有按钮按下,然后依次将每一行设置为零(P3 = 0xfb,P3 = 0xf 7),读取列的状态,确定按下了哪个按钮,如果没有按下,则表示没有按下按钮。
C51代码:
#include void Delay10ms()//@11.0592MHz
{
unsigned char i, j;
i = 18;
j = 235;
do
{
while (--j);
} while (--i);
}
void key_scan()
{
unsigned char temp;
P3=0xfe;
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
delay10ms();
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xee:
P2=0x00;
break;
case 0xde:
P2=0x01;
break;
case 0xbe:
P2=0x02;
break;
case 0x7e:
P2=0x03;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp&=0xf0;
}
}
}
P3=0xfd;
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
delay10ms();
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xed:
P2=0x04;
break;
case 0xdd:
P2=0x05;
break;
case 0xbd:
P2=0x06;
break;
case 0x7d:
P2=0x07;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp&=0xf0;
}
}
}
P3=0xfb;
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
delay10ms();
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xeb:
P2=0x08;
break;
case 0xdb:
P2=0x09;
break;
case 0xbb:
P2=0x0a;
break;
case 0x7b:
P2=0x0b;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp&=0xf0;
}
}
}
P3=0xf7;
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
delay10ms();
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xe7:
P2=0x0c;
break;
case 0xd7:
P2=0x0d;
break;
case 0xb7:
P2=0x0e;
break;
case 0x77:
P2=0x0f;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp&=0xf0;
}
}
}
}
void main()
{
P2=0x00;
while(1)
{
key_scan();
}
}
key_scan()是键盘扫描功能,分为四个部分,每个部分的核心都是相同的,以实现矩阵键盘扫描的原理。第一段介绍如下:
P3=0xfe;
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
delay10ms();
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xee:
P2=0x00;
break;
case 0xde:
P2=0x01;
break;
case 0xbe:
P2=0x02;
break;
case 0x7e:
P2=0x03;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp&=0xf0;
}
}
}
首先,P3 = 0xfe,然后将P3分配给temp,然后将temp与0xf0进行“与”运算。如果P3的高四位为0,则temp不能等于0xf0,但不能直接判断是否有按下按钮。可能会有一些干扰,并且在按下按钮的初始阶段不稳定。它不是理想的下降沿,因此需要消除抖动。实际上,要重新读取P3端口状态要延迟10毫秒。如果tmep仍不等于0xf0,则可以判断按钮被按下,然后可以将p3幅度赋予temp,然后判断temp的状态。
然后下面的程序将确定按钮是否被抬起,否则它将保留在此循环中并且无法执行其他程序:
while(temp!=0xf0)
{
temp=P3;
temp&=0xf0;
}
以上代码是通过while循环实现的,或者可以被中断:
#include unsigned char num;
void Delay10ms()//@11.0592MHz
{
unsigned char i, j;
i = 18;
j = 235;
do
{
while (--j);
} while (--i);
}
void key_scan()
{
unsigned char temp;
P3=0xfe;
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
delay10ms();
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xee:
P2=0x00;
break;
case 0xde:
P2=0x01;
break;
case 0xbe:
P2=0x02;
break;
case 0x7e:
P2=0x03;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp&=0xf0;
}
}
}
P3=0xfd;
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
delay10ms();
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xed:
P2=0x04;
break;
case 0xdd:
P2=0x05;
break;
case 0xbd:
P2=0x06;
break;
case 0x7d:
P2=0x07;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp&=0xf0;
}
}
}
P3=0xfb;
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
delay10ms();
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xeb:
P2=0x08;
break;
case 0xdb:
P2=0x09;
break;
case 0xbb:
P2=0x0a;
break;
case 0x7b:
P2=0x0b;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp&=0xf0;
}
}
}
P3=0xf7;
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
delay10ms();
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xe7:
P2=0x0c;
break;
case 0xd7:
P2=0x0d;
break;
case 0xb7:
P2=0x0e;
break;
case 0x77:
P2=0x0f;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp&=0xf0;
}
}
}
}
void main()
{
TMOD=0x01;
TH0 = (65536-917)/256;//1000/1.09
TL0 = (65536-917)%256;;
EA=1;
ET0=1;
TR0=1;
P2=0x00;
while(1)
{
if(num==2)
{
num=0;
key_scan();
}
}
}
void Timer0() interrupt 1
{
TH0 = (65536-917)/256;
TL0 = (65536-917)%256;
num++;
}
核心内容相同,因此不再赘述。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/bofangqi/article-357440-1.html