STM32F1与STM32CubeIDE编程实例-矩阵键盘驱动 矩阵键盘驱动 1、矩阵键盘介绍 键盘是广泛用于各种电子和嵌入式项目的输入设备。 它们用于以数字和字母的形式获取输入,并将其输入系统以进行进一步处理。
矩阵键盘由一组相互连接的按钮组成。 在本次实例中使用 4X4 矩阵键盘,其中四行中的每一行都有 4 个按钮。 按钮端子按下图所示示连接。 在第一行,所有4个按钮的一个端子连接在一起,4个按钮的另一个端子代表4列中的每一列,每行也是如此。 所以一共有 8 根线来连接一个微控制器。
首先,需要配置 8 个 GPIO 引脚。 其中四个是输入,另外四个是输出引脚。 然后您可以将列引脚连接到输入或输出引脚,但为方便起见,我将它们连接到 4 个输出引脚。
最后但同样重要的是,4 行引脚将连接到微控制器的 4 个输入引脚。 如下图所示:
如何确定键盘中哪个按键按下?
1)查找列位置
首先,将所有行都设置为逻辑级别 0,将所有列设置为逻辑级别 1。
每当按下一个按键时,对应于该按钮的列和行就会短路,并使相应的列变为逻辑电平 0。因为该列连接(短路)到处于逻辑电平 0 的行。
2)查找行位置
首先,将所有行都设置为逻辑级别1,将所有列设置为逻辑级别 0。
当按下按键的行应为 0,因为它已连接(短路)到按下按钮的列,并且所有列都处于 0 逻辑。 所以我们已经扫描了所有行的 0。
因此,每当在逻辑 0 处找到 Row 时,就意味着这是按下按钮的行。 所以现在就可以将列号(在步骤 2 中得到)和行号确定按键的位置。
在前面的文章中,对矩阵键盘的驱动做了详细的描述,请参考:
2、矩阵键盘配置 开发环境搭建、系统时钟配置、调试配置及串口配置,请参考:
传感器配置如下:
保存配置并生成代码。
3、矩阵键盘驱动实现 1)基本定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 /\* \* keypad4x4.h \* \* Created on: Apr 24, 2022 \* Author: jenson \*/ #ifndef \_\_KEYPAD\_H\_\_ #define \_\_KEYPAD\_H\_\_ #include <stdio.h> #include <stm32f1xx\_hal.h> #include "main.h" typedef struct { uint16\_t id; uint16\_t rows; uint16\_t cols; GPIO_TypeDef \*\*row_ports; uint16\_t \*row_pins; GPIO_TypeDef \*\*column_ports; uint16\_t \*column_pins; uint8\_t \*keys_map; } keypad\_t; /\*\*\* \* @brief Keypad初始化 \* @param keypad Keypad对象 \*/ void keypad\_init(keypad\_t \*keypad); /\*\*\* \* @brief 读取Keypad按键值 \* @param keypad Keypad对象 \*/ uint8\_t keypad\_read(keypad\_t \*keypad); /\*\*\* \* @brief Keypad 销毁 \* @param keypad Keypad对象 \*/ void keypad\_release(keypad\_t \*keypad); #endif /\* \_\_KEYPAD\_H\_\_ \*/
2)矩阵键盘键值扫描
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 /\* \* keypad4x4.c \* \* Created on: Apr 24, 2022 \* Author: jenson \*/ #include <keypad/keypad.h> void keypad\_init(keypad\_t \*keypad) { } void keypad\_release(keypad\_t \*keypad) { } // 设置行 void \_\_keypad\_set\_column(keypad\_t \*keypad, uint16\_t column) { for (int i = 0; i < keypad->cols; i++) { HAL\_GPIO\_WritePin(keypad->column_ports[i], keypad->column_pins[i], GPIO_PIN_RESET); } HAL\_GPIO\_WritePin(keypad->column_ports[column], keypad->column_pins[column], GPIO_PIN_SET); } // 检查列状态,并确定按键位置 uint8\_t \_\_keypad\_check\_row(keypad\_t \*keypad, uint16\_t column) { uint8\_t key = 0; for (int i = 0; i < keypad->rows; i++) { if (HAL\_GPIO\_ReadPin(keypad->row_ports[i], keypad->row_pins[i])) { //HAL\_Delay(50); while (HAL\_GPIO\_ReadPin(keypad->row_ports[i], keypad->row_pins[i])) ; // 等待松开 key = keypad->keys_map[i \* keypad->rows + column]; break; } } return key; } uint8\_t keypad\_read(keypad\_t \*keypad) { uint8\_t key = 0; for (int i = 0; i < keypad->cols; i++) { \_\_keypad\_set\_column(keypad, i); key = \_\_keypad\_check\_row(keypad, i); if (key) { break; } } return key; }
3)主程序
在main.c文件中,添加如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 /\* Private includes ----------------------------------------------------------\*/ /\* USER CODE BEGIN Includes \*/ #include <keypad/keypad.h> /\* USER CODE END Includes \*/ /\* Private variables ---------------------------------------------------------\*/ /\* USER CODE BEGIN PV \*/ GPIO_TypeDef \*column_ports[] = { KEYPAD_C1_GPIO_Port, KEYPAD_C2_GPIO_Port, KEYPAD_C3_GPIO_Port, KEYPAD_C4_GPIO_Port }; uint16\_t column_pins[] = { KEYPAD_C1_Pin, KEYPAD_C2_Pin, KEYPAD_C3_Pin, KEYPAD_C4_Pin }; GPIO_TypeDef \*row_ports[] = { KEYPAD_R1_GPIO_Port, KEYPAD_R2_GPIO_Port, KEYPAD_R3_GPIO_Port, KEYPAD_R4_GPIO_Port }; uint16\_t row_pins[] = { KEYPAD_R1_Pin, KEYPAD_R2_Pin, KEYPAD_R3_Pin, KEYPAD_R4_Pin }; // 按键值 uint8\_t keys_map[4][4] = { { '1', '2', '3', 'A' }, { '4', '5', '6', 'B' }, {'7', '8', '9', 'C' }, { '\*', '0', '#', 'D' } }; keypad\_t keypad; /\* USER CODE END PV \*/ int main(void) { /\* USER CODE BEGIN 1 \*/ /\* USER CODE END 1 \*/ /\* MCU Configuration--------------------------------------------------------\*/ /\* Reset of all peripherals, Initializes the Flash interface and the Systick. \*/ HAL\_Init(); /\* USER CODE BEGIN Init \*/ /\* USER CODE END Init \*/ /\* Configure the system clock \*/ SystemClock\_Config(); /\* USER CODE BEGIN SysInit \*/ /\* USER CODE END SysInit \*/ /\* Initialize all configured peripherals \*/ MX\_GPIO\_Init(); MX\_USART1\_UART\_Init(); /\* USER CODE BEGIN 2 \*/ keypad.id = 1; keypad.rows = 4; keypad.cols = 4; keypad.column_ports = column_ports; keypad.column_pins = column_pins; keypad.row_ports = row_ports; keypad.row_pins = row_pins; keypad.keys_map = (uint8\_t\*) &keys_map[0]; printf("\*\*\*\*STM32CubeIDE:Keypad4x4 \*\*\*\*\r\n"); /\* USER CODE END 2 \*/ /\* Infinite loop \*/ /\* USER CODE BEGIN WHILE \*/ while (1) { /\* USER CODE END WHILE \*/ /\* USER CODE BEGIN 3 \*/ uint8\_t key = keypad\_read(&keypad); if (key) { printf("key %c pressed\r\n", key); } } /\* USER CODE END 3 \*/ }
运行结果:
文章来源: https://iotsmart.blog.csdn.net/article/details/125500171
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!