可以在P00/P01/P02/P03四个I/O口上每个接四个按键,,在P04/P05/P06/P07四个口线上与前面的四个口线上的按键交插相连,这样可以通过查询的方式,比如是第查到P10口上有按键按下了,再转向查看P01,P05,P06,P07哪个口的电平发生的变化,这样就很容易找到是哪个按键了
有问题,当按下多个按键时,消抖都没用了。有计数法,但是需要消耗的内存。可以识别具体的键位,键的按下d起状态,消抖。每个按键状态独立识别,无需等待延时。typedefenum{Key_No,Key_Down,Key_Up,}KeyStateEnum;vkey[4]={0};//4组按键ucharkeyDownNum[16]={0};//按下计数ucharkeyDownUp[16]={0};//d起计数//判断键状态ucharstateKey(ucharkeySta,uchardownNum,ucharupNum,uchardel){ucharsta=Key_No;if(keySta){upNum[0]=0;if(downNum[0]==del){sta=Key_Down;}if(downNum[0]>4);}}voidmain(){while(1){Readkey();//ScanKey();}}
没有硬件电路,单从程序来看应该没错。我加了注释,你可以参考下。
#include<STC12C5A60S2h>
char code table[]={
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x00,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e};
void delayms(int xms)
{
int i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒
for(j=110;j>0;j--);
}
void display(char num)
{
P1=table[num]; //段选数据
}
void matrixkeyscan()
{
char temp,key;
P3=0xfe;
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)//说明有按键按下
{
delayms(10);//延时,去抖动
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)//说明按键被持续按下
{
temp=P3;//记录P3口状态
switch(temp)//根据现在的状态判断哪个按键被按下
{
case 0xee: //p3^4被按下
key=0;
break;
case 0xde: //p3^5
key=1;
break;
case 0xbe://p3^6
key=2;
break;
case 0x7e://p3^7
key=3;
break;
}
while(temp!=0xf0)//按键松开之后跳出循环
{
temp=P3;
temp=temp&0xf0;
}
display(key);//显示
}
}
P3=0xfd;
{};
P3=0xfb:
{};
P3=0xf7;
{};
void main()
{
P0M1 = 0x00;//推挽输出的定义
P0M0 = 0x0f;//推挽输出的定义
P0=0x0f;
while(1)
{
matrixkeyscan();//不停调用键盘扫描程序
}
}
#define uint unsigned int
#define uchar unsigned char
#define Key_Scanf P1 //4X4按键显示;
#define Print_Out P0 //显示数字P0;
#define PORT P2 //数码选择;
#define SYSLED P0^7; //系统指示灯;
uchar code table[]={0xff,0x4f,0x12,0x06,0x4c,0x24,0x20,0x0f,0x00,0x0c,0x01}; //0~9数字
void display(uchar); //显示
void delay_50us(uint t); //延时50微秒,防抖动
uchar keyscan(void); //键盘
void SYS_LED(void); //指示灯
uchar a=0;
uchar keynum;
void delay_50us(uint t)
{
uchar j;
for(;t>0;t--)
for(j=19;j>0;j--);
}
void SYS_LED()
{
SYSLED = 0;
delay_50us(100);
SYSLED = 1;
}
void display( uchar keynum) //根据keynum返回值显示数字
{
PORT=0xfe;
Print_Out=table[keynum];
}
uchar keyscan()
{
Key_Scanf=0xbf; // 扫描第一横行,后四位为1,前四位线与,然后跟原来数值比较,如果不等,则把对应的数字赋给keynum
if((Key_Scanf&0xbf)!=0xbf)
{
delay_50us(100);
if((Key_Scanf&0xbf)!=0xbf)//消抖
{
SYS_LED();
a=Key_Scanf&0xbf;
switch(a)
{
case 0x77:keynum=1;break;
case 0x7b:keynum=2;break;
case 0x7d:keynum=3;break;
default:break;
}
}
}
Key_Scanf=0xdf; //扫描第二横行,后四位为1,前四位线与;
if((Key_Scanf&0xdf)!=0xdf)
{
delay_50us(100);
if((Key_Scanf&0xdf)!=0xdf)
{
a=Key_Scanf&0xdf;
switch(a)
{
case 0x7e:keynum=4;break;
case 0xb7:keynum=5;break;
case 0xbb:keynum=6;break;
default: break;
}
}
}
Key_Scanf=0xef; //扫描第三横行,后四位为1,前四位线与;
if((Key_Scanf&0xef)!=0xef)
{
delay_50us(100);
if((Key_Scanf&0xef)!=0xef)
{
a=Key_Scanf&0xef;
switch(a)
{
case 0xbd:keynum=7;break;
case 0xbe:keynum=8;break;
case 0xe7:keynum=9;break;
default: break;
}
}
}
Key_Scanf=0xf7; //扫描第四横行,后四位为1,前四位线与;
if((Key_Scanf&0xf7)!=0xf7)
{
delay_50us(100);
if((Key_Scanf&0xf7)!=0xf7)
{
a=Key_Scanf&0xf7;
switch(a)
{
case 0xeb:keynum=10;break;
default: break;
}
}
}
return keynum;
}
void main(void)
{
while(1)
{
keyscan();
display(keynum);
}
}
以上就是关于编写一个4X4的矩阵键盘程序,单片机利用AVR atmega16单片机,硬件如图所示。全部的内容,包括:编写一个4X4的矩阵键盘程序,单片机利用AVR atmega16单片机,硬件如图所示。、如何用汇编语言实现4*3矩阵键盘程序设计,当任意一个按键按下后使用四、单片机矩阵键盘程序求解释和修正!等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)