第三章:LED 模块详解

💡 第三章:LED 模块详解(STM32G431RBT6 + HAL 库 · 小白友好版)

本章完全基于你的开发环境


硬件原理图:

配置CUBEMX环境:

🧩 一、你的开发板长什么样?LED 接在哪?

你用的 STM32G431RBT6 是一颗 64 引脚的芯片,常见于 Nucleo-G431RB 或自研最小系统板。

在很多 G431 开发板上:

  • 8 个 LED 通常接在 GPIOC 的高 8 位PC8 ~ PC15
  • 控制信号(锁存使能) 接在 GPIOD 的第 2 脚PD2
  • 所有 LED 采用 共阳极接法(阳极接 3.3V,阴极接 GPIO)

🔌 共阳极 = 软件写 0 → 灯亮;写 1 → 灯灭

(这是理解你代码的关键!)

✅ 你已经在 STM32CubeMX 中把:

  • PC8~PC15 和 PD2 都配置为 GPIO_Output(推挽输出)
  • 系统时钟和 GPIO 时钟已自动开启

所以,你可以在代码里放心操作寄存器,不会出错!


📦 二、你的"LED状态箱":ucLed[8]

复制代码
uint8_t ucLed[8];  // 全局变量,定义在 led_app.c 或 .h 中

这就像一个 8格的小抽屉,每格放一个数字:

抽屉编号 ucLed[0] ucLed[1] ... ucLed[7]
控制哪个灯? LED0 LED1 ... LED7
值 = 1 👉 "我想让这个灯 !"
值 = 0 👉 "这个灯 。"

💡 小白注意:你只管改这个数组,真正的"开关灯"工作,交给下面的函数去做!


⚙️ 三、核心函数 led_disp() ------ "把想法变成灯光"

