为了实现计算器键盘,需要使用4X5矩阵按键,因此,我在4X4矩阵键盘上重新设计了一个4X5矩阵按键。原理图如下:

原理描述:
4X5矩阵按键,可以设置4个引脚为输出,5个引脚为输入模式,4个引脚依次设置为低电平,5个引脚依次扫描读取电平变化,如果为低电平,则表示按键按下,这样就可以通过坐标算出按键的位置(二维矩阵坐标)。
设计的PCB板如下:

3D效果图如下:

实物图:

接线表如下:
| 矩阵按键 | STM32 | |
| R5 | PA15 | 上拉输入模式 | 
| R4 | PB12 | 上拉输入模式 | 
| R3 | PB13 | 上拉输入模式 | 
| R2 | PB14 | 上拉输入模式 | 
| R1 | PB15 | 上拉输入模式 | 
| C1 | PA8 | 推挽输出模式 | 
| C2 | PA9 | 推挽输出模式 | 
| C3 | PA10 | 推挽输出模式 | 
| C4 | PA11 | 推挽输出模式 | 
| - | PA2 | USART2_TX | 
| - | PA3 | USART2_RX | 
功能:
将按键的信息在串口2显示,和博客原理一致:
4X4矩阵按键实现,博客地址:
STM32CubeMX实现矩阵按键(HAL库实现)_使用hal库使用矩阵按键-CSDN博客
CubeMX配置过程如下:

注意:这里需要注意一下,如果用STM32F103C8T6最小系统USB供电,PA12口不能作为普通的输入输出口,因为该口与USB相接,导致电平混乱。
代码如下:
按键扫描:
/* USER CODE BEGIN 0 */
uint16_t keyScan(void)
{
	HAL_GPIO_WritePin(GPIOA, COL1_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOA, COL2_Pin|COL3_Pin|COL4_Pin, GPIO_PIN_SET);
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA, ROW5_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA, ROW5_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA, ROW5_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 4\r\n", 8, 0XFFFF);
		return 20;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW4_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW4_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW4_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 4\r\n", 8, 0XFFFF);
		return 4;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW3_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW3_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW3_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 8\r\n", 8, 0XFFFF);
		return 8;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW2_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW2_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW2_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 12\r\n", 9, 0XFFFF);
		return 12;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW1_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW1_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW1_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 16\r\n", 9, 0XFFFF);
		return 16;
	}
	HAL_GPIO_WritePin(GPIOA, COL2_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOA, COL1_Pin|COL3_Pin|COL4_Pin, GPIO_PIN_SET);
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA, ROW5_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA, ROW5_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA, ROW5_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 4\r\n", 8, 0XFFFF);
		return 19;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW4_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW4_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW4_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 3\r\n", 9, 0XFFFF);
		return 3;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW3_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW3_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW3_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 7\r\n", 9, 0XFFFF);
		return 7;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW2_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW2_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW2_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 11\r\n", 9, 0XFFFF);
		return 11;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW1_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW1_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW1_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 15\r\n", 9, 0XFFFF);
		return 15;
	}
	HAL_GPIO_WritePin(GPIOA, COL3_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOA, COL1_Pin|COL2_Pin|COL4_Pin, GPIO_PIN_SET);
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA, ROW5_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA, ROW5_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA, ROW5_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 4\r\n", 8, 0XFFFF);
		return 18;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW4_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW4_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW4_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 2\r\n", 9, 0XFFFF);
		return 2;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW3_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW3_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW3_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 6\r\n", 9, 0XFFFF);
		return 6;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW2_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW2_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW2_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 10\r\n", 9, 0XFFFF);
		return 10;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW1_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW1_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW1_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 14\r\n", 9, 0XFFFF);
		return 14;
	}
	HAL_GPIO_WritePin(GPIOA, COL4_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOA, COL1_Pin|COL2_Pin|COL3_Pin, GPIO_PIN_SET);
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA, ROW5_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA, ROW5_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOA, ROW5_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 4\r\n", 8, 0XFFFF);
		return 17;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW4_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW4_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW4_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 1\r\n", 9, 0XFFFF);
		return 1;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW3_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW3_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW3_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 5\r\n", 9, 0XFFFF);
		return 5;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW2_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW2_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW2_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 9\r\n", 9, 0XFFFF);
		return 9;
	}
	if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW1_Pin))
	{
		HAL_Delay(20);
		if(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW1_Pin))
		{
			HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
		}
		while(GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOB, ROW1_Pin));
		//HAL_UART_Transmit(&huart2, (uint8_t *)"key: 13\r\n", 9, 0XFFFF);
		return 13;
	}
	return 0;
}
/* USER CODE END 0 */主函数:
int main(void)
{
  /* USER CODE BEGIN 1 */
	uint16_t keyValue = 0;		//	按键返回的键值
	uint8_t str[10] = "";
  /* 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_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
	HAL_GPIO_WritePin(GPIOA, COL1_Pin|COL2_Pin|COL3_Pin|COL4_Pin, GPIO_PIN_SET);	//	初始化高电平
  /* USER CODE END 2 */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
		if((keyValue = keyScan()) !=0 )
		{
			sprintf((char*)str,"key: %d\r\n",keyValue);
			HAL_UART_Transmit(&huart2, str, strlen((char*)str), 0XFFFF);
		}
  }
  /* USER CODE END 3 */
}实现效果,如下:

代码并不是很复杂。
代码如下:
STM32CubeMX实现4X5矩阵按键(HAL库实现)资源-CSDN文库



















