1.键盘的分类
编码键盘:键盘上闭合键的识别由专用的硬件编码器实现,并产生键编码号或键值的称为编码键盘,如计算机键盘
非编码键盘:靠软件编程来识别的称为非编码键盘。独立键盘、矩阵键盘
2.按键消抖
如图,理想波形与实现波形之间是有区别的。实际波形在按下和释放的瞬间都有抖动现象,抖动事件的长短与按键的机械特性有关,一般为5~10ms。通常我们手动按下键然后立即释放,这个动作中稳定闭合时间超过20ms。因此检测键盘是否按下时,需加上去抖动操作。
一般有两种消抖方式:
硬件消抖:如图。或有专门去抖动的芯片。
软件消抖:通常用delay函数,将抖动的时间延时。
3.独立键盘
1 //独立键盘检测 + 数码管显示所按值 2 #include <reg52.h> 3 void delay_ms(unsigned int n); 4 sbit Key1 = P3^4; 5 sbit Led1 = P1^0; 6 7 int main() 8 { 9 Key1 = 1; 10 Led1 = 1; 11 while(1) 12 { 13 if(Key1 == 0) { 14 delay_ms(20); //消抖 15 if(Key1 == 0) { 16 Led1 =! Led1; 17 while(!Key1); //等待按键释放 18 } 19 } 20 } 21 return 0; 22 } 23 24 void delay_ms(unsigned int n) //误差 -0.651041666667us 25 { 26 unsigned char a,b; 27 unsigned int i; 28 for(i = 0; i < n; i++) { 29 for(b=4;b>0;b--) 30 for(a=113;a>0;a--); 31 } 32 }
4.矩阵键盘
矩阵键盘模块示意图(根据模块电路即与I/O口相连情况简化)
(这里用的方法,自认为比郭天祥书上的方法好、更简单)
假设按下的键为1.
P3=0xf0 //1111 0000
temp = P3 //1110 0000 (1按下)确认所在列P3.4
P3 = 0x0f //0000 1111
temp2 = P3 //0000 1110 (1按下)确认所在行P3.0
temp = temp | temp2= 0xee // 1110 0000 | 0000 1110 = 1110 1110
每个按键的最后的temp值不同,故可以用此种方法检测。
1 //矩阵键盘检测 + 数码管显示所按值 2 #include <reg52.h> 3 sbit DUAN = P2^6; 4 sbit WE = P2^7; 5 unsigned char DuanTable[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07, 6 0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71}; 7 unsigned char WeTable[] = {0xFE,0xFD,0xFB,0xF7,0xEF,0xDF}; 8 unsigned char num; 9 void delay_ms(unsigned int n); 10 unsigned char key_jz(); 11 void display(int num); 12 13 int main() 14 { 15 while(1) 16 { 17 num = key_jz(); 18 display(num); 19 } 20 return 0; 21 } 22 23 unsigned char key_jz() 24 { 25 unsigned char temp; 26 P3=0xf0; 27 temp=P3; 28 if(temp!=0xf0) 29 { 30 delay_ms(20); 31 P3=0xf0; 32 temp=P3; 33 P3=0x0f; 34 temp|=P3; 35 switch(temp) 36 { 37 case 0xee:num=1;break; //1 38 case 0xde:num=2;break; //2 39 case 0xbe:num=3;break; //3 40 case 0x7e:num=\'A\';break; //A 41 42 case 0xed:num=4;break; //4 43 case 0xdd:num=5;break; //5 44 case 0xbd:num=6;break; //6 45 case 0x7d:num=\'B\';break; //B 46 47 case 0xeb:num=7;break; //7 48 case 0xdb:num=8;break; //8 49 case 0xbb:num=9;break; //9 50 case 0x7b:num=\'C\';break; //C 51 52 case 0xe7:num=\'*\';break; //* 53 case 0xd7:num=0;break; //0 54 case 0xb7:num=\'#\';break; //# 55 case 0x77:num=\'D\';break; //D 56 57 58 } 59 60 } 61 return num; 62 } 63 void display(int num) 64 { 65 //十位数 66 DUAN = 1; 67 P0 = DuanTable[num/10]; 68 DUAN = 0; 69 P0 = 0xFF; 70 WE = 1; 71 P0 = WeTable[4]; 72 WE = 0; 73 P0 = 0xFF; 74 delay_ms(2); 75 76 //个位数 77 DUAN = 1; 78 P0 = DuanTable[num%10]; 79 DUAN = 0; 80 P0 = 0xFF; 81 WE = 1; 82 P0 = WeTable[5]; 83 WE = 0; 84 P0 = 0xFF; 85 delay_ms(1); 86 } 87 88 89 void delay_ms(unsigned int n) //误差 -0.651041666667us 90 { 91 unsigned char a,b; 92 unsigned int i; 93 for(i = 0; i < n; i++) { 94 for(b=4;b>0;b--) 95 for(a=113;a>0;a--); 96 } 97 }
按下1时,显示1 按下A时,显示A的ASCII码65