本文包含原理图、PCB、源代码、封装库、中英文PDF等资源
您需要 登录 才可以下载或查看,没有账号?注册会员
×
4*4键盘扫描程序
一、
#include<at89x51.h>
#define uint unsigned int
#define uchar unsigned char
uchar code light[]={0x7f,0xbf,0xdf,0xef}; //灯位
uchar code LED[]={ //共阴极数码管段码
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0};
uchar key,j;
void delay(uint m) //延时
{
uint i;
for(;m>0;m--)
for(i=124;i>0;i--)
;
}
void keyscan() //扫描程序
{
for(j=0;j<4;j++)
{
P2=light[j];
while((P2&0x0f)!=0x0f)
{
delay(5);
while((P2&0x0f)!=0x0f)
{
if(P2==0x7e) key=0; //读取键码值
if(P2==0x7d) key=1;
if(P2==0x7b) key=2;
if(P2==0x77) key=3;
if(P2==0xbe) key=4;
if(P2==0xbd) key=5;
if(P2==0xbb) key=6;
if(P2==0xb7) key=7;
if(P2==0xde) key=8;
if(P2==0xdd) key=9;
if(P2==0xdb) key=10;
if(P2==0xd7) key=11;
if(P2==0xee) key=12;
if(P2==0xed) key=13;
if(P2==0xeb) key=14;
if(P2==0xe7) key=15;
}
}
}
}
void main() //主函数
{
key=16;
while(1)
{
keyscan();
P1=LED[key];
}
}
1、 键盘扫描可归纳为如下套路
A)
If(有键按下)
{
If(有键按下)
{
While(仍有键按下) //等待松手
}
}
B)
While(有键按下)
{
While(有键按下)
{ //用while语句,不用再另加判松手语句
}
}
2、要注意的是判断条件if((P2&0x0f)!=0x0f)因为!=优先级高于&所以要加小括号
二、以上是用等侍方式,CPU利用率不高,用中断方式会提高利用率
中断方式又可分为外部中断方式和定时中断方式,外部中断要配合上一定的硬件电路以实现功能,而定时中断方式则可与数码管定时显示配合使用,典型的例子如制作一个电子计算器。程序及图如下:
#include<at89x51.h>
#define uint unsigned int
#define uchar unsigned char
uchar code light[]={0x7f,0xbf,0xdf,0xef}; //控制显示灯位
uchar code seg[]={0x3f,0x06,0x5b,0x4f, //共阴极段码
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
uchar disp_buffer[]={1,0,0,0,0}; //当前灯位,显示区
uchar key_buffer[]={0,0}; //缓冲区满标志,键码
uchar p,flag;
void delay(uint m) //延时程序
{
uint n;
for(;m>0;m--)
for(n=124;n>0;n--)
;
}
void init() //初始化
{
TMOD=0x01;
TH0=0xf7;
TL0=0x0;
p=0;
flag=0;
EA=1;
ET0=1;
TR0=1;
}
void display(uchar j,uchar k) //显示程序
{
P3=light[j];
P0=seg[k];
}
void keyscan() //键盘扫描程序
{
uchar i,key;
for(i=0;i<4;i++)
{
P2=light;
while((P2&0x0f)!=0x0f)
{
delay(5);
while((P2&0x0f)!=0x0f)
{
if(P2==0x7e) key=15;
if(P2==0x7d) key=0;
if(P2==0x7b) key=14;
if(P2==0x77) key=10;
if(P2==0xbe) key=1;
if(P2==0xbd) key=2;
if(P2==0xbb) key=3;
if(P2==0xb7) key=11;
if(P2==0xde) key=4;
if(P2==0xdd) key=5;
if(P2==0xdb) key=6;
if(P2==0xd7) key=12;
if(P2==0xee) key=7;
if(P2==0xed) key=8;
if(P2==0xeb) key=9;
if(P2==0xe7) key=13;
key_buffer[0]=1;
key_buffer[1]=key;
}
}
}
}
void timer0() interrupt 1 //定时器0,定时显示和扫描
{
TH0=0xf7;
TL0=0x0;
if(disp_buffer[0]==5) disp_buffer[0]=1;
display(disp_buffer[0]-1,disp_buffer[disp_buffer[0]]);
disp_buffer[0]++;
p++;
if(p==4)
{
p=0;
keyscan();
}
}
void main()
{
uchar a,operator,i;
uint tempa,tempb;
uchar temp[5];
init();
while(1)
{
keyscan();
if(key_buffer[0]) //判缓冲区满
{
key_buffer[0]=0;
switch(key_buffer[1])
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:if(flag) //数值输入
{
for(i=1;i<=4;i++)
{
temp=disp_buffer;
disp_buffer=0;
}
}
flag=0;
for(a=1;a<=3;a++) disp_buffer[a]=disp_buffer[a+1];
disp_buffer[4]=key_buffer[1];
break;
case 10: //运算符和清零输入
case 11:
case 12:
case 13:
case 14:flag=1; tempa=1000*disp_buffer[1]+100*disp_buffer[2]+10*disp_buffer[3]+disp_buffer[4];
tempb=1000*temp[1]+100*temp[2]+10*temp[3]+temp[4];
switch(operator)
{
case 10:tempa+=tempb;break;
case 11:tempa=tempb-tempa;break;
case 12:tempa*=tempb;break ;
case 13:tempa=tempb/tempa;break;
}
tempa%=10000;
disp_buffer[1]=tempa/1000;
tempa%=1000;
disp_buffer[2]=tempa/100;
tempa%=100;
disp_buffer[3]=tempa/10;
disp_buffer[4]=tempa%=10;
operator=key_buffer[1];
break;
case 15:for(i=1;i<=4;i++) disp_buffer=0;
flag=1;
operator=0;
}
}
}
} |