这是你写的重点函数(原封不动,逐行解释

复制代码
void led_disp(uint8_t *ucLed)
{
    uint8_t temp = 0x00;                // 临时拼图板
    static uint8_t temp_old = 0xff;     // 记住上次拼的是什么图

    // 把 ucLed[0]~ucLed[7] 拼成一个字节
    // ucLed[0] 放最高位(bit7),ucLed[7] 放最低位(bit0)
    for (int i = 0; i < 8; i++) {
        temp |= (ucLed[i] << (7 - i));
    }

    // 只有当图案变了,才去更新硬件(省电 + 不闪屏!)
    if (temp != temp_old) {
        GPIOC->ODR = 0x00ff;            // ① 先清空 PC8~PC15(全亮)
        GPIOC->ODR = ~(temp << 8);      // ② 把新图案取反后放到高8位
        GPIOD->BSRR = 0x01 << 2;        // ③ PD2 输出高电平("准备更新!")
        GPIOD->BRR = 0x01 << 2;         // ④ PD2 输出低电平("现在更新!")
        temp_old = temp;                // ⑤ 记住这次的图案
    }
}

🌟 用"舞台换景"来理解这 4 步:

想象你是一个舞台导演:

  • 舞台上 8 盏灯(LED)正在亮着
  • 你想换成新图案,但不能一盏一盏关------观众会看到闪烁!

于是你这样做:

  1. 后台先准备好新灯控信号temp 就是新图案)
  2. 拉下幕布(PD2 拉高 → 锁存器暂停输出)
  3. 快速切换所有灯的控制线 (写 GPIOC->ODR
  4. 拉开幕布 (PD2 拉低 → 锁存器输出新状态)→ 观众看到 瞬间切换

✅ 这就是 PD2 的作用 :它是一个 同步使能信号 ,常用于驱动 74HC573 等锁存器


❓ 四、小白高频问题解答

Q1:为什么要把 temp 左移 8 位

因为:

  • temp 是 8 位(0~255)
  • 你要控制的是 PC8 ~ PC15 (即 GPIOC 的 高 8 位
  • 所以必须 temp << 8,才能对齐到正确位置!

例如:

  • temp = 0b10000000(只想亮 LED0)
  • temp << 8 = 0b10000000 00000000
  • 写入 GPIOC->ODR 后,PC15 = 1,其他高8位=0

Q2:为什么要 取反(~)

因为你的电路是 共阳极

软件意图 ucLed[i] temp 中的位 实际需要 GPIO 输出
灯亮 1 1 0(低电平)
灯灭 0 0 1(高电平)

所以必须 取反,才能让硬件行为和软件意图一致!

✅ 举例:

  • temp = 0b10000000~(temp<<8) = 0b01111111 11111111
  • → PC15 = 0(亮),PC14~PC8 = 1(灭)✅

Q3:为什么先写 GPIOC->ODR = 0x00ff

这是为了 保护低 8 位(PC0~PC7)

  • GPIOC->ODR 控制 全部 16 个引脚
  • 如果你直接写 ~(temp<<8),结果是一个 32 位数(比如 0xFFFFxxFF
  • 可能会意外把 PC0~PC7 拉低(如果它们正在控制串口、按键等,就出大事了!)

所以:

  • 0x00ff = 低8位=1,高8位=0 → 只清高8位,低8位保持原样
  • 再写 ~(temp<<8) → 高8位更新,低8位仍是 0x00ff 的低8位(即不变)✅

▶️ 五、怎么用?三步点亮你的想法!

第 1 步:确保 CubeMX 已配置(你已做完 ✅)

  • PC8~PC15 → GPIO_Output, Push-Pull, Low Speed
  • PD2 → GPIO_Output, Push-Pull, Low Speed
  • 生成代码后,MX_GPIO_Init() 会自动开启时钟

第 2 步:在 main() 中初始化

复制代码
// main.c
#include "led_app.h"

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();  // ← CubeMX 生成,千万别删!

    // 初始:所有灯灭
    for (int i = 0; i < 8; i++) {
        ucLed[i] = 0;  // 共阳:0 = 灭
    }

    while (1)
    {
        // 示例:让 LED0 亮 500ms,灭 500ms
        ucLed[0] = 1;   // 亮
        led_proc();     // 刷新
        HAL_Delay(500);

        ucLed[0] = 0;   // 灭
        led_proc();
        HAL_Delay(500);
    }
}

第 3 步(进阶):加入任务调度器

如果你有调度器,只需:

复制代码
// 在任务数组中添加
{led_proc, 1, 0}  // 每 1ms 检查一次(实际只在状态变化时刷新)

然后在主循环调用 scheduler_run() 即可!


🧠 本章口诀(背下来,不怕忘!)

💡 G431 板子要记牢

LED 接在 PC8 到 PC15!

🔌 共阳接法别搞反

软件写 0 灯才亮,写 1 就熄灭!

📦 ucLed 是指令箱

1=亮,0=灭,改它就生效!

刷新四步稳又准

清高8 → 取反写 → PD2高 → PD2低!

🛡️ 先清 0x00ff 很重要

保住低8位,安全又可靠!


✅ 动手挑战(适合小白)

while(1) 里加这段代码:

复制代码
static int dir = 1;
static int pos = 0;

ucLed[pos] = 1;          // 当前位置亮
led_proc();
HAL_Delay(200);
ucLed[pos] = 0;          // 熄灭

pos += dir;
if (pos == 7 || pos == 0) dir = -dir;  // 到头就回头

你会看到一颗小灯 左右来回跑!🎉

相关推荐
不能只会打代码2 小时前
蓝桥杯---垒骰子(Java实现,代码注释,图文讲解)
算法·蓝桥杯·动态规划·垒骰子
沧澜sincerely3 小时前
蓝桥杯11 路径之谜
c++·蓝桥杯·stl·dfs·剪枝
Swift社区19 小时前
LeetCode 443. 压缩字符串
leetcode·职场和发展·蓝桥杯
_OP_CHEN1 天前
【算法基础篇】(二十七)从记忆化搜索到动态规划:保姆级入门指南,带你吃透 DP 核心思想!
算法·蓝桥杯·动态规划·记忆化搜索·算法竞赛·acm/icpc
爬上树顶2 天前
软件项目中的人与事
程序人生·职场和发展·蓝桥杯
魂梦翩跹如雨2 天前
P8752 [蓝桥杯 2021 省 B2] 特殊年份——Java解答
java·蓝桥杯
大聪明-PLUS2 天前
C++编程中存在的问题
linux·嵌入式·arm·smarc
_OP_CHEN2 天前
【算法基础篇】(二十六)数据结构封神!Trie 树从入门到爆杀算法题:拼音输入法、单词统计都靠它
数据结构·c++·算法·蓝桥杯·trie树·算法竞赛·acm/icpc
是苏浙3 天前
蓝桥杯备战day3
蓝桥杯