**4.1 关于独立键盘**
是第一天在这里记相应的学习笔记。日后一定依据学习的频率和时间随时更。
关于按键,51单片机里比较常见的是他的开关(自锁式小按键,弹性很好)以及常用的矩阵键盘上的弹性按键。这个按键当矩阵按键时是以输入口的方式使用的。且一般都会给键盘相接的I/O口以高电平。单片机需要检测的是I/O这路是否处于高电平状态。
由图所示,当开关按下后,I/O接地,则为低电平。在这里规定开关导通低电平,断开高电平。
另外,在单片机开发中一般使用软件去抖的方法,即通过延时避开震荡的波形。
如果抖动是8ms的话 delay 10ms就够了。
独立键盘与8051芯片的连接图如下,可以发现在这里几个按键键盘的一端接到了一起并接地。
下来用一个实际程序来演示一下独立键盘的操作。
分析:
可以看到这是一个十分基本的键盘操作,其中:
1.变化范围0-59意味着要做循环,当有大于59数出现时要置零
2.开始显示是00说明是两位数码管,分为十位和个位,写出unchar code table[]的数组后,dula段选对应数组中的值,wela位选对应地址。
3.要用到定时器的中断功能,可用定时器0/1的第一方式。S5这里可以考虑对TR0取反,这样子可以实现工作状态的变化。
下面是代码部分,有详细的注释
4.50ms*20=1s 体现在(65536-45872)
#define uchar unsigned char
#define uint unsigned int
sbit key1=P3^4;
sbit key2=P3^5;
sbit key3=P3^6;
sbit key4=P3^7;
sbit dula=P2^6;
sbit wela=P2^7;
//提示 如果主函数没有思路,可以先一步一步写好子函数,之后思路就清楚了
/*加延时的目的是因为单片机执行速度快,且是循环检测按键,
若不加延时可能会出现一个循环体中程序被执行好几次的情况*/
uchar code table[]=
{0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};//LED数码管显示,由1--F
void delayms(uint);//提前声明延时函数
uchar numt0,num;//定义无符号的两个变量,其中num应该是秒数
void display(uchar numdis)//显示子函数
{
uchar shi,ge;
shi=numdis/10;
ge=numdis%10;
dula=1;//段选(与数码管显示有关)
P0=table[shi];//打开寄存器。让P0端口(接收到?)
dula=0;
P0=0xff;
wela=1;//位选。要把东西(显示出来的)送到哪个相应的地址
P0=0xfe;
wela=0;
delayms(5);
dula=1;//个位十位分别都得送一次吧
P0=table[ge];
dula=0;
P0=0xff;
wela=1;
P0=0xfd;//送到十位对应的数码管上去
wela=0;
delayms(5);
}
void delayms(uint xms)//延时子程序
{
uint i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
void init()//初始化程序
{
TMOD=0x01;//定时器0的方式一
TH0=(65536-45872)/256;//20ms
TL0=(65536-45872)%256;//这样子其实储存了20ms所包含的全部信息
EA=1;//总使能--开总中断?
ET0=1;//开定时器0的中断
}
void keyscan()//键盘扫描函数
{
if(key1==0)//键盘1功能,按下一次加1
delayms(10);//软件延时,防抖动
if(key1==0)
{
num++;
if(num==60)
{
num=0;
}
while(!key1);//给一个死循环
}
if(key2==0)//键盘2功能,按一次减一,到零自动到59(注意59和60之间的设置关系)
{
delayms(10);
if(key2==0)
{
if(num==0)
num=60;
num--;
while(!key2);
}
}
if(key3==0)//直接置零
{
delayms(10);
if(key3==0)
{
num=0;
while(!key3);
}
}
if(key4==0)//防抖+改变数码管的状态(计数/停止,这个就可以借助TR0)
{
delayms(10);
if(key4==0)
{
while(!key4);
{
TR0=~TR0;
}
}
}
}
void main()//主函数
{
init();//初始化
while(1)//构造循环体,其中包括键盘输入功能(低电平有效)以及显示功能
{
keyscan();
display(num);//显示功能是通过寄存器dula和wela控制段选与位选
}
}
void T0_tinme()interrupt 1//中断函数1
{
TH0=(65536-45872)/256;
TL0=(65536-45872)%256;
numt0++;
if(numt0==20)//代表1s到了
{
numt0=0;
num++;
if(num==60)//60秒到,一个周期结束
num=0;
}
}
4.2 矩阵键盘的检测
矩阵键盘就是在独立键盘基础上加了行列检测。
以常用的4*4为例,即先给一行(1-4行)高电平,再检测1-4列中有没有出现低电平,如果出现低电平就看好是哪个列出现如此问题,从而确定按键的位置(用坐标地址的形式表示)。
原理图与独立键盘的差别在于这里的行跟列接在了一起,形成了一个四行四列的便于检索的电路。当行给高电平后,检测对应列就可。
下面是一个例题。
分析:
-
是要按矩阵键盘上的16位依次操作显示出数码管上的0-15
-
函数display(),用来点亮数码管,这其中应有dula和wela两个寄存器的使能端
-
函数delayms()用于延时
-
函数matrixscan()用于矩阵键盘的检测,这其中分为四个大部分,分别为对1/4行操作后----对所有列(1-4)进行检索。
直接上代码了
```c
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit dula=P2^6;
sbit wela=P2^