一、适用场景
适用场景:单片机课堂演示、嵌入式入门实验、门禁/菜单输入、数字键盘模拟器等。

二、器材清单
4×4薄膜矩阵键盘(16键) ×1
stm32f103vet6开发板 ×1
若干杜邦线(母对母/公对公,根据引脚)
三、工作原理(要点)
矩阵结构:4×4键盘有4条行和4条竖,每个按键连接对应的一行和一列。

扫描思想:把行设为输出、列设为输入(或相反),逐行输出低电平(或高电平),读取列线变化以识别哪个按键被按下。
简单示例:检测S1、S2、S3、S4中的按键(以行为基础进行扫描)
先给第一行高电平(即P17为高电平),此时电路无电流,如果S1按下,电流从P17-S1开关-P13,即S1按下后此时P13为高电平,如果是S2按下则P12为高电平
接着给第一行改为低电平(即P17为低电平),将第二行即P16设置为高电平,此时电路无电流,如果S5按下,电流从P16-S5开关-P13,即S5按下后此时P13为高电平,如果是S6按下则P12为高电平

接着拉低P16,继续重复这个操作,直到将16个按键都扫描一遍,这就是逐行扫描查询法识别
四、接线示意

五、示例代码
//标准库
cpp
void gpio_init()
{
GPIO_InitTypeDef PA,PD;
//使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
PA.GPIO_Pin = GPIO_Pin_0 |GPIO_Pin_1;
PA.GPIO_Mode = GPIO_Mode_Out_PP;
PA.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&PA);
PD.GPIO_Pin = GPIO_Pin_0 |GPIO_Pin_1;
PD.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOD,&PD);
}
int main(void)
{
SysTick_Init(); //延时函数初始化
gpio_init(); //初始化与LED连接的硬件接口
USART_Config();
while(1)
{
GPIO_SetBits(GPIOA,GPIO_Pin_0);
if(GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_0) == SET)
Usart_SendString(USART1,"1\n");
else if(GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_1) == SET)
Usart_SendString(USART1,"2\n");
GPIO_ResetBits(GPIOA,GPIO_Pin_0);
GPIO_SetBits(GPIOA,GPIO_Pin_1);
if(GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_0) == SET)
Usart_SendString(USART1,"4\n");
else if(GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_1) == SET)
Usart_SendString(USART1,"5\n");
GPIO_ResetBits(GPIOA,GPIO_Pin_1);
Delay_us(500000);
}
}
//HAL库(注意这里的列是接到了PB0和PB1,和标准库不一样)
cpp
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 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_SET);
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0) == 1)
HAL_UART_Transmit(&huart1,"1\n", strlen("1\r\n"), HAL_MAX_DELAY);
else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) == 1)
HAL_UART_Transmit(&huart1,"2\n", strlen("2\r\n"), HAL_MAX_DELAY);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0) == 1)
HAL_UART_Transmit(&huart1,"4\n", strlen("4\r\n"), HAL_MAX_DELAY);
else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1) == 1)
HAL_UART_Transmit(&huart1,"5\n", strlen("5\r\n"), HAL_MAX_DELAY);
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);
HAL_Delay(300);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
六、讲解视频