直接放一个实物图在这里
接线放在这里~
STM32F103C8T6 4x4 A0 C4 A1 C3 A2 C2 A3 C1 A4 R1 A5 R2 A6 R3 A7 R4
实现原理 遍历矩阵的每一行,开始时将当前遍历的行设置为 低电平,再扫描每一列并判断找出为低电平的列号,符合要求时记录行号和列号
结束当前行时再将当前行设置为 高电平
源代码 MATRIX_KEY_Sx 的编号由行号和列号组成
matrix_key.h
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
#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
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
#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 中调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 );
}
}
你可以在串口中输出按键的号码~
Licensed under CC BY-NC-SA 4.0