PUYA GPIO — GPIO 翻转输出(HAL 库)

PUYA PY32F0xx_Firmware V1.5.0 GPIO 翻转输出(GPIO_Toggle)示例教学(HAL 库版本)

GPIO — GPIO 翻转输出(HAL 库)

固件库: PY32F0xx_Firmware V1.5.0
芯片: PY32F030(PY32F002A / F003 同库可参考)
源文件: PUYA/PY32F0xx_Firmware_V1.5.0/Projects/PY32F030-STK/Example/GPIO/GPIO_Toggle/Src/main.c


功能简介

本示例演示如何让一个 GPIO 引脚工作于推挽输出模式,并在主循环中周期性翻转其电平。GPIO(通用输入输出)是 MCU 最基础、最常用的外设,所有“点灯”“驱动继电器”“软件模拟时序”都建立在它之上。

示例中 LED 连接在 PA11(开发板丝印 LED3),程序每 250ms 翻转一次该引脚,人眼即可看到 LED 闪烁。

硬件准备

  • PY32F030 开发板(或 PY32F002A / F003 官方 STK 板)
  • 板载 LED(PA11,对应 LED3
  • 一根 USB 数据线用于供电与下载
  • 无需额外外接元件

提示:如果你手上的板子 LED 不在 PA11,请修改下方宏定义中的引脚即可。

完整代码

 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
47
48
49
50
51
#include "main.h"

/* 把板载 LED3 映射成一组好记的宏,方便后续修改 */
#define LED_GPIO_PIN          LED3_PIN          /* LED 引脚:PA11 */
#define LED_GPIO_PORT         LED3_GPIO_PORT    /* LED 端口:GPIOA */
#define LED_GPIO_CLK_ENABLE() LED3_GPIO_CLK_ENABLE() /* 开启 GPIOA 时钟 */

/* 静态函数声明:GPIO 初始化 */
static void APP_GpioConfig(void);

int main(void)
{
  /* 1. 复位所有外设,并初始化 HAL 库与 SysTick 时基 */
  HAL_Init();

  /* 2. 配置 LED 引脚为推挽输出 */
  APP_GpioConfig();

  /* 3. 主循环:每 250ms 翻转一次 LED 电平 */
  while (1)
  {
    HAL_Delay(250);                              /* 阻塞延时 250ms */
    HAL_GPIO_TogglePin(LED_GPIO_PORT, LED_GPIO_PIN); /* 翻转引脚电平 */
  }
}

/**
  * @brief  GPIO 引脚配置函数
  */
static void APP_GpioConfig(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  LED_GPIO_CLK_ENABLE();                        /* 必须先开时钟,否则配置无效 */

  GPIO_InitStruct.Pin   = LED_GPIO_PIN;
  GPIO_InitStruct.Mode  = GPIO_MODE_OUTPUT_PP;  /* 推挽输出模式 */
  GPIO_InitStruct.Pull  = GPIO_PULLUP;          /* 启用上拉 */
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; /* 引脚翻转速度:高速 */
  HAL_GPIO_Init(LED_GPIO_PORT, &GPIO_InitStruct);
}

/**
  * @brief  错误处理:卡死在此处便于调试
  */
void APP_ErrorHandler(void)
{
  while (1)
  {
  }
}

代码分段讲解

1. 时钟使能

LED_GPIO_CLK_ENABLE() 展开为 __HAL_RCC_GPIOA_CLK_ENABLE()。在 PY32(与 STM32 一致)中,任何外设使用前都必须先开启其时钟,否则写寄存器无效。这是初学者最容易遗漏的一步。

2. 引脚模式

  • GPIO_MODE_OUTPUT_PP:推挽输出。输出高电平时由 VDD 驱动,输出低电平时由内部 NMOS 拉到 GND,驱动能力较强,适合直接驱动 LED。
  • 与之相对的 GPIO_MODE_OUTPUT_OD 为开漏输出,常用于 I2C 等需要“线与”的总线。

3. 翻转与延时

  • HAL_GPIO_TogglePin():读取引脚当前电平后取反再写回,是最常用的“闪烁”原语。
  • HAL_Delay(250):基于 SysTick 的毫秒级阻塞延时,由 HAL_Init() 内部完成初始化。注意它是阻塞的,期间 CPU 不能做别的事(真实项目推荐用定时器中断替代)。

实验现象

  • 板载 LED(PA11)以约 2Hz(每 250ms 一次)的频率闪烁。
  • 用示波器/逻辑分析仪测量 PA11,可见周期为 500ms 的方波。

常见问题

  1. 下载后 LED 不闪?

    • 确认引导/下载模式与复位电路正常;确认 LED 实际连接引脚与代码中 LED3_PIN 一致(不同板型可能接在 PB0 / PB1 / PA5)。
    • 检查是否选择了正确的芯片型号(PY32F030x8),Flash 容量不同会导致下载失败。
  2. 编译报 LED3_PIN 未定义?

    • 该宏定义在 Drivers/BSP/PY32F030xx_Start_Kit/py32f030xx_Start_Kit.h 中,确认工程已包含该 BSP 头文件。
  3. 闪烁很快/很慢?

    • 直接调整 HAL_Delay() 的参数;若使用内部 HSI 且频率与工程设定不一致,实际延时会有偏差。
  4. 想用定时器非阻塞闪烁?

    • 参考同系列 TIMERx 示例,用定时器更新中断翻转引脚,主循环可空出来做其他任务。

小结

  • GPIO 输出只需三步:开时钟 → 配置引脚模式 → 写/翻转电平
  • HAL_GPIO_TogglePin() + HAL_Delay() 是最简单的闪烁模板,适合作为每个新板子的“点灯”验证程序。
  • 推挽输出(OUTPUT_PP)适合直接驱动 LED;开漏输出(OUTPUT_OD)适合总线应用。

拓展应用

  • HAL_Delay 换成定时器中断,实现“非阻塞”多任务闪烁(如多个 LED 不同频率)。
  • 读取按键(GPIO_INPUT + HAL_GPIO_ReadPin)实现“按键控制 LED 亮灭”。
  • GPIO_SPEED_FREQ_VERY_HIGH 配合精确延时,用单引脚“软”模拟单总线协议(如 DHT11、WS2812)。
  • 结合 PWM(见 TIM1_PWM 示例)做 LED 呼吸灯。
世界是你们
使用 Hugo 构建
主题 StackJimmy 设计