使用某C51学习板,编写一个C51程序,实现如下功能
1)启动时,数码管显示11, 代表第1行第1列
2)按下矩阵键盘中某键时,数码管显示按键对应的行号和列号,例如23代表2行3列
3)按下K1时,行号显示减小1,如行号等于1不再减小
4)按下K2时,行号显示增加1,如行号等于4不再增加
5) 按下K3时,列号显示减小1,如列号等于1不再减小
6) 按下K4时,列号显示增加1,如列号等于4不再增加
#include <reg51.h>
typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;
//定义四个独立按键
sbit K1=P3^1;
sbit K2=P3^0;
sbit K3=P3^2;
sbit K4=P3^3;
//定义矩阵按钮的端口
#define AnNiu P1
//定义数码管段码口
#define SMG P0
//定义数码管位选信号控制脚
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
//共阴极数码管显示0~F的段码数据
u8 gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
u16 x=1;//定义一个变量存储按键的值
u16 num=0;//定义一个变量存储按键返回的值
//延时
void delay_10us(u8 ten_us)
{
while(ten_us--);
}
//矩阵按键
u16 key_discern(void)
{
AnNiu=0xf7;//第一列为低电平
if(AnNiu!=0xf7)
{
delay_10us(1000);
switch(AnNiu)
{
case 0x77:x=1;break;
case 0xb7:x=5;break;
case 0xd7:x=9;break;
case 0xe7:x=13;break;
}
}
AnNiu=0xfb;//第二列为低电平
if(AnNiu!=0xfb)
{
delay_10us(1000);
switch(AnNiu)
{
case 0x7b:x=2;break;
case 0xbb:x=6;break;
case 0xdb:x=10;break;
case 0xeb:x=14;break;
}
}
AnNiu=0xfd;//第三列为低电平
if(AnNiu!=0xfd)
{
delay_10us(1000);
switch(AnNiu)
{
case 0x7d:x=3;break;
case 0xbd:x=7;break;
case 0xdd:x=11;break;
case 0xed:x=15;break;
}
}
AnNiu=0xfe;//第四列为低电平
if(AnNiu!=0xfe)
{
delay_10us(1000);
switch(AnNiu)
{
case 0x7e:x=4;break;
case 0xbe:x=8;break;
case 0xde:x=12;break;
case 0xee:x=16;break;
}
}
return x;
}
//显示数码管
void smg_display(void)
{
//行的数码管
LSC=1;LSB=1;LSA=1;
SMG=gsmg_code[(num-1)/4+1];//传送段选数据
delay_10us(100);//延时一段时间,等待显示稳定
SMG=0x00;//消隐
//列的数码管
LSC=1;LSB=1;LSA=0;
SMG=gsmg_code[(num-1)%4+1];//传送段选数据
delay_10us(100);//延时一段时间,等待显示稳定
SMG=0x00;//消隐
}
void main()
{
while(1)
{
num=key_discern();
//按键消抖
if(K1==0||K2==0||K3==0||K4==0)
{
delay_10us(1000);
//K1按键控制行的减
if(K1==0&&x>4&&x<=16)
{
x=x-4;
while(1)//等待K1松开
{
;
if(K1!=0)
break;
}
}
//K2按键控制行的加
if(K2==0&&x>=1&&x<=12)
{
x=x+4;
while(1)//等待K2松开
{
;
if(K2!=0)
break;
}
}
//K3按键控制列的减
if(K3==0&&x>1&&x<=16)
{
if((x-1)/4==(x-1-1)/4)//检测是否在同一行(现键位的行与前一个键位的行比较)
x=x-1;
while(1)//等待K3松开
{
;
if(K3!=0)
break;
}
}
//K4按键控制列的加
if(K4==0&&x>=1&&x<16)
{
if((x-1)/4==(x+1-1)/4)//检测是否在同一行(现键位的行与后一个键位的行比较)
x=x+1;
while(1)//等待K4松开
{
;
if(K4!=0)
break;
}
}
}
//显示数码管
smg_display();
}
}