要求
在单片机综合训练平台上,首先将J5处的跳帽接到2~3引脚,使按键S4-S7四个按键的另一端接地,从而成为4个独立键盘。在扫描按键的过程中,发现有按键触发信号后,做去抖动操作,当确认为按键按下的时候,才进行相应的功能处理。
1.按下S7,点亮L1,松开后熄灭。
2.按下S6,点亮L2,松开后熄灭。
3.按下S5,点亮L3,松开后熄灭。
4.按下S4,点亮L4,松开后熄灭。按键均做去抖。
电路图:
独立键盘:
将J5处的跳帽接到2~3引脚,使按键S4-S7四个按键的另一端接地,从而成为4个独立键盘。当按键按下的时候,为低电平。要想知道哪个键被按下了,即读引脚,若为低电平,即为按下了。
一般要进行去抖动处理,以免出现干扰信号。有多种处理方法,最简单的是做延时处理,当读到S7为低电平的时候,过段时间再去读,若还为低电平,则为按下了。否则为干扰信号。
代码
当看到电路图的时候,可以先把38译码器的代码放上去。
1.38译码器
void SelectHC138(unsigned char channel) //通过38译码器对P2口写,控制锁存器
{
switch(channel)
{
case 4:
P2=(P2&0x1f)|0x80;
break;
case 5:
P2=(P2&0x1f)|0xa0;
break;
case 6:
P2=(P2&0x1f)|0xc0;
break;
case 7:
P2=(P2&0x1f)|0xe0;
break;
}
}
2.独立键盘的定义
由于是对独立键盘的操作,需要先提前定义。
sbit S7 = P3^0; //需要对独立键盘定义
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;
3.LED灯的定义
同样,由于是对LED灯的操作,需要先提前定义。
sbit L1 = P0^0; //需要对灯定义
sbit L2 = P0^1;
sbit L3 = P0^2;
sbit L4 = P0^3;
sbit L5 = P0^4;
sbit L6 = P0^5;
sbit L7 = P0^6;
sbit L8 = P0^7;
4.完成题目
按下按键,点亮对应的灯,松开后熄灭。
void ScanKeys_Alone()
{
if(S7 == 0) //S7按键
{
DelayK(100); //去抖操作
if(S7 == 0)
{
L1 = 0; //L1灯点亮
while(S7 == 0);
L1 = 1; //按键松开后,熄灭
}
}
if(S6 == 0) //S6按键
{
DelayK(100);
if(S6 == 0)
{
L2 = 0; //点亮L2
while(S6 == 0);
L2 = 1;
}
}
if(S5 == 0) //S5按键
{
DelayK(100);
if(S5 == 0)
{
L3 = 0; //点亮L3
while(S5 == 0);
L3 = 1;
}
}
if(S4 == 0) //S4按键
{
DelayK(100);
if(S4 == 0)
{
L4 = 0; //点亮L4
while(S4 == 0);
L4 = 1;
}
}
}
完整代码
#include"reg52.h"
sbit S7 = P3^0; //需要对独立键盘定义
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;
sbit L1 = P0^0; //需要对灯定义
sbit L2 = P0^1;
sbit L3 = P0^2;
sbit L4 = P0^3;
sbit L5 = P0^4;
sbit L6 = P0^5;
sbit L7 = P0^6;
sbit L8 = P0^7;
void SelectHC138(unsigned char channel) //通过38译码器对P2口写,控制锁存器
{
switch(channel)
{
case 4:
P2=(P2&0x1f)|0x80;
break;
case 5:
P2=(P2&0x1f)|0xa0;
break;
case 6:
P2=(P2&0x1f)|0xc0;
break;
case 7:
P2=(P2&0x1f)|0xe0;
break;
}
}
void DelayK(unsigned char t)
{
while(t--);
}
void ScanKeys_Alone()
{
if(S7 == 0) //S7按键
{
DelayK(100); //去抖操作
if(S7 == 0)
{
L1 = 0; //L1灯点亮
while(S7 == 0);
L1 = 1; //按键松开后,熄灭
}
}
if(S6 == 0) //S6按键
{
DelayK(100);
if(S6 == 0)
{
L2 = 0; //点亮L2
while(S6 == 0);
L2 = 1;
}
}
if(S5 == 0) //S5按键
{
DelayK(100);
if(S5 == 0)
{
L3 = 0; //点亮L3
while(S5 == 0);
L3 = 1;
}
}
if(S4 == 0) //S4按键
{
DelayK(100);
if(S4 == 0)
{
L4 = 0; //点亮L4
while(S4 == 0);
L4 = 1;
}
}
}
void main()
{
SelectHC138(4);
while(1)
{
ScanKeys_Alone();
}
}
总结
1.对于独立按键、LED灯,需要提前定义引脚。
2.独立按键,按下为低电平,要先进行去抖操作,再看是否为低电平,再对灯操作
3.注意主函数里面38译码器代码的位置。
4.代码中,按键松开:while(S5==0) ;
要求2
1.按下S7点亮L1,L1亮后,S6不响应操作,S5控制L3,S4控制L4,再次按下S7,L1熄灭,S6可以响应操作。
2.按下S6点亮L2,L2亮后,S7不响应操作,S5控制L5,S4控制L6,再次按下S6,L2熄灭,S7可以响应操作。
3.当S7、S6未按下时,S5、S4不响应操作
代码2
#include"reg52.h"
sbit S7 = P3^0; //需要对独立键盘定义
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;
sbit L1 = P0^0; //需要对灯定义
sbit L2 = P0^1;
sbit L3 = P0^2;
sbit L4 = P0^3;
sbit L5 = P0^4;
sbit L6 = P0^5;
sbit L7 = P0^6;
sbit L8 = P0^7;
void SelectHC138(unsigned char channel) //通过38译码器对P2口写,控制锁存器
{
switch(channel)
{
case 4:
P2=(P2&0x1f)|0x80;
break;
case 5:
P2=(P2&0x1f)|0xa0;
break;
case 6:
P2=(P2&0x1f)|0xc0;
break;
case 7:
P2=(P2&0x1f)|0xe0;
break;
}
}
void DelayK(unsigned char t)
{
while(t--);
}
unsigned char stat_k = 0; //状态锁定
void ScanKeys_Alone()
{
if(S7 == 0) //S7按键
{
DelayK(100);
if(S7 == 0)
{
if(stat_k == 0) //状态为0
{
L1 = 0;
stat_k = 1;
}
else if(stat_k == 1) //状态为1
{
L1 = 1;
stat_k = 0;
}
}
}
if(S6 == 0) //S6按键
{
DelayK(100);
if(S6 == 0)
{
if(stat_k == 0) //状态为0
{
L2 = 0;
stat_k = 2;
}
else if(stat_k == 2) //状态为2
{
L2 = 1;
stat_k = 0;
}
}
}
if(S5 == 0) //S5按键
{
DelayK(100);
if(S5 == 0)
{
if(stat_k == 1) //若为状态1
{
L3 = 0;
while(S5==0);
L3 = 1;
}
else if(stat_k == 2) //状态为2
{
L5 = 0;
while(S5==0);
L5 = 1;
}
}
}
if(S4 == 0) //S4按键
{
DelayK(100);
if(S4 == 0)
{
if(stat_k == 1) //若为状态1
{
L4 = 0;
while(S5==0);
L4 = 1;
}
else if(stat_k == 2) //状态为2
{
L6 = 0;
while(S5==0);
L6 = 1;
}
}
}
}
void main()
{
SelectHC138(4);
while(1)
{
ScanKeys_Alone();
}
}
总结2
要定义一个状态锁定值,通过状态控制按键。