# 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 缓存位图;串口下发由副板通信任务周期性执行。