# Modbus RTU 报文说明 本文档描述 STM32 通过 RS485 接口轮询 Noris AMS 模块的 Modbus RTU 通信协议, 以及报警数据如何通过 RF433 无线上报。 --- ## 1. Modbus RTU 请求帧 (MCU → Noris AMS) ```text 01 03 04 88 00 01 C5 D3 -- -- -- -- -- -- -- -- | | | | | | | | | | | | | | | +-- CRC16 低字节 | | | | | | +------ CRC16 高字节 | | | | | +---------- 读取数量 = 1 个寄存器 (00 01) | | | +------------------ 寄存器起始地址 = 0x0488 = 1160 (Noris 41161) | | +---------------------- 功能码 = 0x03 (Read Holding Registers) | +-------------------------- 从站地址 = 1 +------------------------------ 固定从站地址 ``` - 帧长度: 8 字节 - 发送间隔: 1000ms (MODBUS_RTU_POLL_INTERVAL) - 发送方式: HAL_UART_Transmit() 阻塞发送, @19200bps 约 4.2ms --- ## 2. Modbus RTU 正常响应帧 (Noris AMS → MCU) ```text 01 03 02 00 F0 B8 47 -- -- -- -- -- -- -- | | | | | | | | | | | | | +-- CRC16 高字节 | | | | | +------ CRC16 低字节 | | | | +---------- 寄存器值低字节 = 0xF0 | | | +-------------- 寄存器值高字节 = 0x00 (大端序) | | +------------------ 数据字节数 = 2 (1个寄存器 × 2字节) | +---------------------- 功能码 = 0x03 (正常响应) +-------------------------- 从站地址 = 1 ``` - 帧长度: 7 字节 - 寄存器值: 0x00F0 (大端序) --- ## 3. 寄存器值 → 报警位映射 寄存器 41161 值为 0x00F0 时的位分布: ```text Bit: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 ↑ ↑ ↑ ↑ │ │ │ └─ Bit4: 火灾综合报警 (Fire) │ │ └──── Bit5: 水密门综合报警 (Door) │ └─────── Bit6: 舱底水综合报警 (Bilge) └────────── Bit7: 气体检测综合报警 (Gas) ``` 提取宏定义 (modbus_rtu_master.h): ```c NORIS_FIRE_ALARM(reg) = (reg >> 4) & 1 // Bit4 → 报警字节 Bit0 NORIS_DOOR_ALARM(reg) = (reg >> 5) & 1 // Bit5 → 报警字节 Bit1 NORIS_BILGE_ALARM(reg) = (reg >> 6) & 1 // Bit6 → 报警字节 Bit2 NORIS_GAS_ALARM(reg) = (reg >> 7) & 1 // Bit7 → 报警字节 Bit3 ``` 映射后的紧凑报警字节 (0x00F0 → 0x0F): ```text Bit: 7 6 5 4 3 2 1 0 0 0 0 0 1 1 1 1 ↑ ↑ ↑ ↑ │ │ │ └─ Bit0: 火灾报警 │ │ └──── Bit1: 水密门报警 │ └─────── Bit2: 舱底水报警 └────────── Bit3: 气体检测报警 ``` --- ## 4. 报警状态变化上报 (主动上报, Type 0x10) 当 Modbus RTU 报警状态发生变化时,立即发送此包。 格式与原 DI 变化通知完全一致,上位机代码无需修改。 ```text AA 10 03 ID XX SUM -- -- -- -- -- --- | | | | | | | | | | | +-- 校验和 | | | | +------ 报警状态字节 (见第3节报警字节定义) | | | +---------- 本机设备 ID | | +-------------- 长度固定为 0x03 (ID + 1字节状态 + SUM) | +------------------ 类型标识:0x10 (I/O Data) +---------------------- 固定起始符 ``` 示例 (设备ID=105, 报警=0x0F): ```text AA 10 03 69 0F [SUM] ``` 触发条件: Modbus RTU 轮询到报警状态变化,且非首次轮询结果。 --- ## 5. 系统心跳包 (30秒/次, Type 0xAA) ```text AA AA 09 ID [SEQ_H] [SEQ_L] [FW_H] [FW_L] [RTU] [TCP_H] [TCP_L] SUM -- -- -- -- --------------- ------------- ---- --------------- --- | | | | | | | | | | | | | | | | | +-- 校验和 | | | | | | | +------------- Modbus TCP 寄存器值 | | | | | | +------------------------ Modbus RTU 报警状态 | | | | | | Bit0:火灾 Bit1:水密门 | | | | | | Bit2:舱底水 Bit3:气体检测 | | | | | +------------------------------------ 固件版本编码 | | | | +--------------------------------------------------- 序列号 (0-65535) | | | +------------------------------------------------------------- 本机设备 ID | | +----------------------------------------------------------------- LEN = 9 | +--------------------------------------------------------------------- 类型 0xAA +------------------------------------------------------------------------- 固定起始符 ``` Payload 字段说明: | 偏移 | 字段 | 长度 | 说明 | |------|----------|------|------| | 0-1 | SEQ | 2 | 序列号 (16-bit 大端, 0-65535 循环自增) | | 2-3 | FW | 2 | 固件版本编码 (MAKE_XTELL_CODE 宏) | | 4 | RTU | 1 | Modbus RTU 报警状态字节 (原 DI 状态位,现替换为报警位) | | 5-6 | TCP | 2 | Modbus TCP 最后寄存器值 (0xFFFF 表示无效) | --- ## 6. Modbus RTU 异常响应帧 (参考) 如果从站返回异常: ```text 01 83 02 C0 F1 -- -- -- -- -- | | | | | | | | | +-- CRC16 校验 | | | +------ 异常码 = 02 (非法寄存器地址) | | +---------- 功能码 + 0x80 (异常标志, 0x03 → 0x83) | +-------------- 从站地址 +------------------ ``` 处理: 异常响应 FC ≠ 0x03,被 parse_modbus_response() 中 mb_rx_buf[1] != 0x03 判断拦截,静默丢弃。 --- ## 7. 状态机与轮询时序 ### 7.1 状态机 ```text IDLE ──[1000ms到]──> WAIT_POLL ──[立即发送]──> WAIT_RESPONSE ↑ │ │ ┌─────────────┤ │ │ │ │ [帧接收完成] [超时500ms] │ │ │ └──────────── PROCESS ←─────────┘ │ │ │ │ (解析+更新报警) │ └────────────────────────────────┘ ``` ### 7.2 轮询时序示例 ```text 时间 0ms 1000ms 2000ms 3000ms │ │ │ │ T0 ├─TX(8B,4ms) ├─RX(7B,4ms) ├─解析 │ T1 ├─TX ├─RX ├─解析 │ T2 ├─TX ├─超时500ms ├─回IDLE │ T3 ├─TX ├─RX ├─解析 ``` 每秒一个完整轮询周期: 发送(~4ms) + 等响应(~10ms) + 解析(<1ms) ≈ 15ms,其余 985ms 空闲。 ### 7.3 关键超时参数 | 参数 | 值 | 说明 | |------|------|------| | MODBUS_RTU_POLL_INTERVAL | 1000ms | 轮询间隔 | | MODBUS_RTU_RESP_TIMEOUT | 500ms | 响应超时 | | MODBUS_RTU_INTER_CHAR_TIMEOUT | 10ms | 帧内字符间隔超时 | | MODBUS_RTU_TX_ECHO_MARGIN | 10ms | 发送回波屏蔽时间 |