一、实验任务:
1.用单个按键控制数码管显示0-9-A-F(按一下,加1)
2.用矩阵键盘控制数码管显示矩阵键盘的位置编号(01-02----12)
二、实验目的及原理
1.实验目的:了解键盘的三种工作方式;掌握独立按键、矩阵式键盘的工作原理及编程方法;掌握如何进行按键消抖。
2.实验原理:通过0,1表示按键的状态;矩阵式键盘通过依次读取行列数据确定按键状态。
三、实验中使用的仪器与材料
Keil、PZ-ISP、普中科技51单片机、数码管、发光二极管、独立按键、矩阵式按键
四、实验方案、步骤及原始记录(数据、图表、计算等)
1.任务一:单个数码管静态显示独立按键编号
(1)用keil编写程序,输出hex文件
#include<reg52.h>
unsigned char code Tab[]= //共阴数码管段码表0-F
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
sbit key =P3^1;
void Delay1ms(unsigned int xms) //延时1ms函数
{
unsigned char i,j;
while(xms)
{
i = 2 ;
j = 239 ;
do
{
while (--j);
}
while (--i);
xms--;
}
}
void main () //主函数
{
unsigned char n = 0 ; //局部变量计位数n是段码表的位置
P0= 0x3f; //定义初始值显示0
while(1)
{
if(key == 0) //判断按键是否按下
{
Delay1ms(20); //消抖
if(key==0) //再次判断
{
while(key==0) //按键松开检测
{;}
n++;
if(n>15) //判断是否超出断码表,超出置0
n=0;
Delay1ms(300);
P0=Tab[n];
}
}
}
}
(2)将输出的hex文件烧录到开发板上
2.任务二:两个数码管动态扫描显示矩阵键盘按键编号
(1)用keil编写程序,输出hex文件
#include<reg52.h>
typedef unsigned int u16;
typedef unsigned char u8;
#define GPIO_DIG P0
#define GPIO_KEY P1
sbit LSA = P2^2; //P2_2,P2_3,P2_4控制数码管位选
sbit LSB = P2^3;
sbit LSC = P2^4;
sbit key = P3^0;
u8 KeyValue;
u8 DisplayData[2]; //分别包含个位、十位
u8 code DIG_CODE[17]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; //0-F数字
void delay(u16 i) //延时函数
{
while(i--);
}
void KeyDown(void) //判断哪个按键被按下
{
char a=0;
GPIO_KEY=0x0f; //行线置0,列线置1,读取列线
if(GPIO_KEY!=0x0f) //!=0x0f,说明有按键按下
{
delay(1000); //延时
if(GPIO_KEY!=0x0f) //再次判断有无按键按下
{
GPIO_KEY=0X0F; //行线置0,列线置1,读取列线
switch(GPIO_KEY)
{
case(0X07): KeyValue=0;break; //列线P13被置0,说明第一列有按键被按下
case(0X0b): KeyValue=1;break; //第二列有按键被按下
case(0X0d): KeyValue=2;break; //第三列有按键被按下
case(0X0e): KeyValue=3;break; //第四列有按键被按下
}
GPIO_KEY=0XF0; //列线置0,行线置1,读取行线
switch(GPIO_KEY)
{
case(0X70): KeyValue=KeyValue;break; //行线P17被置0,说明第一行有按键被按下
case(0Xb0): KeyValue=KeyValue+4;break;//第二行有按键被按下
case(0Xd0): KeyValue=KeyValue+8;break;//第三行有按键被按下
case(0Xe0): KeyValue=KeyValue+12;break;//第四行有按键被按下
}
}
}
}
void DigDisplay() //数码管显示
{
u8 i;
for(i=0;i<2;i++)
{
switch(i) //i=0首先显示个位 i=1显示十位
{
case(0):
LSA=0;LSB=0;LSC=0; break; //1号数码管亮 个位
case(1):
LSA=1;LSB=0;LSC=0; break; //2号数码管亮 十位
}
GPIO_DIG=DisplayData[i]; //数码管显示数字
delay(10); //延时
GPIO_DIG=0x00;//清屏
}
}
void main(void)
{
while(1)
{
KeyDown();//确认所按按键
if(KeyValue>0 && KeyValue< 10) //1-9按键
{
DisplayData[1] = ~DIG_CODE[0]; //十位显示0
DisplayData[0] = ~DIG_CODE[KeyValue]; //个位显示键值
}
else
{
DisplayData[1] = ~DIG_CODE[KeyValue/10]; //十位
DisplayData[0] = ~DIG_CODE[KeyValue%10]; //个位
}
DigDisplay();
}
}
(2)将输出的hex文件烧录到开发板上
五、实验结果及分析、实验过程中遇到问题及处理过程说明
1.任务一结果:
2.任务二结果:
3.遇到的问题及处理过程
在网上看到一个对端口进行位操作时未用sbit,直接P1_3,非常不理解,仔细观察他的代码后发现他的头文件为<regx52.h>,而我一般用的是<reg52.h>,查找后发现这两个头文件的位操作是不一样的,<regx52.h>可以直接P1_3,而<reg52.h>必须是P1^3;
六、实验总结及心得体会
通过本次实验,我学会了独立按键、矩阵式按键的原理及编程应用,理解了软件消抖的内部逻辑。编写代码时可以利用网上的资源,重在理解其逻辑,要看懂,还要结合自己的实验任务对代码进行修改。