# 代码怎样工作：两段讲解动画

这两段动画配合真实源码摘录，适合放在实物演示之后，解释主循环和一次查询怎样运行。每段 18 秒，原生 1920 × 1080、24 fps、H.264 MP4，无声；对应 SRT 可导入剪辑软件，照着字幕录旁白。PNG 为第 8 秒的预览，额外抽帧检查保存在构建排除的 `artifacts/code-video-qa/`。

## 07 · 主循环

[播放 MP4](07-main-loop.mp4) · [字幕与旁白](07-main-loop.srt) · [预览 PNG](07-main-loop-preview.png)

先看初始化，再看当前测量类型。直线模式和角度模式每轮只走一条解算分支，之后调用协议轮询；RTT 和状态灯按各自的时间条件处理。上方原码采样持续运动，说明 ADC 连续扫描、DMA 循环写入是在初始化后由硬件持续进行，主循环没有每轮重新启动 ADC。

“直线分支 → 角度分支”的展示是为了解释两种选择，并不表示同一轮会调用两个函数。右侧只是功能关系，ADC 三路也不是严格同时采样；没有标注未实测的循环频率或延迟。

旁白：

> 先看初始化，采样和通信先准备好。然后按当前类型选择解算。直线模式走直线分支，角度模式走角度分支，每轮只选一条。再处理协议，继续下一轮。采样硬件持续工作，不会每轮重启。

## 08 · RS485 查询与应答

[播放 MP4](08-rs485-query.mp4) · [字幕与旁白](08-rs485-query.srt) · [预览 PNG](08-rs485-query-preview.png)

以单设备、单播 `GET_DATA` 查询为例：主机发送请求，USART0 中断调用接收函数，把字节放进接收环；主循环取字节拼帧，先检查长度和 CRC，再检查测量类型、地址和命令。发送时 PB5 拉高，发送完成后拉低回到接收。

CRC、类型或地址不匹配的帧会静默丢弃；通过帧校验的有效请求如果参数不对，可返回非成功状态。这两类情况不同。广播、主动上报、超时与全部命令分支未在这段短片中展开。动画没有实际发送串口请求，不表示真实收发时序或保护能力。

旁白：

> 电脑先发一帧查询。串口中断把字节收进来。主循环取出字节，拼成帧。先检查长度和 CRC，再核对类型、地址和命令。PB5 拉高发送，发完拉低接收。校验错就丢弃；参数错回错误状态。

## 源码与版本

两段均依据教学仓库内 **2026-10-27 源码快照**，不是原工程此后修改的新版本。源文件路径、SHA-256 和显示或支撑说明的行号范围记录在 [source-references.json](source-references.json)。代码面板按真实行号读取，`…` 与 `/* ... */` 表示省略未展示的行，不是新增到固件的代码；图中的箭头和高亮是后期教学标注。

依据文件：

- [主程序](../../../software/firmware/src/main.c)：初始化顺序、类型选择、解算与协议调用。
- [ADC 与 DMA](../../../software/firmware/src/hall_encoder.c)：连续扫描、过采样、循环 DMA 与初始化触发。
- [中断入口](../../../software/firmware/src/gd32e23x_it.c)：USART0 IRQ 调用。
- [协议实现](../../../software/firmware/src/rs485_proto.c)：接收环、拼帧、CRC、类型/地址处理、PB5 发送方向。

## 重新生成

安装 Pillow，并保证 FFmpeg 在 PATH。默认字体为 Windows 微软雅黑和 Consolas；可用环境变量 `HALL_VIDEO_FONT`、`HALL_VIDEO_BOLD`、`HALL_VIDEO_MONO` 指定本地字体。

```powershell
python media/animation/code/render_code_clips.py
# 只生成其中一段
python media/animation/code/render_code_clips.py 07
python media/animation/code/render_code_clips.py 08
```

脚本写入临时视频，编码成功后再替换成品，避免留下零字节 MP4。若更新了固件，先重新核对说明与旁白，再重新生成；不要把旧版说明直接贴到新版演示上。
