一. 键盘检测
键盘分为编码键盘和非编码键盘。
编码键盘 :键盘上闭合键的识别由专用的硬件编码器实现,并产生键编码号或者键值,如计算机键盘。
非编码键盘:靠软件编程来识别。
在单片机组成的各种系统中,用的较多的是非编码键盘。编码键盘又分为独立键盘和行列式键盘(矩阵式键盘)。
1. 独立键盘
单片机系统中常见的几种按键:弹性按键,贴片按键,自锁按键
编写单片机的键盘检测程序时,一般在检测按下时加入去抖延时,检测松手时就不用加了。
案例1:用数码管的前两位显示一个十进制数,变化范围为00-59,开始时显示00,每按下S2键1次,数值加1;每按下S3键1次,数值减1;每按下S4键1次数值归零;按下S5键1次,利用定时器功能使数值开始自动每秒加1,再次按下S5键,数值停止自动加1,保持显示原数。
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned intsbit key1 = P3^4;
sbit key2 = P3^5;
sbit key3 = P3^6;
sbit key4 = P3^7;
sbit dula = P2^6; //U1锁存器的锁存端
sbit wela = P2^7; //U2锁存器的锁存端uchar code table[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};void delayms(uint);
uchar numt0, num;/***数码管显示函数***/
void display(uchar numdis)
{uchar shi,ge;shi = numdis/10;he = numdis%10;dula = 1;P0 = table[shi]; //送十位段选数据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;i>0;j--);}
}/***初始化函数***/
void init()
{TMOD = 0x01; //设置定时器0为工作方式1TH0 = (65536-45872)/256; //装初值50ms一次中断TL0 = (65536-45872)%256; EA = 1; //开总中断ET0 = 1; //开定时器0中断
} /***键盘扫描函数***/
void keyscan()
{if(0 == key1){delayms(10);if(0 == key1){num++;if(60 == num){num = 0}while(!key1); //等待按键释放}}if(0 == key2){delayms(10);if(0 == key2){if(0 == num){num = 60}num--;while(!key2); }}if(0 == key3){delayms(10);if(0 == key3){num = 0;while(!key3);}}if(0 == key4){delayms(10);if(0 == key4){while(!key4); TR0 = ~TR0; //启动或者停止定时器0}}
}void main()
{init();while(1){keyscan();display(num);}
}/***定时器中断函数***/
void T0_time() interrupt 1
{TH0 = (65536-45872)/256; //重装初值TL0 = (65536-45872)%256; numt0++;if(20 == numt0){numt0 = 0;num++; if(60 == num){num = 0;} }
}
2. 矩阵键盘
独立键盘有一端固定为低电平,单片机写程序检测时比较方便。而矩阵键盘两端都与单片机I/O口相连,因此在检测时需人为通过单片机I/O口送出低电平。
检测时,先送一列为低电平,其余几列全为高电平(此时我们确定了列数),然后立即轮流检测一次各行是否有低电平,若检测到某一行为低电平(这时我们又确定了行数),则我们可以确定当前被按下的键是哪一行哪一列的。用同样的方法轮流送各列一次低电平,再轮流检测一次各行是否变为低电平,这样即可检测完所有的按键,当有按键被按下时便可判断出按下的键是哪一个键。
案例2:实验板上电时,数码管不显示,顺序按下矩阵键盘后,在数码管上依次显示0-F,6个数码管同时静态显示即可。
其中,矩阵键盘的4行分别与单片机的P3.0-P3.3相连,4列分别与P3.4-P3.7相连。
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned intsbit dula = P2^6; //U1锁存器的锁存端
sbit wela = P2^7; //U2锁存器的锁存端uchar code table[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};/***延时函数***/
void delayms(uint xms)
{uint i ,j;for(i= xms; i>0 ; i--){for(j =110;i>0;j--);}
}/***数码管显示函数***/
void display(uchar num)
{P0 = table[num]; //显示函数只送段选数据dula = 1;dula = 0;
}/***矩阵键盘扫描函数***/
void matrixkeyscan()
{uchar temp,key;//第一行P3 = 0xfe;temp = P3;temp = temp & 0xf0; //用于判断temp高4位是否有0if(0xf0 != temp) /*temp的高4位数据实际上就是矩阵键盘的4个列线,若temp不等于0xf0,说明有键被按下*/{delayms(10); //延时去抖temp = P3;temp = temp & 0xf0;if(0xf0 != temp){temp =P3;switch(temp){case 0xee:key = 0;break;case 0xde:key = 1;break;case 0xbe:key =2;break;case 0x7e:key = 3;break;}while(temp!=0xf0) //等待按键释放{temp = P3;temp = temp & 0xf0;}display(key); //显示}}//第2行P3 = 0xfd;temp = P3;temp = temp & 0xf0;if(0xf0 != temp){delayms(10);temp = P3;temp = temp & 0xf0;if(0xf0 != temp){temp =P3;switch(temp){case 0xed:key = 4;break;case 0xdd:key = 5;break;case 0xbd:key =6;break;case 0x7d:key = 7;break;}while(temp!=0xf0) //等待按键释放{temp = P3;temp = temp & 0xf0;}display(key); //显示}}//第3行P3 = 0xfb;temp = P3;temp = temp & 0xf0;if(0xf0 != temp){delayms(10);temp = P3;temp = temp & 0xf0;if(0xf0 != temp){temp =P3;switch(temp){case 0xeb:key = 8;break;case 0xdb:key = 9;break;case 0xbb:key = 10;break;case 0x7b:key = 11;break;}while(temp!=0xf0) //等待按键释放{temp = P3;temp = temp & 0xf0;}display(key); //显示}}//第4行P3 = 0xf7;temp = P3;temp = temp & 0xf0;if(0xf0 != temp){delayms(10);temp = P3;temp = temp & 0xf0;if(0xf0 != temp){temp =P3;switch(temp){case 0xe7:key = 12;break;case 0xd7:key = 13;break;case 0xb7:key =14;break;case 0x77:key = 15;break;}while(temp!=0xf0) //等待按键释放{temp = P3;temp = temp & 0xf0;}display(key); //显示}}
}void main()
{P0 = 0; //关闭所有数码管段选dula = 1;dula = 0;P0 = 0xc0; //位选中所有数码管wela = 1;wela = 0;while(1){matrixkeyscan(); //不停调用键盘扫描程序}
}