/**
* 文件名称:矩阵键盘实验
* 实验目的:1.掌握矩阵键盘扫描的基本原理
* 2.掌握按键扫描及消除抖动的基本原理
* 程序说明:1.使用程序前,将跳线J2调整为KBD模式
* 2.按键功能可参考按键处理函数: void key_proc(uint8_t key);
*/
#include <reg52.h> //定义51单片机特殊功能寄存器
typedef unsigned char uint8_t;
volatile bit key_flag;
uint8_t tmr0LowByte, tmr0HighByte;
uint8_t read_keyboard();
void key_proc(uint8_t key);
void main() {
uint8_t key_temp = 0xFF;
tmr0HighByte = (65536 - 2000) >> 8;
tmr0LowByte = (uint8_t)(65536 - 2000);
TMOD |= 0x01; //配置定时器工作模式
TH0 = tmr0HighByte;
TL0 = tmr0LowByte;
EA = 1;
ET0 = 1; //打开定时器中断
TR0 = 1; //启动定时器
while(1) {
if (key_flag) {
key_flag = 0;
key_temp = read_keyboard();
}
key_proc(key_temp);
key_temp = 0xFF; //清除旧键值
}
}
//定时器中断服务函数,2ms执行一次。
void tmr0ISR() interrupt 1 {
static uint8_t intr;
TH0 = tmr0HighByte; //定时器重载
TL0 = tmr0LowByte;
if (++intr == 10) {
intr = 0;
key_flag = 1; //20ms按键扫描标志位置1
}
}
//读取矩阵键盘键值
uint8_t read_keyboard() {
static uint8_t col, key_press, key_value;
static bit key_re;
uint8_t key_temp;
P3 = 0xf0;
key_temp = (P3 & 0xf0);
if (key_temp != 0xf0) //有按键按下
key_press++;
else
key_press = 0; //抖动
if (key_press == 3) {
key_press = 0;
key_re = 1;
switch (key_temp) {
case 0x70:
col = 1; //第一列按键按下
break;
case 0xb0:
col = 2; //第二列按键按下
break;
case 0xd0:
col = 3; //第三列按键按下
break;
case 0xe0:
col = 4; //第四列按键按下
break;
}
P3 = 0x0f;
key_temp = (P3&0x0f);
switch (key_temp) {
case 0x0e:
key_value = (col - 1); //第一行按键按下
break;
case 0x0d:
key_value = (3 + col); //第二行按键按下
break;
case 0x0b:
key_value = (7 + col); //第三行按键按下
break;
case 0x07:
key_value = (11 + col); //第四行按键按下
break;
}
}
//连续三次检测到按键被按下,并且该按键已经释放
P3 = 0x0f;
key_temp = (P3 & 0x0f);
if ((key_re == 1) && (key_temp == 0x0f)) {
key_re = 0;
return key_value;
}
return 0xff; //无按键按下或被按下的按键未被释放
}
//按键处理函数:S7,S11
void key_proc(uint8_t key) {
switch (key) {
case 0: //
P2 = ((P2 & 0x1f) | 0x80);
P0++;
P2 &= 0x1f;
break;
case 1: //
P2 = ((P2 & 0x1f) | 0x80);
P0--;
P2 &= 0x1f;
break;
}
}