目录

1.  GPIO 概述

2.  原理图

3.  按键

4.  工程创建

5.  函数讲解

6.  代码编写


1.  GPIO 概述

        GPIO(General Purpose Input Output)即通用输入输出端口,是 STM32 芯片可直接控制的引脚。通过将 GPIO 引脚与外部设备连接,可实现与外部设备的通讯、控制及数据采集等功能。所有 GPIO 引脚均具备基本的输入和输出能力:

功能类型 原理 核心作用 典型应用
输出 由 STM32 控制引脚输出高、低电平,实现开关控制 控制外部设备通断 / 状态 LED 驱动、继电器 / 三极管控制
输入 检测外部输入的电平信号,通过电平高低区分不同状态。 检测外部电平 / 状态 按键检测、传感器信号采集

        本章只介绍GPIO输入功能,详细可以参考:

HAL库学习笔记_时光の尘的博客-CSDN博客

2.  原理图

        本章除了三颗LED灯还需要用到按键,我们开发板上按键原理图如下:

3.  按键

        按键机械触点断开、闭合时,由于触点的弹性作用,按键开关不会马上稳定接通或一下子断开,使用按键时会产生图按键抖动说明图中的带波纹信号,需要用软件消抖处理滤波,不方便输入检测。可以利用电容充放电的延时,消除了波纹,从而简化软件的处理,软件只需要直接检测引脚的电平即可。

4.  工程创建

        创建工程可以参考:

STM32学习·HAL库速通篇(四)·GPIO输出与点灯实验-CSDN博客

        这里直接沿用上一章的3颗LED灯实验,不需要再去重复声明了,只需要对两个按键进行声明,找到.ioc文件,打开:

        找到GPIO配置的地方,将三颗LED灯的初始电平设为高电平,也就是初始处于熄灭状态:

        然后找到PA0和PC13将其设置为输入模式:

        然后将其引脚配置为下拉模式:

        然后重新生成代码:

        可以看到此时gpio.c的初始化函数中增加了按键的初始化代码:

void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, LED_G_Pin|LED_B_Pin|LED_R_Pin, GPIO_PIN_SET);

  /*Configure GPIO pin : PtPin */
  GPIO_InitStruct.Pin = KEY2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  HAL_GPIO_Init(KEY2_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : PtPin */
  GPIO_InitStruct.Pin = KEY1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
  HAL_GPIO_Init(KEY1_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pins : PBPin PBPin PBPin */
  GPIO_InitStruct.Pin = LED_G_Pin|LED_B_Pin|LED_R_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}

5.  函数讲解

        这里主要用到读取GPIO状态的函数:

/**
  * @brief  读取指定输入端口引脚的电平状态。
  * @param  GPIOx: x可以是(根据所用器件而定,取值为A..G),用于选择GPIO外设
  * @param  GPIO_Pin: 指定要读取的端口位。
  *         此参数可以是GPIO_PIN_x,其中x可以是(0..15)。
  * @retval 输入端口引脚的电平值。
  */
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
  GPIO_PinState bitstatus;  // 用于存储引脚电平状态的变量

  /* 检查参数合法性 */
  assert_param(IS_GPIO_PIN(GPIO_Pin));

  // 判断读取到的引脚电平是否为高电平
  if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET)
  {
    bitstatus = GPIO_PIN_SET;  // 引脚为高电平
  }
  else
  {
    bitstatus = GPIO_PIN_RESET;  // 引脚为低电平
  }
  return bitstatus;  // 返回引脚电平状态
}

        你可以把它理解成:给单片机发一个 “指令”,问它 “某个 GPIO 引脚现在是高电平(3.3V)还是低电平(0V)?”,这个函数会返回明确的答案,是单片机获取外部硬件信号(比如按键、传感器)的核心接口。

6.  代码编写

        来到主函数,通过检测KEY1和KEY2按键是否被按下,来控制所有LED灯的亮灭:

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();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		if(HAL_GPIO_ReadPin(GPIOA, KEY1_Pin) == GPIO_PIN_SET)//检测KEY1按键是否被按下
		{
			HAL_GPIO_WritePin(GPIOB, LED_G_Pin|LED_B_Pin|LED_R_Pin, GPIO_PIN_RESET);//点亮所有LED灯
		}
		else if(HAL_GPIO_ReadPin(GPIOC, KEY2_Pin) == GPIO_PIN_SET)//检测KEY2按键是否被按下
		{
			HAL_GPIO_WritePin(GPIOB, LED_G_Pin|LED_B_Pin|LED_R_Pin, GPIO_PIN_SET);//关闭所有LED灯
		}
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

完整代码:

基于STM32实现GPIO输入功能(HAL版本按键控制LED灯亮灭)资源-CSDN下载

HAL库学习笔记_时光の尘的博客-CSDN博客

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