目录

1.  GPIO 概述

2.  原理图

3.  工程创建

4.  基础延时设置流水灯

4.1  函数介绍

4.2  代码编写


1.  GPIO 概述

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

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

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

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

2.  原理图

        本章就需要三颗LED灯,我们开发板上3颗LED灯原理图如下:

3.  工程创建

        创建工程可以参考:

STM32学习·HAL库速通篇(三)·如何在STM32CubeMX新建工程_stm32cubemx 配置cmsis库-CSDN博客

        这里我们在此基础上进行修改,找到.ioc文件:

        双击打开配置界面:

        在右下角搜索相关引脚:

        分别找到原理图示的三个引脚,将其配置成输出模式:

        找到图示位置对引脚进行相关配置:

        根据上图每个引脚都配置一下:

        然后重新生成代码,找到gpio.c文件:

        其中声明代码如下:

void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};

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

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

  /*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);

}

        此时下载代码可以发现三个LED灯全部电亮。

4.  基础延时设置流水灯

        延时(Delay)简单来说,就是让 STM32 芯片在执行完某一条 / 某一段指令后,暂停(等待)指定的时间,再继续执行后面的代码。

        在 GPIO 应用中,延时是最常用的基础功能之一 ,比如控制 LED 灯闪烁时,需要让 LED 亮 1 秒、灭 1 秒,这个 “1 秒的等待” 就是通过延时实现的。

4.1  函数介绍

        为了实现流水灯的功能,这里需要使用两个函数,其一设置 / 清除指定 GPIO 引脚的电平状态函数:

/**
  * @brief  设置或清除选定的数据端口位。
  *
  * @note   该函数使用 GPIOx_BSRR 寄存器实现原子化的读/修改操作,
  *         这样可以避免在读取和修改操作之间触发中断(IRQ)而导致的操作异常。
  *
  * @param  GPIOx: 其中 x 可以是(根据所用器件而定,可选 A..G),用于选择 GPIO 外设
  * @param  GPIO_Pin: 指定要写入的端口位。
  *          该参数可以是 GPIO_PIN_x 中的一个值,其中 x 可以是(0..15)。
  * @param  PinState: 指定要写入到选定端口位的值。
  *          该参数可以是 GPIO_PinState 枚举类型的取值之一:
  *            @arg GPIO_PIN_RESET: 清除该端口位(置低电平)
  *            @arg GPIO_PIN_SET: 设置该端口位(置高电平)
  * @retval 无
  */
void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
{
  /* 检查参数合法性 */
  assert_param(IS_GPIO_PIN(GPIO_Pin));
  assert_param(IS_GPIO_PIN_ACTION(PinState));

  if (PinState != GPIO_PIN_RESET)
  {
    GPIOx->BSRR = GPIO_Pin; // 设置指定端口位(置1)
  }
  else
  {
    GPIOx->BSRR = (uint32_t)GPIO_Pin << 16u; // 清除指定端口位(置0)
  }
}

        其核心实现是利用 BSRR 寄存器的高低 16 位分别控制 “置高 / 置低”,避免中断干扰。

        另一个是延时函数:

/**
  * @brief  该函数通过变量自增的方式提供以毫秒为单位的最小延时。
  * @note   在默认实现中,SysTick定时器是时间基准的来源。
  *         它用于按固定时间间隔产生中断,在中断中uwTick变量会自增。
  * @note   该函数被声明为__weak(弱定义),以便在用户文件中实现其他方案时可以重写此函数。
  * @param  Delay 指定延时的时长,单位为毫秒。
  * @retval 无
  */
__weak void HAL_Delay(uint32_t Delay)
{
  uint32_t tickstart = HAL_GetTick();  // 记录延时开始时的系统滴答值
  uint32_t wait = Delay;               // 待等待的延时时长

  /* 增加一个频率值以保证最小等待时间(避免因中断时序导致延时不足) */
  if (wait < HAL_MAX_DELAY)
  {
    wait += (uint32_t)(uwTickFreq);
  }

  /* 循环等待,直到达到指定的延时时长 */
  while ((HAL_GetTick() - tickstart) < wait)
  {
  }
}

        其中:

英文术语 中文译法 补充说明
SysTick timer SysTick 定时器 STM32 内核自带的系统滴答定时器
time base 时间基准 提供统一时间参考的基础信号
__weak 弱定义 C 语言特性,允许用户重定义同名函数
uwTick 系统滴答计数器 HAL 库核心的毫秒级计时变量
uwTickFreq 系统滴答频率 uwTick 的递增频率(默认 1kHz,即 1ms 递增 1)
HAL_MAX_DELAY HAL 最大延时值 HAL 库定义的延时上限(通常为 uint32_t 最大值)

4.2  代码编写

        来到主函数,我们下面实现三颗灯珠依次点亮,主要更改主函数代码:

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)
  {
		HAL_GPIO_WritePin(GPIOB, LED_G_Pin, GPIO_PIN_RESET);
		HAL_GPIO_WritePin(GPIOB, LED_B_Pin|LED_R_Pin, GPIO_PIN_SET);
		HAL_Delay(500);

		HAL_GPIO_WritePin(GPIOB, LED_B_Pin, GPIO_PIN_RESET);
		HAL_GPIO_WritePin(GPIOB, LED_G_Pin|LED_R_Pin, GPIO_PIN_SET);
		HAL_Delay(500);

		HAL_GPIO_WritePin(GPIOB, LED_R_Pin, GPIO_PIN_RESET);
		HAL_GPIO_WritePin(GPIOB, LED_G_Pin|LED_B_Pin, GPIO_PIN_SET);
		HAL_Delay(500);
    /* USER CODE END WHILE */

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

        观察实验可以发现,LED灯每隔500ms依次点亮(文章无法放视频,这里就不演示实验想象了)。

完整工程:

基于STM32实现GPIO输出功能(HAL版本LED流水灯实验)资源-CSDN下载

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

Logo

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

更多推荐