test_led_strip/doc/光磁头软件架构文档.md

12 KiB
Raw Blame History

光磁头软件架构文档

本文档为光磁头(小板 / 温度传感端)固件的设计规范,源码实现应遵循本文档的模块划分、数据流与设计约束。 配套协议:通讯协议.md 硬件平台STM32G0B0板级 dr2501a_g0b0ce


1. 系统定位

光磁头是光磁热疗系统的温度传感端,通过一根 UART 线与主板(控制端)通信,向主板提供 9 路皮肤温度反馈,供主板 PID 温控闭环使用。

职责 说明
温度采集 9 路 godtek 温度传感器8 路经 CH9438 扩展 + 1 路片内直连)
温度上报 每 20ms 主动上报 9 路最大值(温度闭环反馈)
命令响应 响应主板查询ID / 温度)与运行状态设置
状态指示 按主板运行状态点亮红外灯与灯带
flowchart LR
    subgraph 光磁头[光磁头 传感端]
        S[9 路 godtek 传感器] -->|UART 触发| C[采集聚合 infrared]
        C -->|20ms 周期| T[温度上报 temp]
        T --> P[协议 com<br/>usart1 0x7EE7]
        P -->|运行状态| L[LED 指示 led]
    end
    P <-->|UART 115200| M[主板 控制端]

2. 硬件资源

外设 用途 关键配置
spi2 + CH9438INT# PB13 SPI→8×UART 扩展,传感器 ch0~7 SPI 500kHz8 口均 9600 8N1overlay use_ms.overlay
usart2PA2/PA3 片内第 9 路传感器ch8 9600 8N1
usart1PA9/PA10 与主板通信协议口 115200帧头 0x7EE7 + CRC16
usart3PA5/PB0 调试 console 115200
spi1 + WS281240 灯) 灯带指示standby/running/pause/error SPI 4MHz
led_infPB1 红外加热指示 LED 运行中点亮
led_mcu_statePA15 心跳灯 1s 周期闪烁
IWDG 系统看门狗 20ms 喂狗
graph TD
    subgraph MCU[STM32G0B0]
        U1[usart1 协议口<br/>115200] -->|0x7EE7 帧| MB[主板]
        U2[usart2 第9路<br/>9600] --> G8[godtek ch8]
        U3[usart3 console]
        SP2[spi2 500kHz] --> CH[CH9438<br/>INT# PB13]
        CH --> G0[godtek ch0]
        CH --> G1[godtek ch1]
        CH --> G7[godtek ch7]
        SP1[spi1 4MHz] --> WS[WS2812 灯带 ×40]
        LED1[led_inf PB1]
        LED2[led_mcu_state PA15]
        WDT[IWDG]
    end

传感器工作模式8 路外置为 wrist0xAC 测量命令),片内第 9 路默认 surface0xAA


3. 软件架构

graph TD
    subgraph 应用层
        MAIN[main 主线程]
        TEMP[temp 采集调度<br/>20ms 上报]
        COM[com 协议处理<br/>回调表/上电发ID]
        LED[led 状态指示]
        WDG[watdog 喂狗]
    end
    subgraph 聚合层
        IR[infrared 9路聚合<br/>触发注册/缓存/最大值]
    end
    subgraph 驱动层
        UC[uart_com 帧协议<br/>0x7EE7+CRC16]
        GD[godtek_temp 传感器驱动<br/>组帧/校验/触发]
        CH8[ch9438 SPI→8×UART]
        IND[led_strip_indicator 灯带]
    end

    TEMP --> IR
    TEMP --> COM
    COM --> UC
    IR --> GD
    GD --> CH8
    GD --> U2[usart2]
    LED --> COM
    LED --> IND
    MAIN -.后台驻留.-> TEMP

模块职责

模块 职责 关键约束
infrared(聚合层) 9 路传感器统一抽象:设备列表、触发注册、通道缓存、取最大值 缓存须 ISR 安全;通道编号固定 ch0~7=CH9438、ch8=片内
temp(应用层) 采集触发注册 + 20ms 周期上报最大值 触发注册必须在传感器驱动初始化之后
com(应用层) 协议帧收发、命令回调、运行状态信号广播 回调在系统 workqueue 线程执行;上电主动发 ID
led(应用层) 运行状态 → 红外灯 + 灯带;心跳灯 状态变化由 com 信号驱动,不轮询
watdog(应用层) IWDG 喂狗 20ms 周期;配置失败不得阻塞启动
main(应用层) 入口 + 后台驻留 各模块由 SYS_INIT 初始化

4. 数据流

4.1 温度采集链(触发驱动,无轮询)

