1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
| #include <REGX51.H> #include "LCD1602.H"
/\*\*\* 0-15键值 \*\*\*/ /\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* 0x77,0x7B,0x7D,0x7E 0xB7,0xBB,0xBD,0xBE 0xD7,0xDB,0xDD,0xDE 0xE7,0xEB,0xED,0xEE
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
unsigned char Key\_Scan(); //按键扫描函数声明
/\* 主函数从这里开始 \*/ void main(void) { static unsigned char Key_Code = 0x00; //定义一个静态变量 LCD\_Init(); //初始化LCD1602,用来显示键值 LCD\_ShowString(1,3,"Matrix Key"); while(1) { Key_Code = Key\_Scan(); switch (Key_Code) //演示示例;用switch语句操作键码;比如我在1602液晶屏上显示数字1-16;也可以用数组来操作,自由发挥! { case 0x77: LCD\_ShowNum(2,6,1,2); break; case 0x7B: LCD\_ShowNum(2,6,2,2); break; case 0x7D: LCD\_ShowNum(2,6,3,2); break; case 0x7E: LCD\_ShowNum(2,6,4,2); break; case 0xB7: LCD\_ShowNum(2,6,5,2); break; case 0xBB: LCD\_ShowNum(2,6,6,2); break; case 0xBD: LCD\_ShowNum(2,6,7,2); break; case 0xBE: LCD\_ShowNum(2,6,8,2); break; case 0xD7: LCD\_ShowNum(2,6,9,2); break; case 0xDB: LCD\_ShowNum(2,6,10,2); break; case 0xDD: LCD\_ShowNum(2,6,11,2); break; case 0xDE: LCD\_ShowNum(2,6,12,2); break; case 0xE7: LCD\_ShowNum(2,6,13,2); break; case 0xEB: LCD\_ShowNum(2,6,14,2); break; case 0xED: LCD\_ShowNum(2,6,15,2); break; case 0xEE: LCD\_ShowNum(2,6,16,2); break; default: break; } } }
/\* 带返回值的按键扫描函数\*/ unsigned char Key\_Scan() { unsigned char Key_Temp; //定义一个存放组合键码的变量 unsigned char Key_A,Key_B; // 定义两个变量,Key\_A 用于存放正向扫描的键码; Key\_B 用于存放反向扫描的键码。 P1 = 0xF0; //把P1口的高4位(P1.4-P1.7)置高,低4位置低;(如果有按键按下 高4位肯定有一条线会被拉低)。 Key_Temp = P1; //把P1口的状态读回来,传递给Key\_Temp。没有按键按下Key\_Temp肯定是0XF0; 否则就是其它的数; if(Key_Temp!= 0xF0) // 进入if判断语句;如果Key\_Temp不等于0XF0,说明有键按下了。 { Key_A = P1; // 把P1口此时被按下的状态传递给Key\_A保存 P1 = 0x0F; //开始反转扫描;把P1口的高4位置低,低4位(P1.0-P1.3)置高;(如果有按键按下 低4位肯定有一条线会被拉低)。 Key_B = P1; //把P1口此时被按下的状态传递给Key\_A保存 }
Key_Temp = (Key_A | Key_B); //把正反两次扫描的结果相或, 就会得到按键按下的正确键码 return Key_Temp; //把键码返回,给其他的函数调用 }
//下面是图解正反转扫描的程序工作原理
/\* 正向扫描,比如P1.7和P1.3连接的按键被按下 那么P1口的0XF0:1111 0000 就会变成0X70:0111 0000
P1.3 P1.2 P1.1 P1.0 0 0 0 0 P1.7 1 -+- --- --- ---
P1.6 1 --- --- --- ---
P1.5 1 --- --- --- ---
P1.4 1 --- --- --- ---
反向扫描,比如P1.7和P1.3连接的按键被按下 那么P1口的0X0F:0000 1111 就会变成0X07:0000 0111
P1.3 P1.2 P1.1 P1.0 1 1 1 1 P1.7 0 -+- --- --- ---
P1.6 0 --- --- --- ---
P1.5 0 --- --- --- ---
P1.4 0 --- --- --- ---
最后把 正反两次扫描的结果 0X70 与0X07相或 就会得到0X77的键码 只要得到正确的键码,就可以用这个键码做任何事情。比如我在液晶屏上显示数字1;表示数字1键被按下。 \*/
//下面这组键值根据不同的接线方式,会有不同的键值,需要提前自己算好;就类似数码管的段码一样;也可以做成一个数组。 /\*\*\* 0-15键值 \*\*\*/ /\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* 0x77,0x7B,0x7D,0x7E 0xB7,0xBB,0xBD,0xBE 0xD7,0xDB,0xDD,0xDE 0xE7,0xEB,0xED,0xEE
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
|