Files
DLD154Pro/docs/rs485-modbus-protocol.md
T
wangfq 692b406d0f docs(DLD154Pro): RS485 协议未实现标注 (rs485-modbus V1.8 / 700BS) + V3.05 文档同步
原则:代码未实现的功能,协议文档在相应指令旁如实标注"未实现",避免文档承诺≠固件实现。

- rs485-modbus-protocol.md V1.7→V1.8:
  §3.1 DI 0x0008 Init Flag 未实现(恒 0);§3.2 IR 0x0006/0x0007(Variation)/
  0x000A/0x000B/0x000C 未实现(改读全数据块 0x010A/0x010B);§3.3 保持寄存器
  全部标注(FC 0x06 仅 0x0010/0x0011/0x0012 可写,0x00FE 无分支);
  §4.3/4.5/4.8 未实现横幅;§5 功能码矩阵 0x03/0x10/0x11 → ✗;
  §6.3 仅 0x06;§7 0x3D/Init_B 对照标注;§8 版本历史 V1.8
- rs485-700bs-protocol.md: §4.4 0x3D 未实现注记 + §5 速查表 + §6 兼容对照
- ble-protocol.md / product-manual.md / technical-spec.md: 版本 V3.04→V3.05 + 版本历史
- devlog.md: 置顶 2026-08-27 条目(减配清单 + 文档标注 + 保留能力 + 宏修复)
2026-08-27 08:55:20 +08:00

