问题
单片机AT89C51的P2口外接一4×4矩阵键盘,P1口外接两位LED数码管。编写键盘扫
描程序和显示程序。实现功能如下:按下某按键时,数码管上显示该键对应的键值0
~15。如果连续第二次按下该键,则数码管显示的数值为该键值加3
在单片机系统中,LED数码管的显示程序根据实际需要分为静态显示和动态显示两种方式。
所谓静态显示,是当数码管显示某个字符时,公共端接固定电平,相应段的发光二极管恒定地导通或截止,直到显示另一个字符为止。 采用数码管静态显示方式,单片机显示程序比较简单,数码管显示亮度稳定。但因为每一个数码管都需要一个8位的端口来控制,占用资源较多,一般适用于显示位数较少的场合。
当单片机系统显示的数据位数较多时,通常采用动态显示方式。
所谓动态显示方式,是将所有数码管的段选线并联在一起,由一个8位I/O口控制。而公共端分别由不同的I/O线控制,通过程序实现各位的分时选通。在多位LED显示时,动态显示方式能够简化电路,降低成本 。
位选端决定每个数码管的显示,通过人眼难以察觉的显示先后,来实现同时显示。

#include
unsigned int i,j;
unsigned char buf[2],n=-1,m=0xff;
unsigned char code discodey[12]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
void delay(){ //延迟函数
unsigned int y;
for(y=0;y<200;y++);
}
void dis(unsigned int temp){ //显示界面
buf[0]=temp/10; //获取十位和个位数字
buf[1]=temp%10;
if(temp==0xff){
P0=0xff;
}
else{
for(i=0;i<2;i++){ //动态显示
P1=(0x01<
P0=discodey[buf];
delay();
P0=0xff;
}
}
}
unsigned char keyscan(){ //键扫描子程序,带返回值
unsigned char row,col=0,m=0xff; //定义行号,列号,键值(0xff)
P2 = 0xf0;
if((P2&0xf0)==0xf0) //列值全为1,无按下
return m; //返回键值0xff
delay(); //有键按下,延时去抖
if((P2&0xf0)==0xf0) //无键按下,说明上次是抖动引起的
return m; //返回0xff
for(row=0;row<4;row++){ //仍然有键按下,从0开始逐行扫描
P2=~(1<
m=P2&0xf0; //读列线状态
if(m!=0xf0) //不全为1
{
while(m&(1<<(col+4)))
col++; //所按键不在该列,查找下一列号
if(n==row*4+col) //判断是否按了两次,键值加3
m=row*4+col+3;
else
{
n=m=row*4+col; //计算键值
}
P2=0xf0;
while((P2&0xf0)!=0xf0); //键未抬起,等待
break;
}
}
return m; //返回键值
}
void main(){
P2=0;
P1=0;
P0=0xff;
while(1){
dis(keyscan());
}
}
问题
单片机AT89C51的P2口外接一4×4矩阵键盘,P1口外接两位LED数码管。编写键盘扫
描程序和显示程序。实现功能如下:按下某按键时,数码管上显示该键对应的键值0
~15。如果连续第二次按下该键,则数码管显示的数值为该键值加3
在单片机系统中,LED数码管的显示程序根据实际需要分为静态显示和动态显示两种方式。
所谓静态显示,是当数码管显示某个字符时,公共端接固定电平,相应段的发光二极管恒定地导通或截止,直到显示另一个字符为止。 采用数码管静态显示方式,单片机显示程序比较简单,数码管显示亮度稳定。但因为每一个数码管都需要一个8位的端口来控制,占用资源较多,一般适用于显示位数较少的场合。
当单片机系统显示的数据位数较多时,通常采用动态显示方式。
所谓动态显示方式,是将所有数码管的段选线并联在一起,由一个8位I/O口控制。而公共端分别由不同的I/O线控制,通过程序实现各位的分时选通。在多位LED显示时,动态显示方式能够简化电路,降低成本 。
位选端决定每个数码管的显示,通过人眼难以察觉的显示先后,来实现同时显示。

#include
unsigned int i,j;
unsigned char buf[2],n=-1,m=0xff;
unsigned char code discodey[12]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
void delay(){ //延迟函数
unsigned int y;
for(y=0;y<200;y++);
}
void dis(unsigned int temp){ //显示界面
buf[0]=temp/10; //获取十位和个位数字
buf[1]=temp%10;
if(temp==0xff){
P0=0xff;
}
else{
for(i=0;i<2;i++){ //动态显示
P1=(0x01<
P0=discodey[buf];
delay();
P0=0xff;
}
}
}
unsigned char keyscan(){ //键扫描子程序,带返回值
unsigned char row,col=0,m=0xff; //定义行号,列号,键值(0xff)
P2 = 0xf0;
if((P2&0xf0)==0xf0) //列值全为1,无按下
return m; //返回键值0xff
delay(); //有键按下,延时去抖
if((P2&0xf0)==0xf0) //无键按下,说明上次是抖动引起的
return m; //返回0xff
for(row=0;row<4;row++){ //仍然有键按下,从0开始逐行扫描
P2=~(1<
m=P2&0xf0; //读列线状态
if(m!=0xf0) //不全为1
{
while(m&(1<<(col+4)))
col++; //所按键不在该列,查找下一列号
if(n==row*4+col) //判断是否按了两次,键值加3
m=row*4+col+3;
else
{
n=m=row*4+col; //计算键值
}
P2=0xf0;
while((P2&0xf0)!=0xf0); //键未抬起,等待
break;
}
}
return m; //返回键值
}
void main(){
P2=0;
P1=0;
P0=0xff;
while(1){
dis(keyscan());
}
}
举报