-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
144 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <stm32f10x.h> | ||
|
||
#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 <stm32f10x.h> | ||
#include <Delay.h> | ||
#include <matrix_key.h> | ||
|
||
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) |