看了蓝桥杯单片机的培训视频,发现用状态机消抖法实现矩阵键盘时左边两列没有用,这是因为P36、P37口实际是P42、P44口,所以我们在用行列扫描法时会出错。但习惯了状态机消抖,改其它的方法来实现矩阵键盘不习惯,于是干脆解决这个问题,用状态机消抖法实现矩阵键盘。
代码下载地址:
https://gitee.com/zhang-yanping/singlechip.git
下面是代码
/*功能:利用状态机消抖法实现矩阵键盘,按S4开LED1,按S5开LED5*/
#include"reg52.h" //用状态机消抖的方法实现矩阵键盘
#include"intrins.h"
sfr P4 = 0xc0; //矩阵键盘P3^6和P3^7口实际对应P4^2和P4^4口,sfr为定义寄存器,P4的地址为0xc0,
sbit P42 = P4^2;
sbit P44 = P4^4;
//key_return对应相应按键
#define KEY P3 //KEY为P3口对应值
#define key_state_0 0
#define key_state_1 1
#define key_state_2 2
unsigned char state_p24; //P3口和P42,P44的数据
sbit buzzer = P0^6;
char read_key(void)
{
static char key_state =0;
unsigned char key_return=0,key_press;
unsigned char key1,key2;
KEY=0x30;P42=1;P44=1; //读高四位
if(P42) //读取P34,P35,P42,P44
{
if(P44)
{state_p24 =0xc0|KEY;}
else
{state_p24 =0x40|KEY;}
}
else
{
if(P44)
{state_p24 =0x80|KEY;}
else
{state_p24 =0x00|KEY;}
}
key1=state_p24&0xf0;
KEY=0X0f;P42=0;P44=0; //读低四位
if(P42) //读取P30,P31,P32,P33
{
if(P44)
{state_p24 =0xc0|KEY;}
else
{state_p24 =0x40|KEY;}
}
else
{
if(P44)
{state_p24 =0x80|KEY;}
else
{state_p24 =0x00|KEY;}
}
key2=state_p24&0x0f;
key_press=key1|key2; //读取P3口的值
switch(key_state)
{
case key_state_0: //判断是否有键按下
if(key_press!= 0xff) key_state = key_state_1;
break;
case key_state_1:
if(key_press!=0xff) //判断是否抖动
{
if(key_press==0x77) key_return = 4; //S4
if(key_press==0x7b) key_return = 5; //S5
if(key_press==0x7d) key_return = 6; //S6
if(key_press==0x7e) key_return = 7; //S7
if(key_press==0xb7) key_return = 8; //S8
if(key_press==0xbb) key_return = 9; //S9
if(key_press==0xbd) key_return = 10; //S10
if(key_press==0xbe) key_return = 11; //S11
if(key_press==0xd7) key_return = 12; //S12
if(key_press==0xdb) key_return = 13; //S13
if(key_press==0xdd) key_return = 14; //S14
if(key_press==0xde) key_return = 15; //S15
if(key_press==0xe7) key_return = 16; //S16
if(key_press==0xeb) key_return = 17; //S17
if(key_press==0xed) key_return = 18; //S18
if(key_press==0xee) key_return = 19; //S19
key_state = key_state_2;
}
else
key_state = key_state_0;
break;
case key_state_2: //判断按键是否弹起
if(key_press==0xff) key_state = key_state_0;
break;
}
return key_return; //返回各按键对应值
}
void Delay10ms() //@11.0592MHz
{
unsigned char i, j;
i = 108;
j = 145;
do
{
while (--j);
} while (--i);
}
void main()
{
unsigned char key_val;
P2=0xa0;buzzer=0;P2=0x00;
while(1)
{
key_val=read_key();
if(key_val==4) //如果键值等于S4按下的键值
{
P2=0x80;P0=0xfe;P2=0x00;
}
if(key_val==5) //如果键值等于S5按下的键值
{
P2=0x80;P0=0xef;P2=0x00;
}
Delay10ms();
}
}