docs(屏板): 批 1 收尾,1-2/1-3 判据回填并订正三处错口径
1-2 / 1-3 已于 2026-10-29 完成,判据按实测回填。同时订正原稿三处 会把人带错的口径: 1. 1-2 原写"改 .ioc 而不是只改 Src/usart.c,否则 CubeMX 重生成会丢"—— 这条路不存在:.ioc 不保存任何 UART 的波特率(只有 USART1.IPParameters=VirtualMode),GUI 里改也不落盘。实际做法是在 Src/usart.c 的 USER CODE BEGIN USART1_Init 2 区覆盖后重调一次 HAL_UART_Init,重生成会保留(KeepUserCode)。 2. 1-3 原写"本链路要自写这三个回调"——HAL_UARTEx_RxEventCallback 与 HAL_UART_ErrorCallback 已经有唯一实现(rs485.c),再写一份就是链接期 multiple definition。正确做法是各加一行转发。 3. §1.3 同一处说法同步订正。 另补两条台架实测口径(都会让人误判成"链路坏了"): - 错误回调里不能无条件重挂:NE/FE/PE 是非阻塞型,HAL 不停接收,再调 ReceiveToIdle_IT 只会拿到 HAL_BUSY(实测 err=160/rearm=160 同步涨)。 - PC + 杜邦线顶替屏板时 NE 每帧约 1.3 次,但 crc=0、ok==rx —— 数据完好, 属"能用的告警";真出问题的是 ORE。 §4.1 模块清单、§5 台架步骤(改用 test/host/screenlink_bench.py)、§0 的执行顺序结论一并更新。
This commit is contained in:
+27
-10
@@ -23,7 +23,7 @@
|
||||
**执行顺序因此是**:挪台架线 → 迁日志口 → 才开始写屏板链路。
|
||||
前两步**已于 2026-10-29 完成**(§3 批 0 的 0-1 / 0-2:台架线接 CN1 的 RS232#1,日志口迁到 UART5,
|
||||
台架串口由 `COM6` 变成 `COM3`,`.serialtest/config.json` 已同步);第三项 0-3 的接法也已落纸。
|
||||
**批 0 到此结束,下一步进批 1。**
|
||||
**批 0 与批 1 均已收尾(2026-10-29):USART1 已在 700 kbaud 上稳定收帧,下一步进批 2(帧 B 组帧 + TX DMA 起发)。**
|
||||
|
||||
---
|
||||
|
||||
@@ -74,9 +74,11 @@
|
||||
> `HAL_DMA_IRQHandler(&hdma_usart1_tx)`。在用的是 SPI1(DMA2 Stream0/3)、SPI2(DMA1)、ADC1(Stream4)
|
||||
> ——**与 Stream7 不冲突**,不必重新分配流,`.ioc` 也不用为 DMA 改任何东西(1-2 只改波特率)。
|
||||
> 主机侧 RX 仍然只要 16 B + 空闲中断(屏板只发 6 B),**不要开 RX DMA**。
|
||||
> **三个收尾回调全工程都没人实现**:`HAL_UART_TxCpltCallback` / `HAL_UART_RxCpltCallback` 零实现,
|
||||
> `HAL_UART_ErrorCallback` 只有一处、且只分发另一条通道的句柄(定位:全库搜这三个名字)→ 本链路要**自写这三个、
|
||||
> 按 `huart` 句柄分发**,错误分支里顺手清掉 USART1 的 ORE / NE / FE 再重挂接收(与 1-3 同一手法)。
|
||||
> **三个收尾回调的现状(2026-10-29 核实)**:`HAL_UART_TxCpltCallback` / `HAL_UART_RxCpltCallback`
|
||||
> 零实现(批 2 的 2-4 要写 TxCplt);`HAL_UART_ErrorCallback` 与 `HAL_UARTEx_RxEventCallback`
|
||||
> **已经有一处实现**——`Drivers/BSP/RS485/rs485.c`,只分发它自己那个句柄。所以本链路**不是"自写这三个"**:
|
||||
> 全局回调一个工程只能有一份定义,正确做法是**在那两处各加一行转发**,按句柄过滤放在 `sb_link` 里
|
||||
> (1-3 已按这个做法落地)。错误分支里清 ORE / NE / FE 再按需重挂。
|
||||
> **`.ioc` 在仓库根**(`STM32F407-Demo.ioc`,不在 `MDK-ARM/` 下):`Dma.Request0/1` 已列 `USART1_TX` / `USART1_RX`,
|
||||
> `DMA2_Stream7` 的 NVIC 优先级 9——与 `Src/dma.c`、`Src/stm32f4xx_it.c` 三处互相自洽(换流会被打回优先级 0,须回 `Src/dma.c` 核对)。
|
||||
|
||||
@@ -91,7 +93,7 @@
|
||||
| 项 | 结论 |
|
||||
|---|---|
|
||||
| 端口 | **USART1**——唯一一条 MCU 引脚直出 TTL、不经收发器的通道,同时引到 U5 子板连接器 |
|
||||
| 波特率 | 700000 8N1,`BRR = 0x0078`(APB2 84 MHz → `84 000 000 / (16 × 700 000) = 7.5`,误差 0 %) |
|
||||
| 波特率 | 700000 8N1,`BRR = 0x0078`(APB2 84 MHz → `84 000 000 / (16 × 700 000) = 7.5`,误差 0 %)。**2026-10-29 开机日志实测就是 `0x0078`**(1-2) |
|
||||
| 方向控制 | **不需要**——TTL 直连是 TX / RX 两根独立线(全双工),没有方向切换 |
|
||||
| 剩余子决策 | **USART1 那端怎么接**:TTL 直连屏板 UART2 侧(PA2/PA3,绕过屏板自己的收发器)。**台架按这条做**;产品形态的线束长度与隔离需求届时单独评估 |
|
||||
|
||||
@@ -244,12 +246,26 @@
|
||||
| 序 | 任务 | 改动点 | 判据 |
|
||||
|---|---|---|---|
|
||||
| 1-1 ✅ | **协议层模块(纯逻辑,可主机单测)** | 新建 `Drivers/BSP/ScreenLink/sb_proto.c/h`:CRC-16/MODBUS(与屏板同一多项式,用 16 位合并表)、帧 A 解析、帧 B 组帧(普通图 / LOGO)、帧 B 自校验;双端注册:uvprojx 加 File + IncludePath,模拟器侧走 `scripts/check_registration.py` 的 MCU-only 豁免(纯逻辑,模拟器无消费路径) | **已完成 2026-10-29**:主机单测 **59/59 PASSED**(`test/host/sb_proto/`),覆盖率 74/74 行、6/6 函数;屏板实测向量 `01 03 01 00 F0 48` 与 `01 03 00 09 31 DE` 原样解析通过;组出的两种帧按屏板 `Check_CRC` 口径复核均被接受;Keil 构建 **0 错误 0 警告**(`Code` 不变——尚无调用者,链接器按未用节丢弃) |
|
||||
| 1-2 | **波特率与格式落地** | `STM32F407-Demo.ioc` 里把 **USART1** 改 **700000 / 8N1 / 16 倍过采样**(改 `.ioc` 而不是只改 `Src/usart.c`,否则 CubeMX 重生成会丢);`Src/usart.c` 只写 USER CODE | 示波器/逻辑分析仪实测位宽误差 **< 1 %**;理论值 `USARTDIV = 7.5`、`BRR = 0x0078`(APB2 84 MHz),误差 0 % |
|
||||
| 1-3 | **USART1 收中断与全局回调分支** | 开 IDLE 中断接收(缓冲 **16 B**);`HAL_UARTEx_RxEventCallback` 里**加 USART1 分支**(现有回调只把事件分发给另一条在用通道的句柄,不加分支会静默收不到);`HAL_UART_ErrorCallback` 同样要加,且**必须清 ORE/NE/FE 并重挂接收**(`__HAL_UART_CLEAR_OREFLAG` 或读 SR 再读 DR) | 屏板每 280 ms 发来的 6 B 能稳定收到,`Size == 6`,CRC 通过率 100 %;**拔插一次 TX 线制造噪声后能自动恢复**(不清 ORE 会永久锁死) |
|
||||
| 1-2 ✅ | **波特率与格式落地** | **改 `Src/usart.c` 的 `USER CODE BEGIN USART1_Init 2` 区**(覆盖 `huart1.Init.BaudRate` 后重调一次 `HAL_UART_Init`)——**`.ioc` 这条路不存在**:`.ioc` 不保存任何 UART 的波特率(只有 `USART1.IPParameters=VirtualMode`),GUI 里改也不落盘,与 IWDG 那些"写进 `.ioc` 才不怕重生成"的情形不同 | **已完成 2026-10-29**:开机日志实测 `BRR=0x0078`(APB2 84 MHz / (16 × 700 kHz) = 7.5 → 整数 7、小数 0.5×16 = 8,误差 **0 %**),与理论值逐位相符,不必再架示波器;700 kbaud 下 10 分钟收帧零 CRC 错 |
|
||||
| 1-3 ✅ | **USART1 收中断与全局回调分支** | 新建 `Drivers/BSP/ScreenLink/sb_link.c/h`:开 IDLE 中断接收(缓冲 **16 B**);`HAL_UARTEx_RxEventCallback` / `HAL_UART_ErrorCallback` 里**各加一行转发**(两个回调是全局单例,唯一实现在 `rs485.c`,按句柄过滤在 `sb_link` 内做);错误分支**清 ORE/NE/FE/PE 并按需重挂** | **已完成 2026-10-29**(PC + USB 转 TTL 顶替屏板,`COM6` @700000):`rx == 发送帧数`、`ok == rx`、`crc=0`、`len=0`、`size=6`,`keys` 随按键帧递增;先用错波特率灌 64 B 垃圾(`len=31`、`bits=0x06`)后**自动恢复**,`rearm=0`。主机单测 **81/81 PASSED**(`test/host/sb_link/`),Keil **0 错误 0 警告** |
|
||||
|
||||
> ⚠ **`HAL_UARTEx_RxEventCallback` / `HAL_UART_ErrorCallback` 是全局单例**——全工程只有一处实现,
|
||||
> 现在只按它自己那个 `huart` 句柄分发(定位:全库搜这两个回调名就能找到实现处)。
|
||||
> USART1 必须加自己的分支,否则中断进来了但没人处理——表象是"屏板一直超时",很容易误判成协议错。
|
||||
> **分支只能"加一行转发",不能"自写一份"**:再定义一次就是链接期 multiple definition。
|
||||
|
||||
> ⚠ **错误回调里不能无条件重挂**(2026-10-29 台架实测踩到):HAL 把错误分成两类——
|
||||
> **ORE 是阻塞型**(先 `UART_EndRxTransfer` 把 `RxState` 打回 READY,再回调,必须重挂);
|
||||
> **NE/FE/PE 是非阻塞型**(接收照跑,`RxState` 仍是 `BUSY_RX`,此时再调 `ReceiveToIdle_IT`
|
||||
> 只会拿到 `HAL_BUSY`)。旧写法无条件重挂,于是台架上出现 `err=160 / rearm=160` 完全同步增长——
|
||||
> 看着像"每帧都重挂失败、链路快死了",其实一次都没真失败。判据用 `RxState == HAL_UART_STATE_READY`
|
||||
> 而不是错误位:它直接回答"现在挂着接收没有"。主机单测 `TC-SBLINK-015` 钉住了这条。
|
||||
|
||||
> ⚠ **PC + 杜邦线顶替屏板时会有 NE(噪声错)**:实测 `bits=0x02`、每帧约 1.3 次,
|
||||
> 但 `crc=0` 且 `ok == rx`——数据完好,只是采样点被判噪声(线材无屏蔽、无终端匹配)。
|
||||
> 判读口径写进了 `sb_link.h` 的 `err_bits` 注释:**NE/FE 而 `rx_ok` 照涨 = 能用的告警,不是故障**;
|
||||
> 真出问题的是 ORE(`0x08`)——那是处理不过来,本链路 6 B/280 ms 不该出现。
|
||||
> 台架上没造出 ORE(CPU 读 DR 太快),那条路径由主机单测按 RM0090 的清除语义覆盖。
|
||||
|
||||
### 批 2 · 协议实现(5 项)
|
||||
|
||||
@@ -288,8 +304,9 @@
|
||||
|
||||
```
|
||||
Drivers/BSP/ScreenLink/
|
||||
├── sb_proto.c/h 纯逻辑:CRC-16、帧 A 解析、帧 B 组帧 ← 可主机单测
|
||||
└── sb_link.c/h 传输:USART1 中断起发 + TX DMA、组帧入口、状态灯映射表 ← 依赖 HAL,仅 MCU
|
||||
├── sb_proto.c/h 纯逻辑:CRC-16、帧 A 解析、帧 B 组帧 ← 可主机单测(1-1 ✅)
|
||||
└── sb_link.c/h 传输:USART1 收中断 + ORE 清除 + 统计上报 ← 依赖 HAL,仅 MCU(1-3 ✅)
|
||||
(批 2 再往里加:组帧入口、TX DMA 起发、状态灯映射表)
|
||||
```
|
||||
|
||||
**为什么拆两层**:协议层不碰 HAL 才能在 `test/host/` 里跑单测(项目既有做法:原样 include 生产 `.c`,
|
||||
@@ -368,7 +385,7 @@ stub 提供 HAL)。屏板侧 CRC 有查表实现,**用同一张表做交叉
|
||||
|---|---|---|---|
|
||||
| 0 | **腾位置**:串口线挪到 RS-232 侧、日志迁走 | 改接串口线 + 一个 **USB 转 RS-232 适配器** | USART1 空出来,日志照旧能看(批 0) |
|
||||
| 1 | 协议层单测(`test/host/screenlink/`) | 无硬件 | CRC 与组帧的正确性,可回归 |
|
||||
| 2 | PC 串口助手**模拟屏板**:手发 6 B 召唤帧,看主机回的 4208 B | **USB 转 TTL 模块**接 USART1(PA9/PA10)+ 主机板 | 主机侧协议 100 % 可验证 |
|
||||
| 2 | PC **模拟屏板**:按屏板节拍发 6 B 召唤帧(脚本 `test/host/screenlink_bench.py`,`--port COM6 --key 5`;`--glitch-baud 115200` 可灌噪声验自愈) | **USB 转 TTL 模块**接 U5 的 `ST_RX0`/`ST_TX0`(PA10/PA9)+ 主机板 | 批 1 只验**收**(已做:`ok == rx`、`crc=0`、`size=6`、噪声后自愈);批 2 再验主机回的 4208 B |
|
||||
| 3 | 反向:PC 收主机帧,用脚本核对 4208 B / CRC / 显存内容 | 同上 | 帧内容正确性(与 `g_ui_fbuf` 逐字节比) |
|
||||
| 4 | **接真屏板**(TTL 直连屏板 UART2 的 PA2/PA3 一侧) | 屏板实物 + 屏板 TTL 引出 | 出图 + 按键 + 状态灯全链路 |
|
||||
| 5 | 产品形态:按最终线束接法定版 | 线束 | 产品形态验证 |
|
||||
|
||||
Reference in New Issue
Block a user