按键为什么要消抖呢?
按键再按下时,由于弹片时金属的,会产生振动导致当时IO口读取电平状态错误,其次如果将手指或其他导电物体接触到键盘底部的引脚也会导致读取电平状态错误。(我之前试过在while循环中只读按键和串口发送键值,这时甚至空放也会有个别键值错误)。
什么是状态机消抖?
即使用状态机原理进行消抖,具体来说为间隔(通用消抖间隔为20ms)的调用获取键值的函数,此函数内部会根据具体状态执行相应代码(看下面示例吧,更好看)。下面是我同学根据我代码画的阉割版状态机图(我不想画了,这个图也可以实现消抖,但不是最完备的)
下面是读取键值代码,后续还有另一重状态机处理读取的键值。
/*
下面为获取当前按键键值,需要自己实现,我用的为翻转法,后续有空会专门写一篇
write_matrix_4x4(0x0f);
key_ch[0] = matrix_4x4_r11();
key_ch[1] = matrix_4x4_r21();
key_ch[2] = matrix_4x4_r31();
key_ch[3] = matrix_4x4_r41();
write_matrix_4x4(0xf0);
key_ch[4] = matrix_4x4_r51();
key_ch[5] = matrix_4x4_r61();
key_ch[6] = matrix_4x4_r71();
key_ch[7] = matrix_4x4_r81();
read_now_value = (key_ch[7] << 7) | (key_ch[6] << 6) | (key_ch[5] << 5) | (key_ch[4] << 4) | (key_ch[3] << 3) | (key_ch[2] << 2) | (key_ch[1] << 1) | key_ch[0]; //这一步为获取当前键值
*/
#define no_press_state 1 //未按下状态
#define judge_jitter_state 2 //判断抖动状态
#define press_state 3 //按下状态
byyc_u8 read_matrix_4x4()
{
byyc_u8 return_key = matrix_4x4_key_no, read_now_value;
byyc_u8 key_ch[8];
static byyc_u8 matrix_4x4_state = no_press_state, matrix_last_key_value = matrix_4x4_key_no;
write_matrix_4x4(0x0f);
key_ch[0] = matrix_4x4_r11();
key_ch[1] = matrix_4x4_r21();
key_ch[2] = matrix_4x4_r31();
key_ch[3] = matrix_4x4_r41();
write_matrix_4x4(0xf0);
key_ch[4] = matrix_4x4_r51();
key_ch[5] = matrix_4x4_r61();
key_ch[6] = matrix_4x4_r71();
key_ch[7] = matrix_4x4_r81();
read_now_value = (key_ch[7] << 7) | (key_ch[6] << 6) | (key_ch[5] << 5) | (key_ch[4] << 4) | (key_ch[3] << 3) | (key_ch[2] << 2) | (key_ch[1] << 1) | key_ch[0]; //这一步为获取当前键值
switch (matrix_4x4_state)
{
case no_press_state: //未按下状态
{
if (read_now_value != matrix_4x4_key_no) //不等于未按下的键值
{
matrix_4x4_state = judge_jitter_state; //转入判断是否抖动状态
matrix_last_key_value = read_now_value; //将当前值保存,方便后续判断抖动
}
}
break;
case judge_jitter_state: //判断抖动状态
{
if (read_now_value == matrix_last_key_value) //当前值与上次保存值相等,所以为非抖动状态
{
return_key = read_now_value; //将返回值设为当前键值
matrix_4x4_state = press_state; //转入按下状态
}
else if (read_now_value == no_press_state) //当前值与未按下的键值相等,所以为抖动状态
{
matrix_4x4_state = no_press_state; //返回未按下状态
matrix_last_key_value = read_now_value;
}
else //与保存值和未按下的键值均不相等,即键值不稳定需要再次判断
{
matrix_4x4_state = judge_jitter_state; //保持判断抖动状态(可不写)
matrix_last_key_value = read_now_value; //将当前值保存,方便后续判断抖动
}
}
break;
case press_state: //按下状态
{
if (read_now_value == matrix_last_key_value) //当前值与上次保存值相等,为按下状态
{
return_key = read_now_value; //将返回值设为当前键值(可不写)
matrix_4x4_state = press_state; //保持按下状态(可不写)
}
else if (read_now_value == no_press_state) //当前值与未按下的键值相等,按键抬起
{
matrix_4x4_state = no_press_state; //返回未按下状态
matrix_last_key_value = read_now_value;
}
else //与保存值和未按下的键值均不相等,即按键可能有新按键按下(可实现多按键一起按下)
{
matrix_4x4_state = judge_jitter_state; //转入判断抖动状态
matrix_last_key_value = read_now_value; //将当前值保存,方便后续判断抖动
}
}
break;
default:
break;
}
return return_key;
}