|
这个按键程序是看了马老师的书,改写的一个按键程序,已在仿真板通过,单键,某几个单键连_发都没有问题,但组合按键检测却存在些问题,10最合按键总有几次检测不到,不是很灵敏,程序的思路肯定是有点问题,请马老师指点下
//按键初始化
void key_board_int1(void)
{
KEY_DDR_ROW |= KEY_ROW_ALL; //行输出,
KEY_PORT_ROW &=~ KEY_ROW_ALL;
KEY_DDR_COL &=~ KEY_COL_ALL; //列输入,并使能内部上拉
KEY_PORT_COL |= KEY_COL_ALL;
}
void key_board_int2(void) //翻转
{
KEY_DDR_ROW &=~ KEY_ROW_ALL; //行输入,并使能内部上拉
KEY_PORT_ROW |= KEY_ROW_ALL;
KEY_DDR_COL |= KEY_COL_ALL; //列输出;
KEY_PORT_COL &=~ KEY_COL_ALL;
}
char read_keyboard()
{
static char key_state = 0, key_value1,key_value2;
static char key_value3,key_value4;
static int key_time = 0;
char key_return = No_key,key_value_buf;
switch (key_state)
{
case 0:
key_board_int1();
KEY_PORT_ROW &=~ KEY_ROW_ALL; // 必须送2次!!!
key_value_buf = (~KEY_ROW_ALL) & KEY_PIN_COL; // 读列电平
if (key_value_buf != No_key)
{
key_state = 1; // 有按键
break; // 转消抖确认状态
}
break;
case 1:
if (++key_time >= 8)
{
key_board_int1();
KEY_PORT_ROW &=~ KEY_ROW_ALL; // 必须送2次!!!
key_value_buf = (~KEY_ROW_ALL) & KEY_PIN_COL; // 读列电平
key_board_int2(); // 翻转
KEY_PORT_COL &=~ KEY_COL_ALL;
key_value_buf |= (~KEY_COL_ALL) & KEY_PIN_ROW; // 读行电平,并同上次上一步的结果或
key_value1 = key_value_buf;
if (key_value1 != No_key)
{
key_state = 2;
key_time = 0;
break;
}
key_state = 0;
break;
}
break;
case 2:
key_board_int1();
KEY_PORT_ROW &=~ KEY_ROW_ALL; // 必须送2次!!!
key_value_buf = (~KEY_ROW_ALL) & KEY_PIN_COL; // 读列电平
key_board_int2(); // 翻转
KEY_PORT_COL &=~ KEY_COL_ALL;
key_value_buf |= (~KEY_COL_ALL) & KEY_PIN_ROW; // 读行电平,并同上次上一步的结果或
key_value2 = key_value_buf;
if (key_value2 == key_value1) // 再次扫描,
{
switch (key_value2) // 与状态1的相同,确认按键
{ // 键盘编码,返回编码值
case 0b11101110:
key_return = K1_1; // 0
break;
case 0b11101101:
key_return = K1_2; // 1
break;
case 0b11101011:
key_return = K1_3; // 2
break;
case 0b11100111:
key_return = K1_4;
break;
case 0b11011110:
key_return = K2_1;
break;
case 0b11011101:
key_return = K2_2;
break;
case 0b11011011:
key_return = K2_3;
break;
case 0b11010111:
key_return = K2_4;
break;
case 0b10111110:
key_return = K3_1;
break;
case 0b10111101:
key_return = K3_2;
break;
case 0b10111011:
key_return = K3_3;
break;
case 0b10110111:
key_return = K3_4;
break;
case 0b01111110:
key_return = K4_1;
break;
case 0b01111101:
key_return = K4_2;
break;
case 0b01111011:
key_return = K4_3;
break;
case 0b01110111:
key_return = K4_4;
break;
case 0b01100110:
key_return = KF_0; // 组合按键F+0
break;
case 0b01100101:
key_return = KF_1; // 组合按键F+1
break;
default:
break;
}
key_state = 3; // 转入等待按键释放状态
}
else
key_state = 0; // 两次列电平不同返回状态0,(消抖处理)
break;
case 3:
key_board_int1();
KEY_PORT_ROW &=~ KEY_ROW_ALL; // 必须送2次!!!
key_value_buf = (~KEY_ROW_ALL) & KEY_PIN_COL; // 读列电平
key_board_int2(); // 翻转
KEY_PORT_COL &=~ KEY_COL_ALL;
key_value_buf |= (~KEY_COL_ALL) & KEY_PIN_ROW; // 读行电平,并同上次上一步的结果或
key_value3 = key_value_buf;
if ( key_value3 == No_key)
key_state=0; // 按键已释放,转换到按键初始态
else if ((key_value3 == 0b11100111)||(key_value3 == 0b11011110))
{
if (++key_time >= 300) // 按键时间计数
{
key_state = 4; // 按下时间>1s,状态转换到计时2
key_time = 0; // 清按键计数器
key_return = KJ; // 输出“18”
}
break;
}
break;
case 4:
key_board_int1();
KEY_PORT_ROW &=~ KEY_ROW_ALL; // 必须送2次!!!
key_value_buf = (~KEY_ROW_ALL) & KEY_PIN_COL; // 读列电平
key_board_int2(); // 翻转
KEY_PORT_COL &=~ KEY_COL_ALL;
key_value_buf |= (~KEY_COL_ALL) & KEY_PIN_ROW; // 读行电平,并同上次上一步的结果或
key_value4 = key_value_buf;
if ( key_value4 == No_key)
key_state=0; // 按键已释放,转换到按键初始态
else if (++key_time >= 20) // 按键时间计数
{
key_time = 0; // 清按键计数器
key_return = KJ; // 输出“18”
break;
}
break;
default:
break;
}
return key_return;
} |
阿莫论坛20周年了!感谢大家的支持与爱护!!
知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
|