From 12193eb4f0df130cde07b86ea48031d500f16da6 Mon Sep 17 00:00:00 2001 From: moieo Date: Tue, 9 Jul 2024 19:51:05 +0800 Subject: [PATCH] =?UTF-8?q?STM32F103=20=E5=AE=9E=E7=8E=B0=204x4=20?= =?UTF-8?q?=E7=9F=A9=E9=98=B5=E9=94=AE=E7=9B=98=E7=9A=84=E6=89=AB=E6=8F=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...30\347\232\204\346\211\253\346\217\217.md" | 144 ++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 "source/_posts/STM32F103-\345\256\236\347\216\260-4x4-\347\237\251\351\230\265\351\224\256\347\233\230\347\232\204\346\211\253\346\217\217.md" diff --git "a/source/_posts/STM32F103-\345\256\236\347\216\260-4x4-\347\237\251\351\230\265\351\224\256\347\233\230\347\232\204\346\211\253\346\217\217.md" "b/source/_posts/STM32F103-\345\256\236\347\216\260-4x4-\347\237\251\351\230\265\351\224\256\347\233\230\347\232\204\346\211\253\346\217\217.md" new file mode 100644 index 00000000..4c474e8c --- /dev/null +++ "b/source/_posts/STM32F103-\345\256\236\347\216\260-4x4-\347\237\251\351\230\265\351\224\256\347\233\230\347\232\204\346\211\253\346\217\217.md" @@ -0,0 +1,144 @@ +--- +title: STM32F103 实现 4x4 矩阵键盘的扫描 +date: 2024-07-09 19:44:57 +cover: +categories: + - STM32 + - 嵌入式 +tags: + - STM32 + - 单片机 + - MCU + - 嵌入式 +--- + + +直接放一个实物图在这里![实物图](https://preview.cloud.189.cn/image/imageAction?param=2561B53DE643174BDEFD95D5816918035E7CEE4FB9690172962BEE3D133D3A4677095922A1CD95EF9231E68A982630E65999F3E3914ECF3773AB80EFC6D9CA05FCBA6ED09C3D60D069AC63C13E6959AC6E539287EEC71656C2BDC15EBB8147A6BD5ED6E01E46E8E24E25C38B65B7A2A8103B5057) +接线放在这里~ + +| STM32F103C8T6 | 4x4 | +| --- | --- | +| A0 | C4 | +| A1 | C3 | +| A2 | C2 | +| A3 | C1 | +| A4 | R1 | +| A5 | R2 | +| A6 | R3 | +| A7 | R4 | + +## 实现原理 +遍历矩阵的每一行,开始时将当前遍历的行设置为 低电平,再扫描每一列并判断找出为低电平的列号,符合要求时记录行号和列号 +结束当前行时再将当前行设置为 高电平 + +## 源代码 +MATRIX_KEY_Sx 的编号由行号和列号组成 +matrix_key.h +```c +#ifndef __MATRIX_KEY__ +#define __MATRIX_KEY__ + +#include + +#define ROW_PINS (GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7) // 定义行引脚为GPIOA的4、5、6、7 +#define COL_PINS (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3) // 定义列引脚为GPIOA的0、1、2、3 + +// 第1行 +#define MATRIX_KEY_S1 0x18 // 0001 1000 +#define MATRIX_KEY_S2 0x14 // 0001 0100 +#define MATRIX_KEY_S3 0x12 // 0001 0010 +#define MATRIX_KEY_S4 0x11 // 0001 0001 +// 第2行 +#define MATRIX_KEY_S5 0x28 // 0010 1000 +#define MATRIX_KEY_S6 0x24 // 0010 0100 +#define MATRIX_KEY_S7 0x22 // 0010 0010 +#define MATRIX_KEY_S8 0x21 // 0010 0001 +// 第3行 +#define MATRIX_KEY_S9 0x48 // 0100 0100 +#define MATRIX_KEY_S10 0x44 // 0100 0100 +#define MATRIX_KEY_S11 0x42 // 0100 0010 +#define MATRIX_KEY_S12 0x41 // 0100 0001 +// 第4行 +#define MATRIX_KEY_S13 0x88 // 1000 1000 +#define MATRIX_KEY_S14 0x84 // 1000 0100 +#define MATRIX_KEY_S15 0x82 // 1000 0010 +#define MATRIX_KEY_S16 0x81 // 1000 0001 + +void Init_Matrix_Key(void); + +void Scan_Matrix_Key(void (*Call_Back)(uint8_t)); + +#endif +``` + +matrix_key.c +```c +#include +#include +#include + +void Init_Matrix_Key(void) { + GPIO_InitTypeDef GPIO_InitStructure; + + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能GPIOA时钟 + + // 设置行引脚为推挽输出 + GPIO_InitStructure.GPIO_Pin = ROW_PINS; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + // 设置列引脚为上拉输入 + GPIO_InitStructure.GPIO_Pin = COL_PINS; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; + GPIO_Init(GPIOA, &GPIO_InitStructure); +} + +void Scan_Matrix_Key(void (*Call_Back)(uint8_t)) { + uint8_t row, col; + uint8_t keyDetected = 0; + + for (row = 0; row < 4; row++) { // 遍历行 + GPIO_ResetBits(GPIOA, 1 << (row + 4)); // 将当前行置为低电平,注意这里使用1 << (row + 4)来选中行 + Delay_us(10); // 短暂延时以稳定电平 + + for (col = 0; col < 4; col++) { // 遍历列 + if (GPIO_ReadInputDataBit(GPIOA, 1 << col) == Bit_RESET) { // 判断该列是否为低电平 + Delay_ms(100); // 延时去抖动 + if (GPIO_ReadInputDataBit(GPIOA, 1 << col) == Bit_RESET) { // 再次检查,确认按键被按下 + keyDetected = (1 << col) | (1 << (row + 4)); // 记录按键位置 + Call_Back(keyDetected); + break; // 跳出列循环,因为同一时间只能有一个按键被按下 + } + while(GPIO_ReadInputDataBit(GPIOA, 1 << col) == Bit_RESET);// 等待弹起 + } + } + GPIO_SetBits(GPIOA, 1 << (row + 4)); // 恢复该行至高电平 + if (keyDetected) { + break; // 如果检测到按键,跳出行循环 + } + } +} +``` + +在 main 中调用 +```c +void Matrix_Key_Callback(uint8_t key) { + switch(key) { + case MATRIX_KEY_S1: + // TODO + break; + } +} + +int main(void) { + Init_Matrix_Key(); // 初始化 + while (1) { + Scan_Matrix_Key(Matrix_Key_Callback); + } +} +``` + +你可以在串口中输出按键的号码~ +![](https://preview.cloud.189.cn/image/imageAction?param=E8D28D4DD8268574D1B55EEB925E126321B71374462A2471B6A5E5CE9F5FE78EC23D621BD9E573D40AA8B476CD5C165F61ED90ACC51C792099A082BA3BF677B37748CF1A6C5E7B2DCABD897D8999C6822F878C924EE235B32B22F4043F79785FEEB213769A4FFA6EA1FC82529384364E46C9F9D4) +![](https://preview.cloud.189.cn/image/imageAction?param=B10247C30F3C971823503110465F4537D8A07C9CE3C43FE2B051347C66F2D57D00307D4103E6D9F8774472465E64F29F2DA7C33880D311B33148E8A12CDAB7557D800A1BF9C5B5FDA9FD8DFD55A30FC6BABA801914D35FDCA54F8F0EC502A109BFB42942C381899E0E7720D001BDF289B24B718A)