矩阵按键的原理与实现
矩阵按键(Matrix Keypad)是一种常见的输入设备,广泛应用于嵌入式系统和电子设备中。它不仅节省I/O资源,还能有效提高按键的扩展性。本文将深入剖析矩阵按键的工作原理,并结合代码讲解其软件实现。
一、矩阵按键的基本原理
矩阵按键采用行列交叉的方式连接多个按键,形成类似于坐标系的结构。例如,4x4矩阵按键共有16个按键,却仅使用8个I/O口进行扫描。
矩阵按键电路结构
矩阵按键的电路结构如下图所示:
如图所示,矩阵按键由4行(ROW1-ROW4)和4列(COL1-COL4)组成。每个按键位于某一行和某一列的交点处。按键未按下时,行列线路互不连通;按下某个按键时,该按键所在的行列导通。
二、矩阵按键的软件扫描方法
为了检测按键的按下状态,需要进行行扫描和列扫描。一般有两种方式:
- 行输入,列输出
- 列(COL)置高电平,行(ROW)设为输入,读取行信号。
- 若有按键按下,则对应行变为高电平。
- 2.列输入,行输出
- 行(ROW)置高电平,列(COL)设为输入,读取列信号。
- 若有按键按下,则对应列变为高电平。
以下是具体的软件实现:
void row_in_col_out(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = ROW1_Pin | ROW2_Pin | ROW3_Pin | ROW4_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
GPIO_InitStruct.Pin = COL1_Pin | COL2_Pin | COL3_Pin | COL4_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOE, COL1_Pin | COL2_Pin | COL3_Pin | COL4_Pin, GPIO_PIN_SET);
}
uint8_t key_on(void) {
uint8_t row_statue, col_statue;
row_in_col_out();
if (HAL_GPIO_ReadPin(ROW1_GPIO_Port, ROW1_Pin) == 1) {
row_statue = 1;
} else if (HAL_GPIO_ReadPin(ROW2_GPIO_Port, ROW2_Pin) == 1) {
row_statue = 2;
} else if (HAL_GPIO_ReadPin(ROW3_GPIO_Port, ROW3_Pin) == 1) {
row_statue = 3;
} else if (HAL_GPIO_ReadPin(ROW4_GPIO_Port, ROW4_Pin) == 1) {
row_statue = 4;
} else {
return 0;
}
row_out_col_in();
if (HAL_GPIO_ReadPin(COL1_GPIO_Port, COL1_Pin) == 1) {
col_statue = 1;
} else if (HAL_GPIO_ReadPin(COL2_GPIO_Port, COL2_Pin) == 1) {
col_statue = 2;
} else if (HAL_GPIO_ReadPin(COL3_GPIO_Port, COL3_Pin) == 1) {
col_statue = 3;
} else if (HAL_GPIO_ReadPin(COL4_GPIO_Port, COL4_Pin) == 1) {
col_statue = 4;
} else {
return 0;
}
return (row_statue - 1) * 4 + col_statue;
}
三、矩阵按键驱动 LED 显示
在实际应用中,我们通常使用按键输入控制 LED 灯的亮灭,如下所示:
void led_on(uint8_t led) {
switch (led) {
case 1: HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET); break;
case 2: HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET); break;
case 3: HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET); break;
case 4: HAL_GPIO_WritePin(LED4_GPIO_Port, LED4_Pin, GPIO_PIN_RESET); break;
case 5: HAL_GPIO_WritePin(LED5_GPIO_Port, LED5_Pin, GPIO_PIN_RESET); break;
case 6: HAL_GPIO_WritePin(LED6_GPIO_Port, LED6_Pin, GPIO_PIN_RESET); break;
case 7: HAL_GPIO_WritePin(LED7_GPIO_Port, LED7_Pin, GPIO_PIN_RESET); break;
case 8: HAL_GPIO_WritePin(LED8_GPIO_Port, LED8_Pin, GPIO_PIN_RESET); break;
}
}
完整的矩阵按键控制 LED 的流程如下:
- 读取按键状态
key_on()
- 根据按键编号点亮相应的 LED
led_on(flag)
- 若按键松开,则关闭所有 LED
led_all_off()
主循环代码如下:
while (1) {
uint8_t flag = key_on();
if (flag == 0) {
led_all_off();
continue;
}
led_on(flag);
}
四、总结
矩阵按键是一种高效的按键扫描方式,采用行列扫描的方式极大地减少了I/O端口的占用。本文通过详细的代码解析,从硬件连接到软件驱动,完整地实现了一个4x4矩阵按键的功能。希望这篇文章能够帮助你深入理解矩阵按键的原理,并能在你的嵌入式项目中应用这一技术。
拓展阅读:
- 消抖处理:在实际应用中,按键可能会受到抖动影响,需要添加软件消抖。
- 中断扫描:可以使用外部中断代替轮询,提高系统效率。
- I2C 接口按键:使用 I2C 扩展芯片进一步减少 I/O 资源占用。
如果你觉得这篇文章对你有所帮助,欢迎点赞、评论、收藏,共同学习交流!