最近在做项目中,有开始用到矩阵按键,由于之前做的项目基本是独立IO按键,所以这块算是没接触过。经过从网上了解到的情况,大已明白其原理:列扫行读(基于下面的硬件方式)。
不过网上提供的案例代码有些过于冗余,遂自己尝试写了一下,已验证OK。
先附上硬件设计原理图: 如下是3x4的矩阵键盘
再附上核心的三个函数
/*按键信号读取,判断是否按下被拉低*/
unsigned char key_read(unsigned char col_pos)
{
unsigned char key_status =0x01;
switch(col_pos)
{
case 0:
key_status =GPIO_ReadInputDataBit(KEY_COL1_PORT,KEY_COL1_PIN);//有键值则会被拉低
break;
case 1:
key_status =GPIO_ReadInputDataBit(KEY_COL2_PORT,KEY_COL2_PIN);
break;
case 2:
key_status =GPIO_ReadInputDataBit(KEY_COL3_PORT,KEY_COL3_PIN);
break;
default:
break;
}
return key_status;
}
/*按键信号写入*/
void key_write(unsigned char pos,unsigned char value)
{
switch(pos)
{
case 0://VALUE=1,假如使能拉低电平有效
(value)?(GPIO_ResetBits(KEY_ROW1_PORT,KEY_ROW1_PIN)):(GPIO_SetBits(KEY_ROW1_PORT,KEY_ROW1_PIN));
break;
case 1:
(value)?(GPIO_ResetBits(KEY_ROW2_PORT,KEY_ROW2_PIN)):(GPIO_SetBits(KEY_ROW2_PORT,KEY_ROW2_PIN));
break;
case 2:
(value)?(GPIO_ResetBits(KEY_ROW3_PORT,KEY_ROW3_PIN)):(GPIO_SetBits(KEY_ROW3_PORT,KEY_ROW3_PIN));
break;
case 3:
(value)?(GPIO_ResetBits(KEY_ROW4_PORT,KEY_ROW4_PIN)):(GPIO_SetBits(KEY_ROW4_PORT,KEY_ROW4_PIN));
break;
default:break;
}
}
/*矩阵按键扫描*/
void key_scan(key_st *me)
{
#define COL_KEY_NUM (3) //列
#define ROW_KEY_NUM (4) //行
//横向标记按键ID,ID从=1开始
#define MATRIX_KEY_ID_CONVERT(row_y, col_x) (ROW_KEY_NUM * col_x + row_y + 1) /*矩阵按键id值转换获取,id从1开始*/
me->id=0;//缺省值态
me->status=0;
for(unsigned char i =0;i <ROW_KEY_NUM;i++)
{
key_write(i,1);//行按键信号使能
for(unsigned char j =0;j <COL_KEY_NUM;j++)
{
//列按键信号读取,低电平有效
if(0==key_read(j))
{
*key_id=MATRIX_KEY_ID_CONVERT(i,j);
key_write(i,0x0);//行按键使能信号清除
return 1;//读得键值,终止结束
}
}
key_write(i,0);//行按键使能信号清除
}
}