- C 91%
- Assembly 4.8%
- Makefile 2.2%
- HTML 2%
| .claude | ||
| 1.程序/STM32_LED64X64_Clock_V4.0 | ||
| mario | ||
| CLAUDE.md | ||
| note.txt | ||
| README.org | ||
Mario Clock — STM32 + HUB75E 64×64 RGB LED 点阵屏
项目概述
硬件
MCU
| 项目 | Keil 工程 | mario 工程 |
|---|---|---|
| 芯片 | STM32F103ZE (512K Flash) | STM32F103C8T6 (64K Flash) |
| 晶振 | 12MHz 外部 | 8MHz 外部 |
| 系统时钟 | 72MHz (PLL) | 72MHz (PLL) |
| 调试接口 | SWD (PA13/PA14) | SWD (PA13/PA14) |
| JTAG | 已禁用 (释放 PB3/PB4) | 已禁用 (释放 PB3/PB4) |
LED 面板
- 类型:64×64 全彩 RGB LED 点阵屏
- 接口:=HUB75E=(2×8 排针,共 16 针)
- 结构:上下半屏独立驱动(R1/G1/B1 驱动上半 32 行,R2/G2/B2 驱动下半 32 行)
- 颜色深度:RGB222(每通道 2 位 = 64 色)
引脚接线 (mario 工程,标准 HUB75E 映射)
所有信号线接在 GPIOB,引脚定义见 =mario/src/led.c:6-19=:
| 信号 | 引脚 | 功能 |
|---|---|---|
| R1 | PB0 | 上半屏 红色数据 |
| G1 | PB1 | 上半屏 绿色数据 |
| B1 | PB2 | 上半屏 蓝色数据 |
| R2 | PB3 | 下半屏 红色数据 |
| G2 | PB4 | 下半屏 绿色数据 |
| B2 | PB5 | 下半屏 蓝色数据 |
| A | PB6 | 行地址 bit0 |
| B | PB7 | 行地址 bit1 |
| C | PB8 | 行地址 bit2 |
| D | PB9 | 行地址 bit3 |
| E | PB10 | 行地址 bit4 |
| CLK | PB11 | 移位时钟 |
| LAT | PB12 | 锁存脉冲 |
| OE | PB13 | 输出使能 (低有效) |
*重要*:Keil 工程的引脚映射不同——由于作者的面板 RGB 线序错位,R1/G1/B1 在程序中被调换了顺序(PB0=G1, PB1=B1, PB3=R1)。如果你的面板颜色不对,检查 led.c 中最前面的 LED_x_OUT 宏定义。
电源
LED 面板全白时电流可达 3–5A,*不能*从 STM32 开发板的 3.3V 取电。面板需要独立的 5V 电源供电,控制器和面板 共地 即可。
调试器接线
- 用 ST-Link / CMSIS-DAP / J-Link 等调试器
- 接 4 根线:=3.3V=,
GND,PA13(SWDIO),PA14(SWCLK)
软件工作原理
总体架构
┌──────────────────────────────────────────────┐
│ main() │
│ ├─ 系统初始化 (时钟, GPIO, 定时器) │
│ └─ while(1) │
│ ├─ [display_flag=1] 播放一遍动画 + 更新数字 │
│ └─ [display_flag=0] 持续刷新当前帧 │
└──────────────────────────────────────────────┘
▲
│ display_flag
│ num (0-999)
┌──────────────────────────────────────────────┐
│ TIM2 中断 (每 10ms) │
│ ├─ 计数 100 次 ≈ 1 秒置位 display_flag │
│ └─ num++, 模 1000 │
└──────────────────────────────────────────────┘
动画播放流程 (main.c)
动画共有 6 帧(=gImage_Mario_1= 到 =gImage_Mario_6=),播放方式为"来回顾盼": 1→2→3→4→5→6→[更新数字]→5→4→3→2→1
每帧调用 led_display_64x64_rgb222() 重复 GIF_DELAY_TIME (10) 次,目的是让扫描循环多执行几轮以维持视觉亮度和控制帧率。
当 display_flag==0 时(没有动画需要播放),主循环持续扫描第 1 帧作为"待机画面",让 LED 保持显示而非黑屏。
TIM2 定时器 (timer.c)
TIM2 是帧更新的"心跳"。配置如下:
| 参数 | 值 | 说明 |
|---|---|---|
| PSC | 7200-1 | 预分频:72MHz ÷ 7200 = 10kHz |
| ARR | 10000-1 | 自动重装载:10kHz ÷ 10000 = 1Hz |
| 实际中断频率 | 每 10ms 一次 | — |
每次中断中,软件计数器自增。累计 100 次(≈ 1 秒)后置位 display_flag~,同时将 ~num 加 1(模 1000 循环)。主循环检测到 display_flag==1 后播放一整遍动画,然后将其清零。
注意: mario 工程的中断处理方式与 Keil 工程不同。Keil 工程在每次 10ms 中断中都置位 flag(中断频率本身是 10ms),而 mario 工程中用软件计数器 counter 累加到 100 才触发,实际帧切换间隔约 1 秒。
HUB75E 显示驱动 (led.c)
HUB75E 接口的核心是 行扫描 + /移位输出/。64×64 面板被分为上下两个 32 行,同时驱动。
数据格式
图像数据以 RGB222 格式存储,每像素用 2 字节:
- 上半像素:第 1 字节高 4 位 = G[1:0] B[1:0],第 1 字节低 4 位 + 第 2 字节 = R[1:0]
- 下半像素:存储在数组后半段,格式相同
每个 64×64 的帧占 8192 字节(64×64×2 = 4096 像素 × 2 字节/像素)。
一次扫描输出过程 (led_display_64x64_rgb222())
- 解码 (
led_get_rgb222_pic):将 RGB222 格式的帧数据解成 RGB 缓冲数组 ~gImage_RGB_up/down[2048][3]~,每通道值 = 0–3(2 位) - 数字叠加 (
led_num_color_set):将 4 位数字对应区域的像素挖空(背景透明效果) -
*扫描输出*:4 级灰度 × 32 行循环:
- 设置行地址(A/B/C/D/E 五根地址线)
- 逐像素移位输出 64×6 个颜色位(上下半屏各 RGB 3 位),每个 CLK 脉冲输出一列
- LAT 锁存脉冲:将移位寄存器数据锁存到输出端
- OE 脉冲:使能输出,点亮当前行
- line++ ,进入下一行
4 级灰度实现
灰度通过 PWM 思想 实现:外层循环 grayscale 0→3 共 4 轮。对于每个像素,只有当当前灰度级 < 像素通道值时,才将该颜色引脚置高。例如像素 R=2,则灰度级 0 和 1 时亮,2 和 3 时灭,视觉上就是 50% 占空比的红色。
系统初始化 (sysinit.c)
| 步骤 | 说明 |
|---|---|
| 时钟 | 外部 8MHz 晶振 → PLL 倍频至 72MHz |
| AFIO | 使能复用功能时钟,释放 PB3/PB4 |
| JTAG | 禁用 JTAG,保留 SWD 调试接口 |
| GPIO | 所有 HUB75E 引脚初始化为 50MHz 推挽输出 |
马里奥帧数据
6 帧动画数据定义在 mario/src/font.c=,每帧 8192 字节的压缩 RGB222 数据,通过 =mario/include/font.h 以 extern 声明导出。
构建与烧录
Keil 工程
- 用 Keil uVision 打开
1.程序/STM32_LED64X64_Clock_V4.0/example.uvprojx - 重要:在 Project Options → C/C++ → Optimization 设为 ~Level 1 (-O1)~(提升帧率)
- F7 编译
- F8 下载到芯片
mario 工程(推荐)
依赖:~arm-none-eabi-gcc~, libopencm3, make, openocd
编译:
cd mario/
make
生成文件:=mario_led.elf=, mario_led.bin, mario_led.hex
烧录(使用 OpenOCD,默认 CMSIS-DAP):
make flash
如果使用 ST-Link,修改 =mario/Makefile:14=:
OPENOCD_INTERFACE = interface/stlink.cfg
调试:
make debug-server # 终端 1:启动 OpenOCD
make debug # 终端 2:启动 GDB
调试串口
mario 工程有调试串口:UART1 (PA9=TX, PA10=RX) @ 115200 8N1。启动时会输出 ~=== Mario LED Matrix ===~。
常见问题
- *颜色不对*:检查
led.c中 R1/G1/B1 的引脚宏定义,不同面板的 RGB 线序可能错位 - *亮度/帧率低*:确保编译优化等级为
-O1~(Keil)或 ~-Os~(GCC);减少 ~GIF_DELAY_TIME可加快动画速度但会降低亮度 - *花屏/抖动*:杜邦线过长会导致信号质量问题,建议打 PCB
- *面板不亮*:检查 OE 引脚初始状态是否为 HIGH(关闭输出),以及面板独立供电是否正常