9 路传感器全部由 UART 数据触发驱动,不占用 CPU 轮询:

flowchart LR
    S[godtek 传感器自发上报] --> CH[CH9438 INT# 中断<br/>或 usart2 RX 中断]
    CH --> WQ[系统 workqueue<br/>或 ISR]
    WQ --> GD[godtek 驱动<br/>组帧 + 校验]
    GD -->|有效帧| TRIG[触发回调<br/>更新第 I 路缓存]
    TRIG --> CACHE[volatile 通道缓存]
  • 帧校验+/- 符号 + 6 位十进制数字 + 温度范围(-40.0 ~ +125.0°C坏帧直接丢弃不上报
  • 上下文CH9438 端口回调在系统 workqueueSPI 安全);片内 usart2 回调在 ISR —— 回调内不得做任何阻塞操作

4.2 温度上报链20ms 周期)

flowchart LR
    T[temp 周期任务<br/>20ms] --> M[取 9 路缓存最大值]
    M --> C[组帧上报]
    C -->|0x7EE7 帧 00 02 整数 小数 CRC| U[usart1 → 主板]

温度值格式×10 整数(如 345 = 34.5°C上报数据 2 字节 [整数][小数]

4.3 命令响应链RX ISR → workqueue

flowchart LR
    RX[usart1 RX ISR<br/>逐字节帧状态机] -->|完整帧| P[拷贝到 pending 缓冲<br/>提交 work]
    P --> WQ2[系统 workqueue<br/>执行命令回调]
    WQ2 --> H[ID / 温度查询 / 运行状态]
    H --> LED2[运行状态 → LED 指示]
    H --> R[ID / 温度查询 → 回帧]

命令回调必须在 workqueue 线程上下文执行ISR 只做轻量拷贝),可安全使用 printk / uart_poll_out,避免 ISR 内阻塞导致温度上报停止。


5. 通信协议

帧结构(详见 通讯协议.md

| 7E | E7 | CMD | LEN | DATA[0..LEN-1] | CRC_L | CRC_H |
|----- 帧头 -----|     |                |-- CRC16 Modbus (lsb-msb) --|
指令 方向 内容 响应行为
0x00 温度 小板→主板(主动) 每 20ms 上报最大值2 字节 [整数][小数]
0x00 温度 主板请求→小板回复 请求时回复当前最大值 查询回复
0x01 ID 小板→主板(主动) 上电主动发一次3 字节hwinfo 前 3 字节)
0x01 ID 主板请求→小板回复 请求时回复 查询回复
0x02 运行状态 主板→小板 1 字节0x00 待机 / 0x01 运行 / 0x02 暂停 / 0x03 故障 更新状态并驱动 LED
sequenceDiagram
    participant S as 小板 光磁头
    participant M as 主板 控制端
    Note over S: 系统上电
    S->>M: 【主动】ID 帧 (0x01)
    loop 每 20ms
        S->>M: 【主动】温度最大值帧 (0x00)
    end
    Note over M: 运行状态变化
    M->>S: 运行状态帧 (0x02) → LED 指示
    opt 主板查询
        M->>S: 请求 ID (0x01)
        S-->>M: 回复 ID
        M->>S: 请求温度 (0x00)
        S-->>M: 回复温度最大值
    end

6. 初始化顺序

各模块通过 SYS_INIT 按以下顺序初始化(同优先级内不得存在跨模块依赖):

阶段 优先级 模块 说明
POST_KERNEL 驱动默认 ch9438 SPI 初始化、波特率配置9600含 FCR 时序处理)、中断使能
POST_KERNEL 传感器默认 godtek UART 回调注册、500ms 周期测量命令
APPLICATION 40 led GPIO / 灯带初始化 + 注册状态槽
APPLICATION 45 temp 触发注册(必须在 godtek 之后)+ 启动 20ms 上报
APPLICATION 50 com 协议回调表注册 + 上电主动发 ID
APPLICATION 60 watdog IWDG 安装 + 启动喂狗
APPLICATION 90 ch9438 flush POR 残留 FIFO 清空(边沿中断补偿)
main 主循环(后台线程)
sequenceDiagram
    participant B as 启动
    participant D as 驱动层
    participant A as 应用层
    B->>D: ch9438 初始化(波特率 9600 时序)
    B->>D: godtek 初始化(回调 + 500ms 测量命令)
    B->>A: led 初始化APPLICATION 40
    B->>A: temp 初始化APPLICATION 45触发注册
    B->>A: com 初始化APPLICATION 50上电发 ID
    B->>A: watdog 初始化APPLICATION 60
    B->>A: ch9438 flushAPPLICATION 90
    A->>D: 传感器数据触发 → 缓存 → 20ms 上报

