版权声明: https://blog.csdn.net/JRK_CSDN/article/details/87444489
需要理解
Q:
- 按键消抖时间在20ms左右
- CLK为12MHz的51单片机的指令周期大约是2us(1ms约可执行500条指令)(意在说明不影响程序正常运行,例如数码管刷新效果可以维持下去)
S:
- 用定时器产生1ms中断,维持键盘“实时”扫描
- 沿用
行列扫描
的思维,形成扫描循环(即 释放当前输出引脚,拉低下次的输出引脚)
U:
- 一个定时器中断
- 8个I/O接口
- 约5ms的执行时间
A:
## Config ##
## 注意:该驱动扫描为行索引,即每次扫描 一行 ,每 1ms 扫描一次
全键盘4ms扫描完成,按键经4次(即 16ms)确认后判为按下(KeySta变为0,触发KeyAction)
回弹后,16ms恢复状态(KeySta变为1)
KEY_OUT_1 = P*^*; //扫描输出
KEY_OUT_2 = P*^*;
KEY_OUT_3 = P*^*;
KEY_OUT_4 = P*^*;
KEY_IN_1 = P*^*; //扫描输入
KEY_IN_2 = P*^*;
KEY_IN_3 = P*^*;
KEY_IN_4 = P*^*;
//“实时”状态缓冲区
u8 KeySta[4][4] = { {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1} };
u8 code KeyCodeMap[4][4] = {
{'1', '2', '3', 0x19},
{'4', '5', '6', 0x18},
{'7', '8', '9', 0x17},
{'0', 0x1B,0x0D,0x16}
}; //''为字符,标准ASCII码,'1'即为0x31,两种写法均可
void KeyScan() //在定时器中断中调用,达到1ms扫描一列
{
u8 i;
static u8 keyout = 0;
static u8 key_buff[4][4] = {
{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF},
{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}
}; //需要扫描4次,也就是4次移位:0XFF → 0XFE → 0XFC → 0XF8 → 0XF0
switch(keyout) //释放输出引脚,拉低下一扫描输出引脚(推荐先释放,毕竟是规范)
{
case 0: KEY_OUT_4 = 1; KEY_OUT_1 = 0; break;
case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break;
case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break;
case 3: KEY_OUT_3 = 1; KEY_OUT_4 = 0; break;
default: break;
}
key_buff[keyout][0] = (key_buff[keyout][0] << 1) | KEY_IN_1;
key_buff[keyout][1] = (key_buff[keyout][1] << 1) | KEY_IN_2;
key_buff[keyout][2] = (key_buff[keyout][2] << 1) | KEY_IN_3;
key_buff[keyout][3] = (key_buff[keyout][3] << 1) | KEY_IN_4;
for (i=0; i<4; i++) //每行4个按键,所以循环4次
{
if ((key_buf[keyout][i] & 0x0F) == 0x00) //低电平优先,为0即为按下
{ //连续4次扫描值为0,即4*4ms内都是按下状态时,可认为按键已稳定的按下
Key_Sta[keyout][i] = 0;
}
else if ((key_buf[keyout][i] & 0x0F) == 0x0F)
{ //连续4次扫描值为1,即4*4ms内都是弹起状态时,可认为按键已稳定的弹起
Key_Sta[keyout][i] = 1;
}
}
keyout++; //输出索引递增
keyout = keyout & 0x03; //索引值加到4即归零
void KeyDriver() //主循环调用
{
u8 i, j;
static u8 backup[4][4] = { {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1} };
//数电-锁存器思维,保存上一状态进行比较
for(i=0; i<4; i++)
{
for(j=0; j<4; j++)
{
if(backup[i][j] != KeySta[i][j])
{
if(backup[i][j] != 0)
{
KeyAction(KeyCodeMap[i][j]); //动作函数,暂未定义
}
}
backup[i][j] = KeySta[i][j];
}
}
}