Files
DLD154Pro/docs/rs485-modbus-protocol.md
T
wangfq 32cd45323b docs: Modbus 协议 V1.1 — 修正位宽+输出模式+融合模式
- CAPVD/Origin/Variation → 32-bit (各占2个寄存器)
- Output Mode 删除脉冲模式(单继电器仅存在输出)
- 新增 Fusion Mode (0x0001): direction_mode低4位, 0=仅地感 ~ 6=ETC
- direction_mode 字段重构: bit[7:4]=function_mode, bit[3:0]=fusion_mode
- Fusion Mode 仅在光耦配置为雷达输入时有效
2026-07-22 18:15:39 +08:00

279 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# DLD154Pro RS485 Modbus RTU 协议
> 版本: V1.1 | 日期: 2026-07-22 | 状态: 草案(待评审,未实现)
>
> 适用产品: DLD154Pro (CH591R, 单路线圈车检器)
>
> RS485 支持两种协议:700BS(后续定义)和 Modbus RTU。
> 协议选择通过 `g_function_mode` bit0 控制(BLE 小程序设置 `direction_mode` 高 4 位的 bit0)。
---
## 1. 物理层
| 参数 | 值 |
|------|-----|
| 接口 | RS485 半双工 (UART0) |
| 引脚 | PA14 TX, PA15 RX, PA13 RE (方向控制) |
| 波特率 | 9600 (默认), 19200, 38400, 57600, 115200 |
| 数据位 | 8 |
| 校验 | 无 (N) |
| 停止位 | 1 |
| 从机地址 | 1247 (默认 1) |
| 终端电阻 | 外接 120Ω(板载未集成) |
> **注意**RS485 地址和波特率通过 **BLE 小程序** 修改,不通过 Modbus 寄存器修改(防止改错后设备失联)。Modbus 只读方式可查询当前值。
---
## 2. 帧格式 (Modbus RTU)
```
| 地址 | 功能码 | 数据 | CRC16 |
| 1B | 1B | N B | 2B |
```
- **地址**:1–247,从机地址。0=广播(仅写操作),DLD154Pro 不响应广播。
- **CRC16**:多项式 `0xA001`,低字节在前。超时 3.5 字符作为帧间隔。
- **最大 PDU**:256 字节(含地址 + 功能码)。
### 异常响应
当请求无法处理时,功能码最高位置 1,数据区第一字节为异常码:
| 异常码 | 名称 | 说明 |
|--------|------|------|
| 0x01 | Illegal Function | 不支持的功能码 |
| 0x02 | Illegal Data Address | 寄存器地址超出范围 |
| 0x03 | Illegal Data Value | 写入值超出允许范围 |
| 0x04 | Slave Device Failure | 设备内部错误(如 flash 写入失败) |
---
## 3. 寄存器映射
### 3.1 离散输入 (Discrete Inputs) — 功能码 0x02
| 地址 | 名称 | 说明 | 位值 |
|------|------|------|------|
| 0x0000 | Car Present | 当前有车 | 0=无车, 1=有车 |
| 0x0001 | Loop Fault | 线圈故障(断开/短路) | 0=正常, 1=故障 |
| 0x0002 | Loop Stable | 线圈基线已稳定 | 0=收敛中, 1=稳定 |
| 0x0003 | Opto Input | 光耦输入状态 (PB10) | 0=低, 1=高 |
| 0x0004 | Power Up State | 上电初始化中 | 0=正常, 1=初始化 |
| 0x0005 | Relay Output | 继电器当前输出状态 | 0=释放, 1=吸合 |
### 3.2 输入寄存器 (Input Registers) — 功能码 0x04
| 地址 | 名称 | 类型 | 宽度 | 说明 |
|------|------|------|------|------|
| 0x0000 | Loop Freq Hi | uint16 | 2 寄存器 | 线圈振荡频率,高 16 位 (Hz) |
| 0x0001 | Loop Freq Lo | uint16 | | 线圈振荡频率,低 16 位 (Hz) |
| 0x0002 | CAPVD Hi | uint16 | **2 寄存器** | 归一化周期值 (32-bit),高 16 位 |
| 0x0003 | CAPVD Lo | uint16 | | 归一化周期值,低 16 位 |
| 0x0004 | Origin Hi | uint16 | **2 寄存器** | 基线值 (32-bit),高 16 位 |
| 0x0005 | Origin Lo | uint16 | | 基线值,低 16 位 |
| 0x0006 | Variation Hi | int16 | **2 寄存器** | 变化量 = CAPVD Origin (32-bit 有符号),高 16 位 |
| 0x0007 | Variation Lo | int16 | | 变化量,低 16 位 |
| 0x0008 | FW Version | uint16 | 1 寄存器 | 固件版本,高字节=主版本,低字节=子版本。例 `0x0300` = v3.00 |
| 0x0009 | HW Version | uint16 | 1 寄存器 | 硬件版本。例 `0x0301` = v3.01 |
| 0x000A | Freq Sens | uint16 | 1 寄存器 | 当前灵敏度等级 (0=低, 1=中, 2=高) |
| 0x000B | Condition | uint16 | 1 寄存器 | 环境活跃度 (0=安静, 1–100=嘈杂) |
> **32-bit 值换算**
> - 频率:`freq_hz = (reg[0x0000] << 16) | reg[0x0001]`,单位 Hz。典型空线圈 50120kHz。
> - CAPVD`capvd = (reg[0x0002] << 16) | reg[0x0003]`,归一化到 `MEASUREMENT_BASE = 131072`。
> - Origin`origin = (reg[0x0004] << 16) | reg[0x0005]`100 次滑动平均累加值。
> - Variation`var = (int32_t)((reg[0x0006] << 16) | reg[0x0007])`,正值=频率降低(可能有车),负值=频率升高。
### 3.3 保持寄存器 (Holding Registers) — 功能码 0x03 / 0x06 / 0x10
| 地址 | 名称 | 范围 | 默认 | R/W | 说明 |
|------|------|------|------|-----|------|
| 0x0000 | Sensitivity | 02 | 2 | R/W | 灵敏度等级 (0=低, 1=中, 2=高) |
| 0x0001 | Fusion Mode | 06 | 0 | R/W | 输出组合模式(见 §6.5) |
| 0x0002 | Hold Time | 0255 | 0 | R/W | 有限存在时间 (×5s), 0=永久存在 |
| 0x0003 | Output Delay | 0255 | 10 | R/W | 离开延时 (×50ms), 例 10=500ms |
| 0x0004 | Freq Level | 01 | 0 | R/W | 线圈频率档: 0=高频, 1=低频 |
| 0x0005 | RS485 Baud Hi | — | — | **R** | RS485 波特率高 16 位(只读) |
| 0x0006 | RS485 Baud Lo | — | — | **R** | RS485 波特率低 16 位(只读) |
| 0x0007 | RS485 Addr | 1247 | 1 | **R** | RS485 从机地址(只读) |
| 0x0008 | Protocol | 01 | 0 | **R** | 当前 RS485 协议: 0=700BS, 1=Modbus |
| 0x0009 | BT Timeout | 0255 | 0 | R/W | 蓝牙空闲关闭超时 (分钟), 0=不关闭 |
| 0x000A | Safe Timeout | 0255 | 0 | R/W | 安全模式超时 (×10s), 0=关闭 |
| 0x000B | Opto Func | 01 | 0 | **R** | 光耦功能: 0=雷达输入, 1=复位 |
> **只读寄存器 (0x00050x0008, 0x000B)**:写操作返回异常 0x02Illegal Data Address)。
> 这些参数只能通过 BLE 小程序修改。RS485 地址/波特率通过 Modbus 误改会立即失联。
---
## 4. 命令示例
### 4.1 读离散输入 — 功能码 0x02
读取车辆存在状态:
```
>>> 01 02 00 00 00 01 B9 F8 (从机1, 读地址0x0000, 1个)
<<< 01 02 01 01 61 8C (1字节数据=0x01, 有车)
```
### 4.2 读输入寄存器 — 功能码 0x04
读取频率 + CAPVD + Origin + Variation(共 8 个寄存器,16 字节):
```
>>> 01 04 00 00 00 08 70 1F (读 0x0000 起 8 个寄存器)
<<< 01 04 10
00 01 86 A0 ← Freq = 0x000186A0 = 100000 Hz
00 02 00 7C ← CAPVD = 0x0002007C = 131196
00 01 FF F3 ← Origin = 0x0001FFF3 = 131059
FF FF 00 99 ← Var = 0xFFFF0099 = 65383 (频率降低)
XX XX
```
### 4.3 读保持寄存器 — 功能码 0x03
读取全部可读写参数:
```
>>> 01 03 00 00 00 05 84 09 (读 5 个: 灵敏度/融合模式/存在时间/延时/频率档)
<<< 01 03 0A 00 02 00 00 00 00 00 0A 00 00 XX XX
→ 灵敏度=2(高), 融合模式=0(仅地感), 永久存在, 延时=500ms, 高频
```
### 4.4 写单个寄存器 — 功能码 0x06
修改灵敏度为"中"
```
>>> 01 06 00 00 00 01 49 F3 (写 0x0000=1)
<<< 01 06 00 00 00 01 49 F3
```
修改融合模式为"地感或雷达":
```
>>> 01 06 00 01 00 03 99 F5 (写 0x0001=3, 地感或雷达)
<<< 01 06 00 01 00 03 99 F5
```
### 4.5 批量写寄存器 — 功能码 0x10
一次写入灵敏度和存在时间(60s)
```
>>> 01 10 00 00 00 02 04 00 02 00 0C XX XX
地址 功能 起始 数量 字节 灵敏度=2 时间=12 CRC
<<< 01 10 00 00 00 02 40 31 (写入成功)
```
### 4.6 异常响应示例
写入超出范围的灵敏度值:
```
>>> 01 06 00 00 00 05 88 32 (写 0x0000=5, 超出 02)
<<< 01 86 03 02 63 (异常: 功能码 0x86, 异常码 0x03=Illegal Data Value)
```
---
## 5. 功能码支持矩阵
| 功能码 | 名称 | 支持 | 说明 |
|--------|------|------|------|
| 0x01 | Read Coils | ✗ | 不使用 |
| 0x02 | Read Discrete Inputs | ✓ | 车辆状态、故障、继电器、光耦 |
| 0x03 | Read Holding Registers | ✓ | 读所有配置参数 |
| 0x04 | Read Input Registers | ✓ | 读传感器数据 (32-bit 跨双寄存器) |
| 0x05 | Write Single Coil | ✗ | 不使用 |
| 0x06 | Write Single Register | ✓ | 写单个参数 |
| 0x0F | Write Multiple Coils | ✗ | 不使用 |
| 0x10 | Write Multiple Registers | ✓ | 批量写参数 |
| 0x11 | Report Slave ID | ✓ | 返回设备型号 + 运行状态 |
---
## 6. 设计说明
### 6.1 为什么 CAPVD/Origin/Variation 用 2 个寄存器?
DLD154V4B 算法移植后,`MEASUREMENT_BASE = 131072 (2^17)`IIR 滤波后的 CAPVD 和 Origin 是 `uint32_t` 类型,典型值在 10 万级,远超 16 位(65535)。Variation 是差值且可能为负,需要完整 32-bit 有符号表示。因此各占 2 个 Modbus 寄存器(寄存器对,大端序)。
### 6.2 为什么不通过 Modbus 修改 RS485 地址/波特率?
如果在 Modbus 通信中写入错误的地址或波特率,设备将**立即失联**且无法通过同一条总线恢复。
- 通过 **BLE 小程序** 修改 RS485 地址和波特率(带外管理通道)
- Modbus 侧只读查询当前值,防止误操作
### 6.3 参数持久化
- `0x06``0x10` 写入 Holding Register → 立即更新 RAM → 写入 DataFlash → 返回响应
- Flash 写入失败 → 返回异常码 `0x04` (Slave Device Failure)
- 值超出范围(如灵敏度写 5)→ 返回异常码 `0x03` (Illegal Data Value)
### 6.4 灵敏度与 ΔL/L 对应关系
| 灵敏度值 | SensTable 进入 | ΔL/L 进入 | SensTable1 离开 | ΔL/L 离开 |
|---------|---------------|-----------|----------------|-----------|
| 2 (高) | 28 | **0.085%** | 16 | 0.049% |
| 1 (中) | 54 | **0.165%** | 32 | 0.098% |
| 0 (低) | 108 | **0.330%** | 81 | 0.247% |
ΔL/L 越大越不灵敏。高灵敏度 (2) 适合安静环境,低灵敏度 (0) 适合强干扰环境。
### 6.5 输出组合模式 (Fusion Mode)
`direction_mode` 字段重构:
| 位段 | 名称 | 说明 |
|------|------|------|
| bit [7:4] | `function_mode` | 功能代码。bit0=RS485 协议选择(0=700BS, 1=Modbus), bit1=光耦功能(0=雷达输入, 1=复位) |
| bit [3:0] | `fusion_mode` | 输出组合模式 — **仅当光耦配置为"雷达输入"时有效** |
> DLD154Pro 为单路线圈、单刀双掷继电器,**仅支持存在输出**。继电器输出信号由线圈检测结果与雷达输入(光耦 PB10)按 `fusion_mode` 组合后驱动。
| 值 | 模式 | 继电器吸合条件 | 适用场景 |
|----|------|--------------|---------|
| 0 | 默认 (仅地感) | 线圈有车 | 纯线圈场景(光耦未接雷达时也用此模式) |
| 1 | 仅地感 | 线圈有车 | 同 0,显式指定忽略雷达 |
| 2 | 仅雷达 | 光耦输入有效(雷达有车) | 纯雷达,地感只做背景监控 |
| 3 | 地感 **或** 雷达 | 线圈 OR 雷达 | 互补冗余,任一触发即吸合 |
| 4 | 地感 **且** 雷达 | 线圈 AND 雷达 | 双确认,防地感误触(如行人/拖车) |
| 5 | 混行模式 | 待定义 | 混合交通流场景 |
| 6 | ETC 模式 | 待定义 | ETC 专用逻辑 |
> **注意**:当 `g_fm_radar_input_disable = 1`(光耦配置为复位功能)时,`fusion_mode` 无效,继电器仅由线圈检测结果驱动。
### 6.6 实现要点(待编码时参考)
```c
// RS485 方向控制 (PA13)
#define RS485_RE_TX() GPIOA_SetBits(GPIO_Pin_13) // 发送
#define RS485_RE_RX() GPIOA_ResetBits(GPIO_Pin_13) // 接收
// 32-bit 值拆分为 2 个 Modbus 寄存器(大端序)
// CAPVD = 131196 → reg[0]=0x0002, reg[1]=0x007C
reg[0] = (uint16_t)(capvd >> 16);
reg[1] = (uint16_t)(capvd & 0xFFFF);
// CRC16 查表法:poly=0xA001, init=0xFFFF
// 帧间隔: t3.5 = 3.5 × 11 / baud (秒)
// @9600 = 4.0ms
// @19200 = 2.0ms
```
RS485 半双工时序:发送最后一字节后等待 **1 字节时间** 再切换 RE 为接收,
避免 RE 过早翻转导致最后一个字节被截断。
---
## 7. 版本历史
| 版本 | 日期 | 作者 | 变更 |
|------|------|------|------|
| V1.1 | 2026-07-22 | wangfq | 修正: CAPVD/Origin/Variation 扩展为 32-bit (×2 寄存器); Output Mode 删除脉冲模式(仅存在输出); 新增 Fusion Mode(输出组合模式 0-6); direction_mode 字段重构说明 |
| V1.0 | 2026-07-22 | wangfq | 初版草案 |