7. 关键设计决策

7.1 波特率 POR 时序(重点坑)

现象烧录后波特率正常9600断电重启后回退为 115200部分端口只收到 0x00

根因CH9438 的 FCR 复位位RFIFORST/TFIFORST异步重置波特率分频器。POR 冷启动时 FCR 复位持续较久,把紧随其后的 9600 配置LCR/DLL/DLM清回芯片默认值 115200烧录时芯片未断电、复位瞬间完成因此正常。

修复(初始化顺序):

写 LCR(DLAB=1) → 写 DLL/DLM(9600) → 验证
→ 引脚配置 → FCR=0x07复位+使能,触发发生器重锁存)→ 1ms 延时
→ 重写 LCR(DLAB=1) → 重写 DLL/DLM(9600) → 回读验证(连 LCR 一起检查)→ LCR(DLAB=0)

回读验证假象DLAB 未锁存时,读 "DLL" 实际读到 RBRuart7 短接回环的 0x20、"DLM" 读到 IER0x4E——自洽的谎言。必须连 LCR 一起回读比对,确认 DLAB 真正置位;再加 8 次 ×20ms 重试兜底POR 后 UART 模块可能晚就绪,写入被静默丢弃)。

7.2 触发驱动采集

9 路全部由 UART 数据触发更新缓存,无轮询,响应实时;发送侧固定 20ms 周期取缓存最大值,采集与上报解耦。

7.3 缓存线程安全

volatile 字段 + 编译期通道索引触发回调ISR / workqueue 双上下文)与查询无锁,避免死锁与中断延迟。

7.4 回调上下文

协议命令回调全部在系统 workqueue 线程执行ISR 只做数据拷贝 —— 避免 ISR 内 uart_poll_out / printk 阻塞导致温度上报停止。

7.5 通道编号稳定

DT_FOREACH 按设备树节点顺序展开,若 usart2 排在 spi2 前会导致通道错位ch0 变成片内传感器)。通过按父节点 compatible 分两段构建设备列表,保证 ch0~7 = CH9438、ch8 = 片内。

7.6 坏帧丢弃

帧校验含符号、6 位数字与温度范围三重检查,字节丢失/错位产生的坏帧直接丢弃,不污染缓存。


8. 调试与诊断

8.1 打印规范

所有诊断打印由 APP_DEBUG_PRINT 宏控制(各模块默认 0默认只保留启动确认与错误打印

位置 打印内容
APP_DEBUG_PRINT=1 ch9438 波特率回读、work 计数、FIFO 扫描、运行期诊断
APP_DEBUG_PRINT=1 godtek 原始字节 dump、命令追踪
APP_DEBUG_PRINT=1 temp 每秒 9 路通道状态(含有效掩码)
APP_DEBUG_PRINT=1 com 协议错误统计

启动确认打印(应保留的最小集):

[ch9438] v1.0 port=0 ok          ← CH9438 8 端口初始化成功
[godtek] mode = 0xac: baudrate = 9600   ← 传感器模式与波特率确认
[app_led] Init: ...              ← LED 初始化
[app_temp]temp init              ← 温度模块初始化
[infra] ch0 ready=1 ... ch8 ready=1  ← 9 路设备就绪
[com] init: rx table=3, id sent  ← 协议就绪 + 上电 ID
[watchdog] init                  ← 看门狗就绪

8.2 常见问题排查

现象 排查方向
重启后波特率异常0x00 / 乱码) 确认 ch9438 初始化含 FCR 复位后重写波特率 + 回读验证§7.1
温度恒为 0.0 / 无数据 检查传感器 UART 波特率9600、测量命令周期500ms、帧校验是否丢帧
灯带无指示 检查 led_strip_indicator 节点、WS2812 SPI 时序
主板收不到上报 检查 usart1 115200、帧头 0x7EE7、CRC16 lsb-msb 与主板一致

8.3 回环自测

短接 CH9438 UART7 的 TX/RXPIN25 ↔ PIN26验证中断接收链路ISR → workqueue → 回调 → FIFO 读取),用于驱动回归测试。


9. 构建与烧录

# 构建board 定义在 boards/dr2501aoverlay 配置传感器波特率/模式)
west build -p auto -b dr2501a_g0b0ce/stm32g0b0xx app/app_photomagnetic \
  -d build -DOVERLAY_CONFIG=boards/use_ms.overlay

# 烧录
west flash -d build

板级传感器配置(波特率、模式)统一在 app/app_photomagnetic/boards/use_ms.overlay 中,不修改板级 dts。