9ceb218f80
Co-authored-by: Cursor <cursoragent@cursor.com>
173 lines
7.4 KiB
Markdown
173 lines
7.4 KiB
Markdown
# sub_comm 模块说明
|
||
|
||
> 路径:`app/sub_comm/`
|
||
> 返回主说明:[README](../../README.md)
|
||
|
||
## 1. 模块职责
|
||
|
||
- 主板侧 **USART0** 与副板(CCU621-S)通信:`0x01` 接收 DI/DIP,`0x02/0x03/0x04` 下发 DO 与系统/枪信息;
|
||
- 维护副板 YK/YX 缓存,供其它模块读写;
|
||
- FreeRTOS 周期任务:接收拼帧、发送轮询、DI 超时清零遥信缓存。
|
||
|
||
## 2. 关键文件
|
||
|
||
- `sub_comm_task.c`
|
||
- `sub_comm_task.h`
|
||
|
||
## 3. 功能说明
|
||
|
||
- 任务模型对齐工程其它通信任务(初始化、周期循环、任务锁、喂狗、日志);
|
||
- **执行周期 `50ms`**(`app_init.c` 中 `TASK_SLEEP_MS_50`);
|
||
- 对外接口:
|
||
- `void v_sub_comm_task(void *arg)`:SubComm 线程入口(FreeRTOS)
|
||
- `void v_sub_comm_yk_set(E_SUB_YK_TYPE e_type, E_CMD e_cmd)`:写入待下发的 DO(YK)缓存;实际下发见 `v_sub_comm_tx_process()` 轮询
|
||
- `E_CMD e_sub_comm_yk_get(E_SUB_YK_TYPE e_type)`:读取 YK 缓存
|
||
- `U8_T u8_sub_comm_yx_get(E_SUB_YX_TYPE e_type)`:读取最近一次有效 `0x01` 刷新后的 YX/DIP 缓存
|
||
|
||
## 4. 维护建议
|
||
|
||
- 校验字段实现上使用 `u16_crc_checksum()`,函数名为历史命名,实质为 **字节累加和**(见 `public_func.c`),与副板 `subcomm_checksum8` 语义一致(结果取低 8 位);
|
||
- 可增加链路统计(超时次数、校验失败计数)便于现场诊断;
|
||
- 大报文时可评估环形缓冲;当前 `SUBCOMM_RX_BUF_MAX=128` 与副板一致。
|
||
|
||
## 5. 关联文档
|
||
|
||
- [plat_comm模块说明](../plat_comm/plat_comm模块说明.md)
|
||
- 主索引:[README](../../README.md)
|
||
|
||
---
|
||
|
||
## 6. 协议格式说明(副板:USART0,主板<->副板)
|
||
|
||
本模块使用自定义短帧协议,帧头/帧尾固定,命令码区分 DI 上报与 DO 控制。
|
||
|
||
### 6.1 帧结构(通用)
|
||
|
||
单帧总长度:`total_len = 5 + len`(其中 `len` 为数据域长度)
|
||
|
||
| 字节序号 | 字段 | 说明 |
|
||
| --- | --- | --- |
|
||
| `[0]` | `HEAD` | 固定帧头:`0x5A` |
|
||
| `[1]` | `cmd` | 命令码(DI/DO) |
|
||
| `[2]` | `len` | 数据域长度:`0~64` |
|
||
| `[3..3+len-1]` | `data[]` | 数据域(按 `cmd` 不同含义不同) |
|
||
| `[3+len]` | `sum` | 校验:对帧头到数据域的校验结果取低 8 位 |
|
||
| `[4+len]` | `TAIL` | 固定帧尾:`0xA5` |
|
||
|
||
### 6.2 校验字段 `sum`
|
||
|
||
- 校验计算(发送与接收一致):
|
||
- `sum = (uint8_t)u16_crc_checksum(&buf[0], 3 + len)`
|
||
- 即对 `[0]~[2+len]`(帧头+cmd+len+data)做 `u16_crc_checksum`,再取低 8 位作为 `sum`
|
||
|
||
### 6.3 命令码定义
|
||
|
||
- `0x01`:`SUBCOMM_CMD_DI_STATUS`
|
||
- 方向:副板 -> 主板(上报 DI 状态)
|
||
- 数据域长度:工程约定 `len >= 2`(低 16bit 有效)
|
||
- `0x02`:`SUBCOMM_CMD_DO_CTRL`
|
||
- 方向:主板 -> 副板(控制副板继电器 DO11~DO16)
|
||
- 数据域长度:固定 `len = 2`(两个字节编码 DO11~DO16 + 预留位)
|
||
- `0x03`:`SUBCOMM_CMD_SYS_INFO`
|
||
- 方向:主板 -> 副板(下发系统信息)
|
||
- 数据域长度:固定 `len = 22`
|
||
- `0x04`:`SUBCOMM_CMD_GUN_INFO`
|
||
- 方向:主板 -> 副板(下发充电枪信息)
|
||
- 数据域长度:固定 `len = 14`
|
||
|
||
### 6.4 DI 状态帧(`cmd=0x01`)数据域映射
|
||
|
||
通信方向:**副板 -> 主板**(副板上报 DI/DIP 状态)。
|
||
|
||
数据域低 16bit(`data[0]` 为低字节,`data[1]` 为高字节)用于承载:
|
||
|
||
- `bit0 -> YX13`
|
||
- `bit1 -> YX14`
|
||
- `...`
|
||
- `bit9 -> YX22`
|
||
- `bit10 -> DIP1`
|
||
- `...`
|
||
- `bit15 -> DIP6`
|
||
|
||
当接收未超时(见 6.5)时,上述位值被写入副板缓存 `g_subcomm_ctx.sub_yx.u32_bits`。
|
||
|
||
### 6.5 DO 控制帧(`cmd=0x02`)数据域映射
|
||
|
||
通信方向:**主板 -> 副板**(主板下发 DO11~DO16 控制命令)。
|
||
|
||
数据域固定 2 字节(`payload[0]` 为低字节,`payload[1]` 为高字节),承载:
|
||
|
||
- `bit0 -> DO11(K1)`
|
||
- `bit1 -> DO12(K2)`
|
||
- `bit2 -> DO13(K3)`
|
||
- `bit3 -> DO14(K4)`
|
||
- `bit4 -> DO15(K5)`
|
||
- `bit5 -> DO16(K6)`
|
||
- `bit6 -> RSVD1`(预留遥控位,不参与当前业务)
|
||
- `bit7 -> RSVD2`
|
||
- `...`
|
||
- `bit11 -> RSVD6`
|
||
- `bit12~bit15`:保留对齐
|
||
|
||
### 6.6 系统信息帧(`cmd=0x03`)数据域映射(新增)
|
||
|
||
通信方向:**主板 -> 副板**(主板周期/按需下发系统状态信息)。
|
||
|
||
数据域固定 22 字节,字段定义如下:
|
||
|
||
| 偏移 | 长度 | 字段 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `0` | `12` | `time_str` | 当前时间,ASCII 格式 `YYMMDDhhmmss`,示例:`260101120000` |
|
||
| `12` | `1` | `gun_cnt` | 枪数量,单字节 `0~N` |
|
||
| `13` | `1` | `led_board_type` | 灯板类型,单字节 `0~N` |
|
||
| `14` | `1` | `liquid_cooling_enable` | 液冷使能标志,`0/1` |
|
||
| `15` | `1` | `liquid_cooling_type` | 液冷类型;本工程未提供数据来源,默认 `0x00` |
|
||
| `16` | `6` | `rsvd` | 预留 6 字节,当前固定 `0x00` |
|
||
|
||
说明:
|
||
|
||
- 时间字段为纯 ASCII 数字,不带结束符 `\0`;
|
||
- `gun_cnt` 建议来自主板当前配置枪数;
|
||
- `led_board_type` 建议在后续实现时由板型参数或配置项给出。
|
||
- `liquid_cooling_enable` 取值来源:主板系统配置 `u_enable.bit_enable.bit_YeLenEn` 的最低位(约定 `0/1`);
|
||
- `liquid_cooling_type` 当前未对接任何系统接口,固定为 `0`(预留给后续协议扩展)。
|
||
|
||
### 6.7 充电枪信息帧(`cmd=0x04`)数据域映射(新增)
|
||
|
||
通信方向:**主板 -> 副板**(按枪号下发枪状态信息)。
|
||
|
||
数据域固定 14 字节,字段定义如下:
|
||
|
||
| 偏移 | 长度 | 字段 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| `0` | `1` | `gun_no` | 充电枪号,单字节,取值 `1/2` |
|
||
| `1` | `1` | `gun_link` | 枪连接状态,`0` 未连接,`1` 已连接 |
|
||
| `2` | `1` | `charge_state` | 充电状态,取 `flow_interface.c` 的 `e_flow_real_state`(`u16_flow_put_data(...E_FLOW_PUT_DATA_GUN_REAL_STATE...)`) |
|
||
| `3` | `1` | `led_state` | 指示灯状态,枚举参考 `E_LED_STATE_TYPE`:`0`绿常亮、`1`绿闪、`2`红常亮、`3`红闪、`4`黄常亮、`5`黄闪 |
|
||
| `4` | `1` | `fault_alarm_flag` | 故障告警标志:`0`无、`1`故障、`2`告警 |
|
||
| `5` | `1` | `soc` | 充电 SOC,单字节 `0~100` |
|
||
| `6` | `8` | `rsvd` | 预留 8 字节,当前固定 `0x00` |
|
||
|
||
### 6.8 发送节拍与接收超时
|
||
|
||
> 说明:当前 `sub_comm_task.c` 中 DO/信息帧发送节拍由 SubComm 线程 `50ms` 周期的轮询位移决定,而不是由某个固定 `SUBCOMM_CMD_PERIOD_MS` 常量直接控制。
|
||
|
||
- DO 控制帧 `0x02`:
|
||
- 在 `v_sub_comm_tx_process()` 中通过 `s_send_turn` 轮询发送;
|
||
- 当 SubComm 任务周期为 `50ms` 时,`0x02` 下发约为 `100ms/次`(偶数执行周期发送)。
|
||
- 系统信息 `0x03` / 枪信息 `0x04`:
|
||
- 与 `0x02` 轮流发送;
|
||
- 轮询顺序为:`0x03`(系统)-> `0x04`(枪1)-> `0x04`(枪2,若配置存在)-> 下一轮。
|
||
- DI 接收超时(离线判断):
|
||
- `SUBCOMM_DI_TIMEOUT_MS = 5000ms`
|
||
- 若超过该时间未收到有效 DI 状态帧(`cmd=0x01`),则清零副板 YX/DIP 缓存,避免使用过期状态。
|
||
|
||
### 6.9 收发处理流程(概览)
|
||
|
||
- 接收端:
|
||
- 从 USART0 FIFO 尽可能读取数据追加到 `rx_buf`(支持粘包/残包)。
|
||
- 在 `while (u8_sub_comm_try_parse_one_frame() != 0) {}` 中循环解帧,校验失败则丢弃 1 字节重新同步。
|
||
- 处理策略:当前接收侧仅对 `cmd=0x01` 的 DI 状态帧刷新 YX/DIP 缓存,其它 `cmd` 默认不落业务缓存。
|
||
- 发送端:
|
||
- 上层通过 `v_sub_comm_yk_set()` 仅修改副板 YK 缓存位图;串口下发由副板通信任务周期性执行。
|