这是个矩阵按键,按下任意一个按键,数码管显示从0-F的值。
单片机C语言源程序如下:
- #include<reg52.h>
- sbit ADDR0 = P1^0;
- sbit ADDR1 = P1^1;
- sbit ADDR2 = P1^2;
- sbit ADDR3 = P1^3;
- sbit ENLED = P1^4;
- sbit KeyIn_1 = P2^7;
- sbit KeyIn_2 = P2^6;
- sbit KeyIn_3 = P2^5;
- sbit KeyIn_4 = P2^4;
- sbit KeyOut_1 = P2^3;
- sbit KeyOut_2 = P2^2;
- sbit KeyOut_3 = P2^1;
- sbit KeyOut_4 = P2^0;
- unsigned char code LedChar[16] = { //数码管真值表
- 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
- 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
- };
- unsigned char keyStatus[4][4] = { //全部矩阵按键当前的状态
- {1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}
- };
- void main(){
- unsigned char i,j;
- unsigned char cnt = 0;
- unsigned char backUp[4][4] = {{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}}; //按键状态,保存前一次的值
- EA = 1;
- ENLED = 0;
- ADDR3 = 1;
- ADDR2 = 0;
- ADDR1 = 0;
- ADDR0 = 0;
- TMOD = 0x01;
- TH0 = 0xFC;
- TL0 = 0x67;
- ET0 = 1;
- TR0 = 1;
- P0 = LedChar[cnt];
-
- while(1){
- for(i = 0; i < 4; i++){
- for(j = 0;j < 4; j++){
- if(backUp[i][j] != keyStatus[i][j]){
- if(backUp[i][j] == 0){ //按键抬起
- cnt++;
- if(cnt >= 16){
- cnt = 0;
- }
- P0 = LedChar[cnt];
- }
- backUp[i][j] = keyStatus[i][j];
- }
- }
- }
- }
- }
- /*T0中断服务函数,判断按键状态并消抖*/
- void interruptTimer0() interrupt 1{
- unsigned char i;
- static unsigned char keyOut = 0;
- static unsigned char keyBuff[4][4] = {
- {0xFF,0xFF,0xFF,0xFF},{0xFF,0xFF,0xFF,0xFF},{0xFF,0xFF,0xFF,0xFF},{0xFF,0xFF,0xFF,0xFF} //矩阵按键扫描缓冲区
- };
- TH0 = 0xFC;
- TL0 = 0x67;
- keyBuff[keyOut][0] = (keyBuff[keyOut][0] << 1) | KeyIn_1; //按位与,将KeyIn_1的最后一位移入缓冲区。按位与的结果:最后1位是0就移入0,是1就移入1。
- keyBuff[keyOut][1] = (keyBuff[keyOut][1] << 1) | KeyIn_2; //按位与,将KeyIn_2的最后一位移入缓冲区。按位与的结果:最后1位是0就移入0,是1就移入1。
- keyBuff[keyOut][2] = (keyBuff[keyOut][2] << 1) | KeyIn_3; //按位与,将KeyIn_3的最后一位移入缓冲区。按位与的结果:最后1位是0就移入0,是1就移入1。
- keyBuff[keyOut][3] = (keyBuff[keyOut][3] << 1) | KeyIn_4; //按位与,将KeyIn_4的最后一位移入缓冲区。按位与的结果:最后1位是0就移入0,是1就移入1。
- //更新消抖状态
- for(i = 0; i <= 3 ; i++){
- if((keyBuff[keyOut][i] & 0x0F) == 0x00){
- keyStatus[keyOut][i] = 0;
- }
- else if((keyBuff[keyOut][i] & 0x0F) == 0x0F){
- keyStatus[keyOut][i] = 1;
- }
- }
- //执行下一次的扫描输出
- keyOut++;
- if(keyOut > 4){
- keyOut = 0;
- }
- //根据索引keyOut,释放当前输出引脚,拉低下次的输出引脚。
- switch(keyOut){
- case 0: KeyOut_4 = 1; KeyOut_1 = 0; break;
- case 1: KeyOut_1 = 1; KeyOut_2 = 0; break;
- case 2: KeyOut_2 = 1; KeyOut_3 = 0; break;
- case 3: KeyOut_3 = 1; KeyOut_4 = 0; break;
- default: break;
- }
- }
复制代码
问题:其中这段代码放在switch的前面,有一排按键按下,数码管就一直在累加。
虽然keyOut初始值为0,++一次为1,错过了keyOut为0的判断,但是KeyOut加到4的时候,就置0了,下一轮,case0就可以覆盖的到。
- //执行下一次的扫描输出
- keyOut++;
- if(keyOut > 4){
- keyOut = 0;
- }
复制代码
这段代码放到switch后就ok了,但是逻辑上我 实在不明白为什么放在前面就不可以。求各位大神给指点一下,答疑解惑!
|