496 lines
27 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.7 | 日期: 2026-07-31 | 状态: 已实现
>
> 适用产品: 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 (700BS 默认), **115200 (Modbus 默认, 推荐)** |
| 数据位 | 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=吸合 |
| 0x0006 | Freq Low Fault | 频率下限异常 (Fre_Err bit0) | 0=正常, 1=频率过低 |
| 0x0007 | Freq High Fault | 频率上限异常 (Fre_Err bit4) | 0=正常, 1=频率过高 |
| 0x0008 | Init Flag | 复位后首次指示 (Init_B) | 0=正常, 1=复位后首次—上位机读后清零* | ⚠ **未实现**(固件恒为 0 |
> **Init Flag 清除机制**:上位机读到 1 后,应发送 **写 HR 0x00FE=0x0001** 清零。参见 §4.7。
> ⚠ **实现状态(V1.8 起标注)**`DI 0x0008` 与 `HR 0x00FE` 固件均**未实现**(DI 恒为 0,HR 无处理分支),此机制仅文档保留。
### 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 位 | ⚠ **未实现**(省 Flash 减配,V1.8 |
| 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=中高, 3=高) | ⚠ **未实现**(省 Flash 减配,V1.8 |
| 0x000B | Condition | uint16 | 1 寄存器 | 环境活跃度 (0=安静, 1–100=嘈杂) | ⚠ **未实现**(省 Flash 减配,V1.8 |
| 0x000C | DIP Virtual | uint16 | 1 寄存器 | 虚拟拨码(700BS 兼容): bit[7:4]=function_mode, bit[3:0]=fusion_mode | ⚠ **未实现**(省 Flash 减配,V1.8 |
> ⚠ **输入寄存器实现状态(V1.8 起标注)**`0x0006/0x0007`Variation)、`0x000A`Freq Sens)、`0x000B`Condition)、`0x000C`DIP Virtual)固件**未实现**(读返回异常 0x02 Illegal Data Address)。读取变化量请用全数据块 `0x010A/0x010B`(见 §3.2.1,仍可用)。
### 3.2.1 全数据块 (Input Registers 0x0100+) — 功能码 0x04
> 可供主动上报和单次查询使用。一次读取 19 个寄存器获取设备完整快照。
| 地址 | 名称 | 类型 | 宽度 | 说明 |
|------|------|------|------|------|
| 0x0100 | Sensitivity | uint16 | 1 | 灵敏度等级 (0=低, 1=中低, 2=中高, 3=高) |
| 0x0101 | Freq Level | uint16 | 1 | 频率档位 (0=高频, 1=低频) |
| 0x0102 | Fusion Mode | uint16 | 1 | 输出融合模式 (0=或, 1=混行, 2=ETC, 3=且, 4=仅地感, 5=仅光耦, 6=复位) |
| 0x0103 | Car State | uint16 | 1 | 有车状态 (0=无车, 1=有车) |
| 0x0104 | Loop Status | uint16 | 1 | bit0=线圈断开(1=故障), bit1=基线稳定(1=就绪) |
| 0x0105 | Opto Status | uint16 | 1 | 光耦输入状态 (0=无效/高电平, 1=有效/低电平) |
| 0x0106 | Loop Freq Hi | uint16 | **2** | 线圈振荡频率 (Hz),高 16 位 |
| 0x0107 | Loop Freq Lo | uint16 | | 线圈振荡频率,低 16 位 |
| 0x0108 | CAPVD Hi | uint16 | **2** | 归一化周期值 (32-bit),高 16 位 |
| 0x0109 | CAPVD Lo | uint16 | | 归一化周期值,低 16 位 |
| 0x010A | Variation Hi | int16 | **2** | 变化量 = CAPVD Origin (32-bit 有符号),高 16 位 |
| 0x010B | Variation Lo | int16 | | 变化量,低 16 位 |
| 0x010C | Cut Cnt Hi | uint16 | **2** | 线圈断开累计次数 (32-bit, 上电清零),高 16 位 |
| 0x010D | Cut Cnt Lo | uint16 | | 线圈断开累计次数,低 16 位 |
| 0x010E | Relay Cnt Hi | uint16 | **2** | 继电器吸合累计次数 (32-bit, 上电清零),高 16 位 |
| 0x010F | Relay Cnt Lo | uint16 | | 继电器吸合累计次数,低 16 位 |
| 0x0110 | Time Type | uint16 | 1 | 时间值类型: 0=车间距(间隙), 1=通过时间; 无有效值时 0xFFFF |
| 0x0111 | Misc Time Hi | uint16 | **2** | 时间值 (10ms 单位, 32-bit),高 16 位 |
| 0x0112 | Misc Time Lo | uint16 | | 时间值,低 16 位 |
> **时间类型说明**
> - **车间距 (Time Type=0)**:从上次继电器释放到本次继电器吸合的时间。当 `car_state` 从 0→1(上升沿)时更新。
> - **通过时间 (Time Type=1)**:从继电器吸合到继电器释放的时间。当 `car_state` 从 1→0(下降沿)时更新。
> - 上述两个值写入同一对寄存器 (0x01110x0112)`Time Type` 指示当前存储的是哪种。
> **32-bit 计数器回绕**`Cut Cnt` 和 `Relay Cnt` 为 32-bit 无符号整数,最大值 4,294,967,295,上电清零。日常使用不会溢出。
> **32-bit 值换算**
> - 频率:`freq_hz = (reg[0x0000] << 16) | reg[0x0001]`,单位 Hz。典型空线圈 50120kHz。
> - CAPVD`capvd = (reg[0x0002] << 16) | reg[0x0003]`,归一化到 `MEASUREMENT_BASE = 524288`。
> - Origin`origin = (reg[0x0004] << 16) | reg[0x0005]`500 窗滑动平均累加值。
> - Variation`var = (int32_t)((reg[0x0006] << 16) | reg[0x0007])`,正值=频率降低(可能有车),负值=频率升高。
### 3.3 保持寄存器 (Holding Registers) — 功能码 0x03 / 0x06 / 0x10
> ⚠ **实现状态(V1.8 起标注)**:功能码 **0x03(读保持寄存器)与 0x10(批量写)固件未实现**(返回异常 0x01 Illegal Function)。保持寄存器**只支持 FC 0x06 写单寄存器**,且仅 `0x0010/0x0011/0x0012` 可写;其余 R/W 寄存器(0x00000x0004, 0x0009, 0x000A)因省 Flash 减配**读写均未实现**,只读寄存器(0x00050x0008, 0x000B)因 FC 0x03 未实现**读不到**。
| 地址 | 名称 | 范围 | 默认 | R/W | 说明 |
|------|------|------|------|-----|------|
| 0x0000 | Sensitivity | 03 | 1 | R/W | 灵敏度等级 (0=低, 1=中低, 2=中高, 3=高) | ⚠ **未实现**(省 Flash 减配,V1.8 |
| 0x0001 | Fusion Mode | 06 | 0 | R/W | 输出组合模式(见 §6.5) | ⚠ **未实现**(省 Flash 减配,V1.8 |
| 0x0002 | Hold Time | 0255 | 0 | R/W | 有限存在时间 (×5s), 0=永久存在 | ⚠ **未实现**(省 Flash 减配,V1.8 |
| 0x0003 | Output Delay | 0255 | 10 | R/W | 离开延时 (×50ms), 例 10=500ms | ⚠ **未实现**(省 Flash 减配,V1.8 |
| 0x0004 | Freq Level | 01 | 0 | R/W | 线圈频率档: 0=高频, 1=低频 | ⚠ **未实现**(省 Flash 减配,V1.8 |
| 0x0005 | RS485 Baud Hi | — | — | **R** | RS485 波特率高 16 位(只读) | ⚠ FC 0x03 未实现,读不到 |
| 0x0006 | RS485 Baud Lo | — | — | **R** | RS485 波特率低 16 位(只读) | ⚠ FC 0x03 未实现,读不到 |
| 0x0007 | RS485 Addr | 1247 | 1 | **R** | RS485 从机地址(只读) | ⚠ FC 0x03 未实现,读不到 |
| 0x0008 | Protocol | 01 | 0 | **R** | 当前 RS485 协议: 0=700BS, 1=Modbus | ⚠ FC 0x03 未实现,读不到 |
| 0x0009 | BT Timeout | 0255 | 0 | R/W | 蓝牙空闲关闭超时 (分钟), 0=不关闭 | ⚠ **未实现**(省 Flash 减配,V1.8 |
| 0x000A | Safe Timeout | 0255 | 0 | R/W | 安全模式超时 (×10s), 0=关闭 | ⚠ **未实现**(省 Flash 减配,V1.8 |
| 0x000B | Opto Func | 01 | 0 | **R** | 光耦功能: 0=雷达输入, 1=复位 | ⚠ FC 0x03 未实现,读不到 |
| 0x0010 | Auto Rpt Enable | 01 | 0 | R/W | 全数据主动上报: 0=关闭, 1=使能(见 §4.9 | ✅ FC 0x06 可写 |
| 0x0011 | Active Thr | 065535 | 10 | R/W | 活动状态阈值: \|Variation\| ≥ 该值时进入活动上报速率 (150ms) | ✅ FC 0x06 可写 |
| 0x0012 | System Cmd | — | — | **W** | 系统指令: 写 `0x2C2C` 触发 MCU 全复位 (等效 700BS 0x2C, 见 §4.7);读恒 0 | ✅ FC 0x06 可写 |
| 0x00FE | Init Flag Clear | 01 | — | **W** | 写 1 清零 Init Flag (DI 0x0008) | ⚠ **未实现**(固件无此分支) |
| 0x00FF | Device Reset (已废弃) | — | — | **W** | ⚠ V1.7 废弃, 请使用 HR 0x0012=0x2C2C | ⚠ 废弃(未实现) |
> **只读寄存器 (0x00050x0008, 0x000B)**:写操作返回异常 0x02Illegal Data Address)。
> **写入寄存器 (0x00FE, 0x00FF)**:只写不读。读返回 0x0000。写入非魔数值返回异常 0x03。
---
## 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 38 80 ← Freq = 0x00013880 = 80000 Hz
00 07 FF C8 ← CAPVD = 0x0007FFC8 = 524200
00 08 00 00 ← Origin = 0x00080000 = 524288
FF FF FF A8 ← Var = 0xFFFFFFA8 = 88 (频率升高,有车)
XX XX
```
### 4.3 读保持寄存器 — 功能码 0x03
> ⚠ **V1.8 未实现**:固件已禁用 FC 0x03(省 Flash 减配),请求返回异常 `0x83 0x01`Illegal Function)。保持寄存器只支持 FC 0x06 写(仅 0x0010/0x0011/0x0012),请勿依赖此功能码读取参数。
读取全部可读写参数:
```
>>> 01 03 00 00 00 05 84 09 (读 5 个: 灵敏度/融合模式/存在时间/延时/频率档)
<<< 01 03 0A 00 01 00 00 00 00 00 0A 00 00 XX XX
→ 灵敏度=1(中), 融合模式=0(地感或光耦), 永久存在, 延时=500ms, 高频
```
### 4.4 写单个寄存器 — 功能码 0x06
修改灵敏度为"高"
```
>>> 01 06 00 00 00 02 88 32 (写 0x0000=2)
<<< 01 06 00 00 00 02 88 32
```
修改融合模式为"地感或光耦":
```
>>> 01 06 00 01 00 00 D9 F6 (写 0x0001=0, 地感或光耦)
<<< 01 06 00 01 00 00 D9 F6
```
### 4.5 批量写寄存器 — 功能码 0x10
> ⚠ **V1.8 未实现**:固件已禁用 FC 0x10(省 Flash 减配),请求返回异常 `0x90 0x01`Illegal Function)。批量写请改用 FC 0x06 逐条写,或走 BLE 小程序配置。
一次写入灵敏度和存在时间(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, 超出 03)
<<< 01 86 03 02 63 (异常: 功能码 0x86, 异常码 0x03=Illegal Data Value)
```
### 4.7 触发设备复位 — 写 HR 0x0012
```
>>> 01 06 00 12 2C 2C xx xx (写 0x0012=0x2C2C, 触发 MCU 全复位)
<<< 01 06 00 12 2C 2C xx xx (回显, 随后设备复位)
```
> 复位后 MCU 完全重启,重新初始化线圈基线,Init Flag (DI 0x0008) 置 1。
> 对齐 700BS 0x2C 命令行为:直接调用 `SYS_ResetExecute()`。
### 4.8 清除 Init Flag — 写 HR 0x00FE
> ⚠ **V1.8 未实现**:固件无 HR 0x00FE 处理分支(且 DI 0x0008 Init Flag 恒为 0),此命令无实际效果,仅文档保留。
```
>>> 01 06 00 FE 00 01 xx xx (写 0x00FE=1)
<<< 01 06 00 FE 00 01 xx xx (Init Flag → 0)
```
### 4.9 全数据块查询 — 读 IR 0x0100 起 19 个寄存器
一次读取设备完整快照(灵敏度/频率档/融合模式/车辆状态/光耦/频率/CAPVD/Variation/断开次数/继电器次数/时间):
```
>>> 01 04 01 00 00 13 B1 FA (从机1, 读 0x0100, 19 个寄存器)
<<< 01 04 26
00 01 ← Sensitivity = 1 (中低)
00 00 ← Freq Level = 0 (高频)
00 04 ← Fusion Mode = 4 (仅地感)
00 01 ← Car State = 1 (有车)
00 02 ← Loop Status = 0x0002 (bit1: 基线稳定)
00 00 ← Opto Status = 0 (光耦无效)
00 01 38 80 ← Freq = 80000 Hz
00 07 FF C8 ← CAPVD = 524200
00 00 00 58 ← Variation = +88 (频率降低, 有车)
00 00 00 03 ← Cut Cnt = 3 (累计断开 3 次)
00 00 00 7B ← Relay Cnt = 123 (累计吸合 123 次)
00 01 ← Time Type = 1 (通过时间)
00 00 03 84 ← Misc Time = 900 (900×10ms = 9s)
XX XX
```
> 解析:灵敏度中低,高频档,仅地感模式,当前有车且基线稳定,频率 80kHz,CAPVD=524200,变化量 +88,断开过 3 次线圈,继电器已动作 123 次,最近一次通过时间 9 秒。
### 4.10 使能/关闭主动上报 — 写 HR 0x0010
```
>>> 01 06 00 10 00 01 C8 1B (写 0x0010=1, 使能主动上报)
<<< 01 06 00 10 00 01 C8 1B
```
关闭:
```
>>> 01 06 00 10 00 00 88 1A (写 0x0010=0, 关闭)
<<< 01 06 00 10 00 00 88 1A
```
### 4.11 设置活动阈值 — 写 HR 0x0011
```
>>> 01 06 00 11 00 14 59 D9 (写 0x0011=20, |Variation|≥20 → 活动上报)
<<< 01 06 00 11 00 14 59 D9
```
### 4.12 主动上报帧格式
`Auto Rpt Enable=1` 时,设备自发发送全数据块。帧格式与 §4.9 的响应完全一致:
```
<addr> 04 26 <38 bytes data, same as 0x0100-0x0112 big-endian> <crc>
```
主机接收时无需区分——无论是轮询响应还是主动推送,数据格式和寄存器映射完全相同。
---
## 5. 功能码支持矩阵
| 功能码 | 名称 | 支持 | 说明 |
|--------|------|------|------|
| 0x01 | Read Coils | ✗ | 不使用 |
| 0x02 | Read Discrete Inputs | ✓ | 车辆状态、故障、继电器、光耦 |
| 0x03 | Read Holding Registers | ✗ | ⚠ **V1.8 未实现**(省 Flash 减配,返回异常 0x01 |
| 0x04 | Read Input Registers | ✓ | 读传感器数据 (32-bit 跨双寄存器);⚠ 0x0006/0x0007/0x000A/0x000B/0x000C 未实现,用 0x0100+ 全数据块 |
| 0x05 | Write Single Coil | ✗ | 不使用 |
| 0x06 | Write Single Register | ✓ | 写单个参数;⚠ 仅 0x0010/0x0011/0x0012 有效(V1.8 减配) |
| 0x0F | Write Multiple Coils | ✗ | 不使用 |
| 0x10 | Write Multiple Registers | ✗ | ⚠ **V1.8 未实现**(省 Flash 减配,返回异常 0x01 |
| 0x11 | Report Slave ID | ✗ | ⚠ **V1.8 未实现**(省 Flash 减配,返回异常 0x01 |
| N/A | **Active Push** | ✓ | 主动上报全数据块(格式同 FC 0x04 响应),需 HR 0x0010=1 使能 |
> **主动上报**:非标准 Modbus 功能。设备在 `Auto Rpt Enable=1` 时根据变化量阈值自动调速发送数据帧,帧格式与 FC 0x04 读 0x0100 起 19 个寄存器的响应一致。总线上的其他从机在上报期间保持静默,主机需在接收逻辑中处理非请求响应。
---
## 6. 设计说明
### 6.1 为什么 CAPVD/Origin/Variation 用 2 个寄存器?
DLD154Pro 算法移植后,`MEASUREMENT_BASE = 524288 (2^19)`CH591R@60MHz 无内部分频,需要比 DLD154V4B 更大的 BASE)。IIR 滤波后的 CAPVD 和 Origin 是 `uint32_t` 类型,典型值在 50 万级,远超 16 位(65535)。Variation 是差值且可能为负,需要完整 32-bit 有符号表示。因此各占 2 个 Modbus 寄存器(寄存器对,大端序)。
### 6.2 为什么不通过 Modbus 修改 RS485 地址/波特率?
如果在 Modbus 通信中写入错误的地址或波特率,设备将**立即失联**且无法通过同一条总线恢复。
- 通过 **BLE 小程序** 修改 RS485 地址和波特率(带外管理通道)
- Modbus 侧只读查询当前值,防止误操作
### 6.3 参数持久化
- `0x06`(或 `0x10`,⚠ V1.8 起 0x10 未实现)写入 Holding Register → 立即更新 RAM → 写入 DataFlash → 返回响应
- Flash 写入失败 → 返回异常码 `0x04` (Slave Device Failure)
- 值超出范围(如灵敏度写 5)→ 返回异常码 `0x03` (Illegal Data Value)
-**V1.8 减配**:写寄存器仅剩 `0x0010`(主动上报使能)/`0x0011`(活动阈值)/`0x0012`(复位)三条有效;灵敏度/融合模式等配置请走 BLE 小程序
### 6.4 灵敏度与 ΔL/L 对应关系
| 灵敏度值 | SensTable 进入 | ΔL/L 进入 | SensTable1 离开 | ΔL/L 离开 |
|---------|---------------|-----------|----------------|-----------|
| 3 (高) | 14 | **0.043%** | 12 | 0.037% |
| 2 (中高) | 28 | **0.085%** | 16 | 0.049% |
| 1 (中低) | 54 | **0.165%** | 32 | 0.098% |
| 0 (低) | 108 | **0.330%** | 81 | 0.247% |
ΔL/L 越大越不灵敏。高灵敏度 (3) 适合摩托车/安静环境,低灵敏度 (0) 适合强干扰环境。
> ⚠ 第 3 档 (sens=14) 信噪比余量仅约 2:120°C 温漂 ≈0.1% 感量偏移),仅推荐摩托车/小型车辆检测场景,需确保线圈安装质量。
### 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 | 地感 **或** 光耦 | 线圈 OR 雷达 | 互补冗余,任一触发即吸合 |
| 1 | 人车混行防砸 | 有车后 coil OR opto,离场 3s 窗口内光耦有效 | 混合交通流防砸人 |
| 2 | ETC 模式 | 有车后 coil OR opto,光耦断开 500ms 防抖才释放 | ETC 专用逻辑 |
| 3 | 地感 **且** 光耦 | 线圈 AND 雷达 | 双确认,防地感误触(如行人/拖车) |
| 4 | 仅地感 | 线圈有车 | 纯线圈场景(默认,未接光耦时也用此模式) |
| 5 | 仅光耦 | 光耦输入有效(雷达有车) | 纯雷达,地感只做背景监控 |
| 6 | 光耦复位 | 线圈有车(光耦用于远程复位) | 需要远程复位功能 |
**模式 1(人车混行防砸)状态机**:IDLE(仅线圈检测)→ 线圈有车 → ARMED(线圈||光耦)→ 两者均释放 → WINDOW(3s 防砸窗口,光耦触发即续吸,连续进入持续防砸)→ 3s 超时 → IDLE。
**模式 2ETC)状态机**:IDLE(仅线圈检测)→ 线圈有车 → ARMED(线圈||光耦)→ 两者均释放 → DEBOUNCE(500ms 防抖,期间触发即回 ARMED)→ 超时 → IDLE。
> **注意**:当光耦配置为复位功能(`function_mode` bit1=1)时,`fusion_mode` 无效,继电器仅由线圈检测结果驱动。模式 6 下光耦输入低电平 ≥400ms 后上升沿触发 `SYS_ResetExecute()` 芯片全复位。
### 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 过早翻转导致最后一个字节被截断。
### 6.7 主动上报机制
#### 使能条件
`Auto Rpt Enable` (HR 0x0010) = 1 时,设备自动按速率调度发送全数据块(§3.2.1 的 0x01000x0112)。默认关闭(0)。
#### 上报速率
| 状态 | 条件 | 上报间隔 | 说明 |
|------|------|---------|------|
| **事件** | 继电器状态翻转(吸合↔释放) | **立即** | 最高优先级,不等待间隔 |
| **活动** | \|Variation\| ≥ Active Thr (HR 0x0011) | **150ms** | 车辆进出或干扰期间快速跟踪 |
| **空闲** | \|Variation\| < Active Thr | **800ms** | 无车或稳定时的慢速心跳 |
#### 速率切换
设备在每个上报间隔结束时评估当前状态,决定下一个间隔:
- 继电器翻转事件 → 立即发送,重置计时器 → 按变化量重新判断进入活动/空闲间隔
- 活动态连续 \|Variation\| < 阈值满 2 个间隔 → 降速到空闲 800ms
- 空闲态一旦 \|Variation\| ≥ 阈值 → 立即升速到活动 150ms
#### 车间距 / 通过时间测量
设备内部跟踪两个 tick 计数器(10ms 单位):
```
last_relay_off_tick — 上次继电器释放的时刻
last_relay_on_tick — 上次继电器吸合的时刻
```
- 继电器吸合沿 → `Misc Time = now last_relay_off_tick`, `Time Type = 0`(车间距)
- 继电器释放沿 → `Misc Time = now last_relay_on_tick`, `Time Type = 1`(通过时间)
- 上电后首次事件前,`Time Type = 0xFFFF``Misc Time = 0`
**注意**:车间距/通过时间写入全数据块的 0x0110–0x0112,主动上报或轮询时一并读出。
#### 总线仲裁
主动上报期间,设备在发送数据前监听总线(检测 RX 是否有数据),仅在总线空闲时发送。若与主机轮询冲突(极低概率,因为主机需准备接收),以主机轮询优先——设备检测到冲突后推迟上报至下一个间隔。
#### 与 700BS 主动上报的对照
| 特性 | 700BS 主动上报 | Modbus 主动上报 (本扩展) |
|------|---------------|------------------------|
| 心跳间隔 | 5s 空闲 / 1s 故障 / 事件立即 | 800ms 空闲 / 150ms 活动 / 事件立即 |
| 触发条件 | 固定时间 + 故障状态 | 变化量阈值动态调速 |
| 数据格式 | 0xAA 自定义帧 | FC 0x04 响应格式 (与轮询一致) |
| 主机兼容 | 700BS 主机原生支持 | 需 Modbus 主机适配非请求响应 |
---
## 7. 700BS 协议兼容对照
DLD154Pro RS485 同时支持 700BS 协议(`g_fm_700bs_disable=0`)和 Modbus RTU`g_fm_700bs_disable=1`)。
协议选择通过 BLE 小程序切换。参见 `docs/rs485-700bs-protocol.md`
| 700BS 命令 | 700BS 字段 | Modbus 等价 | 说明 |
|-----------|-----------|------------|------|
| 0xFA 查询状态 | bit7=有车 | DI 0x0000 Car Present | ✅ |
| | bit5=线圈故障 | DI 0x0001 Loop Fault | ✅ |
| 0x1B 查询频率 | 3 字节 Freq | IR 0x000001 Freq (32bit) | ✅ |
| 0x2C 复位 | — | **HR 0x0012** 写 0x2C2C | ✅ V1.7: MCU 全复位 (SYS_ResetExecute)
| 0x3D 查拨码 | DIP1-5 | **IR 0x000C DIP Virtual** | ⚠ V1.8 起未实现(IR 0x000C 减配,读返回异常 0x02 |
| 0xAA 心跳 Init_B | A1=首次 | **DI 0x0008 Init Flag** | ⚠ V1.8 标注:固件恒为 0(未实现) |
| 0xAA 心跳 Fre_Err | bit0=下限异常 | **DI 0x0006 Freq Low Fault** | ✅ V1.2 新增 |
| | bit4=上限异常 | **DI 0x0007 Freq High Fault** | ✅ V1.2 新增 |
| 0xAA 心跳 主动上报 | 5s/1s/事件 | — | ✅ V1.6: Modbus 新增主动上报 (FC 0x04 响应格式, 800ms/150ms/事件立即) |
> **主动上报限制**:Modbus RTU 为严格主从协议,从机不能主动发送数据。
> V1.6 起通过私有扩展实现主动上报(需 `Auto Rpt Enable=1`),帧格式与 FC 0x04 响应一致。
> 主机需适配非请求响应的接收逻辑。关闭主动上报后,仍可通过轮询 DI+IR 等价获取状态。
---
## 8. 版本历史
| 版本 | 日期 | 作者 | 变更 |
|------|------|------|------|
| V1.8 | 2026-08-27 | wangfq | **省 Flash 减配(实现状态如实标注)**FC 0x03(读保持寄存器)/0x10(批量写)/0x11Report Slave ID)未实现;IR 0x0006/0x0007Variation/0x000AFreq Sens/0x000BCondition/0x000CDIP Virtual)未实现(改读全数据块 0x010A/0x010B);HR 0x00000x0004/0x0009/0x000A 读写未实现(灵敏度等配置走 BLE);FC 0x06 仅剩 0x0010/0x0011/0x0012 可写;DI 0x0008 Init Flag 与 HR 0x00FE 标注未实现(固件恒 0/无分支) |
| V1.7 | 2026-07-31 | wangfq | 复位指令重构: HR 0x00FF 废弃, 新增 HR 0x0012 (System Cmd); 写 0x2C2C 触发 `SYS_ResetExecute()` MCU 全复位 (对齐 700BS 0x2C 行为); 0x2C2C 对应 700BS CMD_RESET_INIT 的 0x2C; +§4.7 示例更新 |
| V1.6 | 2026-07-30 | wangfq | 新增主动上报 & 全数据块: +IR 0x01000x0112 全数据块(19 reg, 含灵敏度/频率/融合模式/car_state/线圈/光耦/频率/CAPVD/Variation/断开计数/继电器计数/通过时间); +HR 0x0010 上报使能, +HR 0x0011 活动阈值; +§4.94.12 命令示例; +§6.7 主动上报机制(3 级速率: 空闲800ms/活动150ms/事件立即); 车间距/通过时间(10ms单位); 700BS 对照表更新 |
| V1.5 | 2026-07-30 | wangfq | 枚举再次重排: 且后移 (0=或,1=混行,2=ETC,3=且,4=仅地感,5=仅光耦,6=复位); 模式号引用同步更新 |
| V1.4 | 2026-07-29 | wangfq | 枚举重排: 融合模式值重新分配 (0=或,1=且,2=混行,3=ETC,4=仅地感,5=仅光耦,6=复位); 默认融合模式 0→4(仅地感); 修正所有示例和说明文本 |
| V1.3 | 2026-07-29 | wangfq | 修正: 灵敏度档位 3→4 (范围 03, 默认 1); MEASUREMENT_BASE 131072→524288; Origin 窗口 100→500; 融合模式 5/6 待定义→已实现+状态机; 命令示例数值对齐实际硬件; 700BS 标注为已完成; 版本号 FW 3.00→3.01 |
| V1.2 | 2026-07-22 | wangfq | 700BS 兼容: +DI Freq Low/High Fault, +DI Init Flag, +IR DIP Virtual, +HR Device Reset(0x00FF), +HR Init Flag Clear(0x00FE); +§7 700BS 兼容对照表 |
| 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 | 初版草案 |