📖 第 13 章:跑马灯实验(LED Marquee)

🔧 正点原子《DMF407 开发指南》V1.0 · Chapter 13
🗨️ 「嵌入式第一课:让 LED 学会呼吸。从此你与 32 位 MCU 的缘分开始。」
这一章在干嘛? 跑马灯实验:GPIO 八种模式、寄存器配置、HAL_GPIO_Init 用法、LED 灯交替闪烁。本章是后续 30 个实验的「Hello World」,务必亲手跑通。
13.1 STM32F4 GPIO 简介13.2 硬件设计13.3 程序设计13.4 下载验证

13.1 STM32F4 GPIO 简介

F407IGT6 有 140 个 IO,分 GPIOA~GPIOI 共 10 组(I 组只有 12 个)。

5V 兼容:带 FT 标志的 IO 兼容 5V,可直连 5V 外设(模拟输入模式除外)。

原书图 13.1.1:STM32 IO 端口属性缩写符号表
原书图 13.1.1:STM32 IO 端口属性缩写符号表

GPIO 八种工作模式:

模式典型应用
输入浮空按键检测(外部已上下拉)
输入上拉按键检测(无外部电阻)
输入下拉外接高电平有效信号
模拟ADC 输入
开漏输出I2C 总线
推挽输出LED、蜂鸣器、普通 IO
开漏式复用I2C、SPI 等外设
推挽式复用USART、SPI 等外设

13.1.1 GPIO 功能模式

每种模式由 MODER(模式)、OTYPER(输出类型)、OSPEEDR(速度)、PUPDR(上下拉)、IDR(输入数据)、ODR(输出数据)、BSRR(位设置/复位)等寄存器组合实现。

13.1.2 GPIO 基本结构分析

GPIO 内部结构从引脚看进去:

  1. 保护二极管:限制电压在 VSS~VDD;
  2. 上拉/下拉电阻:30~50K,可软件开关;
  3. TTL 肖特基触发器:将模拟信号整形为 0/1;
  4. 输入数据寄存器 IDR:可读当前电平;
  5. 输出数据寄存器 ODR:可设置输出电平;
  6. 位设置/复位寄存器 BSRR:原子操作 ODR 位。

原书图 13.1.2.1:GPIO 基本结构图
原书图 13.1.2.1:GPIO 基本结构图

BSRR 是 GPIO 的灵魂: GPIOA->BSRR = GPIO_PIN_5; 原子地把 PA5 拉高,且不影响其他 IO。

13.2 硬件设计

DMF407 LED 电路:

LED 串联电阻 ~ 510Ω,限流 ~ 5 mA。

13.3 程序设计

13.3.1 编程步骤

  1. 开启 GPIOF 时钟:__HAL_RCC_GPIOF_CLK_ENABLE();
  2. 配置 GPIO:HAL_GPIO_Init(GPIOF, &gpio_struct);
  3. 在 while 里翻转电平。

原书图 13.3.1.1:LED 硬件原理图
原书图 13.3.1.1:LED 硬件原理图

13.3.2 关键代码

LED_Init:
    GPIO_InitTypeDef gpio = {0};
    __HAL_RCC_GPIOF_CLK_ENABLE();
    gpio.Pin = GPIO_PIN_9 | GPIO_PIN_10;
    gpio.Mode = GPIO_MODE_OUTPUT_PP;
    gpio.Pull = GPIO_NOPULL;
    gpio.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOF, &gpio);
    HAL_GPIO_WritePin(GPIOF, GPIO_PIN_9 | GPIO_PIN_10, GPIO_PIN_SET); // 默认灭

main:
    while (1) {
        LED0_TOGGLE();    // HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_9);
        delay_ms(500);
        LED1_TOGGLE();
        delay_ms(500);
    }

原书图 13.3.2.1:GPIO 初始化流程图
原书图 13.3.2.1:GPIO 初始化流程图

13.4 下载验证

烧录 → 开发板 LED0/LED1 交替闪烁(500ms 周期),看不到闪烁检查:

进阶实验: 改成 PWM 呼吸灯(用 TIM1_CH1 输出 PWM 接到 LED),可调亮度。

🧠 小测验
GPIO 八种模式中,I2C 应该用哪种?
开漏式复用。
原子地设置某一位 GPIO 应使用哪个寄存器?
BSRR(Bit Set Reset Register)。
LED0 接在 PF9,低电平点亮:程序里熄灭 LED0 的语句?
HAL_GPIO_WritePin(GPIOF, GPIO_PIN_9, GPIO_PIN_SET);
← 上一篇🏠 顶层目录下一篇 →