原则:代码未实现的功能,协议文档在相应指令旁如实标注"未实现",避免文档承诺≠固件实现。 - 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 条目(减配清单 + 文档标注 + 保留能力 + 宏修复)
32 KiB
DLD154Pro 开发日志
MCU: CH591R (RISC-V, BLE) @60MHz | 线圈通道: 1路 | 调试口: RS485 / BLE
2026-08-27 — RS485 协议省 Flash 减配(文档如实标注未实现,V3.05 固件 + 协议 V1.8)
背景
本地调整 RS485 侧代码减少 Flash 占用:注释掉一批低频/非核心协议分支与调试打印。原则:代码未实现的功能,协议文档在相应指令旁如实标注"未实现",避免文档承诺 ≠ 固件实现。
固件改动(本地,未提交)
| 文件 | 改动 |
|---|---|
APP/include/cmcng.h |
版本 V3.04 → V3.05(FIRMWARE_VER 字符串 + SUB 宏同步) |
APP/rs485_modbus.c |
FC 0x03(读保持寄存器)/0x10(批量写)/0x11(Report Slave ID)分发注释;IR 0x0006/0x0007(Variation)/0x000A(Freq Sens)/0x000B(Condition)/0x000C(DIP Virtual)注释;HR 0x0000–0x0004/0x0009/0x000A 写 case 注释(FC 0x06 仅剩 0x0010/0x0011/0x0012) |
APP/include/rs485_modbus.h |
MB_MAX_READ_REGS 125→60→40、MB_MAX_DATA_BYTES 250→80(40×2=80 匹配,原 60 会越界 40B,同日修正) |
APP/rs485_700bs.c |
0x3D DIP 查询分支注释 + 4 处调试 PRINT 注释 |
APP/peripheral_main.c |
BREATH_OPTO_DUTY_STEP 32→64(注释"~0.5s 周期"未同步,实际 2 步≈0.25s) |
APP/peripheral.c |
OTA 跳转前 mDelaymS(5) 注释 |
文档同步(本次落地)
| 文件 | 标注 |
|---|---|
docs/rs485-modbus-protocol.md V1.7→V1.8 |
§3.1 DI 0x0008 Init Flag 未实现(恒 0);§3.2 IR 0x0006/0x0007/0x000A/0x000B/0x000C 未实现(Variation 改读全数据块 0x010A/0x010B);§3.3 HR 全部标注(FC 0x06 仅 0x0010/0x0011/0x0012 可写);§4.3/4.5/4.8 未实现横幅;§5 功能码矩阵 0x03/0x10/0x11 → ✗;§6.3 仅 0x06;§7 0x3D/Init_B 对照标注;§8 版本历史 V1.8 |
docs/rs485-700bs-protocol.md |
§4.4 0x3D 未实现注记(V3.05 起减配不响应);§5 速查表 + §6 兼容对照同步 |
保留能力(减配后仍可用)
- FC 0x02 读离散输入(车辆/故障/继电器/光耦)✅
- FC 0x04 读输入寄存器 + 全数据块 0x0100–0x0112(含 Variation 0x010A/0x010B)✅
- FC 0x06 写:0x0010 主动上报使能 / 0x0011 活动阈值 / 0x0012 复位(0x2C2C)✅
- 700BS 0xFA / 0x1B / 0x2C / 0xAA 心跳 ✅
⚠ 遗留提醒
宏越界:✅ 已修(同日):MB_MAX_READ_REGS=60但MB_MAX_DATA_BYTES=80→ 主机查 60 寄存器时data_buf越界 40B。MB_MAX_READ_REGS 60→40,40 寄存器 × 2B = 80B 缓冲匹配;全数据块 19 寄存器不受影响- 协议文档 V1.8 已标注;
DLD154ToolGUI 若暴露 FC 0x03/0x10/0x11 按钮需同步禁用(三层一致性)
2026-08-26 — V3.04:0x24 追加 LOOP_MEASURE_BASE 归一化基数(与 DLD110S 对齐)
背景
DLD110S 2026-08-26 实测发现小程序评估把 variation 归一化基数写错(照搬 DLD154V4B 的 131072,DLD110S/154Pro 实为 524288 2^19 @60MHz)→ 所有百分比放大 4 倍。根治方案:固件 0x24 显式上报基数。DLD110S 已完成(协议 V1.1),DLD154Pro 同步对齐。
改动
| 文件 | 改动 |
|---|---|
APP/include/cmcng.h |
版本 V3.03→V3.04;新增 #define LOOP_MEASURE_BASE 524288L |
APP/dbn_ble_srv.c |
0x24 读参响应尾部追加 3B LE:LOOP_MEASURE_BASE(响应 8B→11B,仍单包 ≤14B,无分包) |
docs/ble-protocol.md |
§5.4 响应表加偏移 8-10 + 换算公式 + 背景说明 |
docs/product-manual.md |
版本号 V3.04 + 版本历史 |
docs/technical-spec.md |
版本号 V3.04 + 版本历史 |
对照 110S 差异结论(不需要改的部分)
- 断开次数双变量:154Pro 不需要——LED 快闪不依赖 cut_amount 次数(走
g_disconnect_active),g_loop_cut_amount本身就是上电持续累计,无 3 次上限 - 0x24 偏移 7 direction_mode:154Pro 已经是完整字节(dbn_ble_srv.c:637),与 110S V4.31 语义一致
- 重连 g_loop_cut_last = 0:154Pro 已有(peripheral_main.c:815)
- ⚠ 位含义差异:两产品 direction_mode 低 4 位语义不同(110S=方向/触发;154Pro=输出融合模式 7 种),小程序按产品区分
涉及文件
| 文件 | 内容 |
|---|---|
BLE/DLD154Pro_Peripheral_28K/APP/include/cmcng.h |
V3.04 + LOOP_MEASURE_BASE |
BLE/DLD154Pro_Peripheral_28K/APP/dbn_ble_srv.c |
0x24 追加 3B |
docs/ble-protocol.md / product-manual.md / technical-spec.md |
同步 V3.04 |
2026-08-25 — 蓝牙小程序接口协议文档
背景
根据 dbn_ble_srv.c(+ peripheral.c/gattprofile.c/storage.h/cmcng.h)整理蓝牙小程序与芯片交互的完整接口协议,供小程序开发对接。
文档要点
| 章节 | 内容 |
|---|---|
| §1 BLE 服务 | 服务 0xFFE0;Char1(0xFFE1 RW 命令下发)、Char4(0xFFE4 Notify 响应/上报);MTU 协商 + notify ≤ MTU−3 |
| §2 帧格式 | Magic(8F/7F)+Header+Len+CMD+Data+XOR+SUM;校验从 Header 起 |
| §3 分包 | 发送按 14B 写死分包(MTU=23 旧假设);Header=(amount<<4)|seq |
| §4-5 命令 | 0x10/0x1F/0x23/0x24/0x31/0x8A/0x92/0xC5 逐字段 |
| §6 主动上报 | 0xC0 线圈动态(type=5,含频率+360 补偿、variation 3B 有符号) |
| §7 坑清单 | sensitvity 1 |
关键发现(源码事实)
- sensitvity 协议层 1~4,内部
g_freq_sens = sensitvity − 1(03 索引灵敏度表 {108,54,28,14}),0x24 回读 +1——**与 vd960Loop 的 03 不同** - 0xC5 超时疑似 bug:
timeout_counter = timeout_min × 60 × 100,若意图 ms 应为 ×1000(现场验证) - 0x8A 写灵敏度表不直接更新 RAM,依赖
para_store_init()重读 - 0x1F/0x92 复位/出厂类命令无响应帧
涉及文件
| 文件 | 内容 |
|---|---|
docs/ble-protocol.md |
新增(依据 dbn_ble_srv.c 整理,固件 V3.03) |
2026-07-31 — 发布 V3.03
变更摘要
| 变更 | 说明 |
|---|---|
| 硬件看门狗 (WWDG) | 使能窗口看门狗,TMR1 ISR 5ms tick 驱动 g_wdg_counter,主循环 poll_wdg() 每 500ms 喂狗,超时 ~558ms 自动复位 |
| OTA 安全 | 跳转 OTA 前 WWDG_ResetCfg(DISABLE) 关闭看门狗,防止 OTA 期间超时复位 |
| 固件版本 | V3.02 → V3.03 |
涉及文件
| 文件 | 变更 |
|---|---|
peripheral_main.c |
+poll_wdg() + g_wdg_counter;移除 u32CountWdt;main() 中 WWDG_ResetCfg(ENABLE) |
peripheral.c |
OTA 跳转前 WWDG_ResetCfg(DISABLE) |
cmcng.h |
FIRMWARE_VER 3.02→3.03 |
2026-07-31 — 发布 V3.02
变更摘要
| 变更 | 说明 |
|---|---|
g_loop_cut_amount 累加修复 |
重连路径补充 g_loop_cut_last = 0 边沿记忆清零,放开 3 次上限 |
| Modbus 主动上报线圈事件 | 线圈断开/重连立即触发主动上报(对齐 700BS) |
| 0x2C 复位指令重构 | 700BS: SYS_ResetExecute() MCU 全复位;Modbus: HR 0x0012=0x2C2C |
| DLD154Tool v1.0.0 | 版本显示 + PyInstaller 打包;Modbus 复位按钮 |
| RS485 初始化时序 | 移至 para_store_init() 之后 |
| 光耦呼吸加速 | 红灯在非复位模式下光耦有信号时加速 (~0.5s),便于现场判断光耦状态 |
涉及文件
| 文件 | 变更 |
|---|---|
peripheral_main.c |
cut_amount 修复 + RS485 时序 + 光耦呼吸加速 (BREATH_OPTO_DUTY_STEP=32) |
rs485_700bs.c |
handle_reset_init() → SYS_ResetExecute() |
rs485_modbus.c/h |
+HR 0x0012 (System Cmd) |
protocol_modbus.py / main.py |
+build_reset_mcu() + 复位按钮 |
DLD154Tool.spec / .gitignore |
PyInstaller 打包配置 |
rs485-modbus-protocol.md |
V1.6→V1.7 |
devlog.md / product-manual.md / technical-spec.md |
V3.02 文档同步 |
2026-07-30 — Modbus RTU V1.6 私有协议编码实现
背景
根据 docs/rs485-modbus-protocol.md V1.6 规范,实现完整 Modbus RTU 从机协议(含主动上报私有扩展)。
与 700BS 协议共享 UART0 物理层,通过 g_fm_700bs_disable 互斥切换。
新增文件
| 文件 | 行数 | 说明 |
|---|---|---|
APP/include/rs485_modbus.h |
52 | API + 协议常量宏 (MB_IR_FULL_BLOCK_START/COUNT, MB_HR_AUTO_RPT_ENABLE/ACTIVE_THRESHOLD, 上报间隔) |
APP/rs485_modbus.c |
815 | 完整 Modbus 实现: CRC16 查表 + 6 个 FC 处理函数 + 全数据块组装 + 主动上报调度 + 车间距/通过时间测量 |
实现的功能码
| FC | 功能 | 关键细节 |
|---|---|---|
| 0x02 | 读离散输入 | 9-bit 位图, GPIOB_ReadPortPin 直读光耦 |
| 0x03 | 读保持寄存器 | 含 HR 0x0010(主动上报使能) 和 0x0011(活动阈值) |
| 0x04 | 读输入寄存器 | 基础 IR 0x0000–0x000C + 全数据块 0x0100–0x0112 (19 reg = 38B) |
| 0x06 | 写单寄存器 | 值域校验 + 只读拦截 + 连锁写入: Fusion Mode→direction_mode, Hold Time→g_hold_time, Freq Level→loopFreq_Level |
| 0x10 | 批量写寄存器 | 逐寄存器同 FC 0x06 逻辑 |
| 0x11 | Report Slave ID | "DLD154Pro\0" + loop1_LOOP_OK 状态 |
全数据块 (0x0100–0x0112)
灵敏度 | 频率档 | 融合模式 | car_state | 线圈状态(bit0=断开/bit1=稳定) | 光耦状态
频率Hz(32b) | CAPVD(32b) | Variation(32b signed)
断开累计(32b) | 继电器吸合累计(32b)
Time Type(0=间隙/1=通过/0xFFFF=无效) | 时间值10ms(32b)
- Variation =
loop1_CAPVD − loop1_Origin,实时计算 - 频率 =
FREQ_SYS * LPCNT / CAPVD + 360,与 700BS 一致 - 光耦 =
GPIOB_ReadPortPin(Pin_10) == 0,直读硬件
主动上报 3 级速率调度
| 状态 | 条件 | 间隔 | 迟滞 |
|---|---|---|---|
| 事件 | 继电器翻转 (relay1_state 边沿) | 立即 | — |
| 活动 | |Variation| ≥ 阈值 (HR 0x0011, 默认 10) | 150ms (30 tick) | — |
| 空闲 | |Variation| < 阈值 | 800ms (160 tick) | 连续 2 次低于阈值才降速 |
- 帧格式复用 FC 0x04 响应,与轮询完全一致
- 上报前先调
update_misc_time()更新 gap/pass time
车间距 / 通过时间
- 单位: 10ms (
mstick()/2) - 继电器 0→1 吸合沿 →
_misc_time_value = now − _last_relay_off_10ms,_misc_time_type = 0 - 继电器 1→0 释放沿 →
_misc_time_value = now − _last_relay_on_10ms,_misc_time_type = 1 _relay_engage_cnt在每次吸合沿递增 (全数据块 0x010E–0x010F)
改造现有文件
| 文件 | 变更 |
|---|---|
rs485_700bs.h |
+rs485_send() 声明; +extern _rx_buf/_rx_len/_rx_last_tick |
rs485_700bs.c |
_rx_buf/_rx_len/_rx_last_tick 去 static; rs485_send 去 static |
peripheral_main.c |
+#include "rs485_modbus.h"; gpio_uart_init 中 modbus_init(); Main_Circulation 中 g_fm_700bs_disable 分派 700BS/Modbus |
关键设计决策
- 与 700BS 共享 ISR: 不创建第二个 UART0_IRQHandler,Modbus 从共享
_rx_buf读取 - 帧超时判定:
mstick() − _rx_last_tick ≥ 2(10ms), 对齐 9600 的 t3.5≈4ms - 写穿透: Holding Register 写入后立即同步到 RAM 全局变量,不等待 flash 持久化 (flash 写入由调用方处理)
- CRC 错误静默: 符合 Modbus 标准——CRC 不匹配时不回应
影响
- RS485 物理层零改动,Modbus/700BS 通过 BLE 小程序切换
- 主动上报默认关闭 (
_auto_rpt_enable = 0),需通过 HR 0x0010 使能 - Holding Register 写操作不写 flash,若需持久化需额外调用
write_cfg_to_store
2026-07-30 — 输出融合模式枚举再次重排:地感且光耦后移
变更
将「地感且光耦」从值 1 移到值 3(排到后面),混行/ETC 前移:
旧 (V1.4): 0=或 1=且 2=混行 3=ETC 4=仅地感 5=仅光耦 6=复位
新 (V1.5): 0=或 1=混行 2=ETC 3=且 4=仅地感 5=仅光耦 6=复位
涉及文件
| 文件 | 变更 |
|---|---|
storage.h |
DLD_OUTPUT_MODE 枚举顺序:AND_RADAR 从 line 2 移至 line 4 |
peripheral_main.c |
注释块 MODE N 标签 + 内联模式号 (0/1/5→0/3/5, 2/3→1/2) |
docs/technical-spec.md |
§6.1 融合模式表重排; §6.2/6.3 标题模式号更新; §7.2 LED 行改写为非数字区间 |
docs/product-manual.md |
§4.6 融合模式表重排 + 默认值 1→4 (仅地感); 模式号引用更新 |
docs/rs485-modbus-protocol.md |
§6.5 融合模式表重排 + 状态机标题模式号更新; V1.4→V1.5 |
docs/devlog.md |
本条目 |
影响
- 代码全用符号名,无行为影响
- 已有 flash 配置的
fusion_mode旧值语义与新模式不兼容,需重新设置
2026-07-29 — 输出融合模式枚举重排
变更
枚举值重新分配,将高频使用的融合模式前置:
旧: 0=复位 1=仅地感 2=仅光耦 3=或 4=且 5=混行 6=ETC
新: 0=或 1=且 2=混行 3=ETC 4=仅地感 5=仅光耦 6=复位
涉及文件
| 文件 | 变更 |
|---|---|
storage.h |
DLD_OUTPUT_MODE 枚举顺序重排 |
peripheral_main.c |
注释号同步更新 (0→6, 1→4, 2/3/4→0/1/5, 5/6→2/3); L1279 >= RADAR_ONLY 区间判断→精确 !=LOOP_ONLY && !=LOOP_X_RESET 比较; 工厂默认 direction_mode=0x04 (仅地感) |
docs/technical-spec.md |
§6 融合模式表 + 状态机标题 |
docs/product-manual.md |
§4.6 融合模式表 |
docs/rs485-modbus-protocol.md |
V1.3→V1.4: §3.3 默认值、§4.3/4.4 示例、§6.5 表格、复位注释 |
docs/devlog.md |
本条目 |
影响
- 已有测试设备的 flash 配置 (
direction_mode低 4 位) 需要重新设置,旧值与新模式语义不兼容 - 代码逻辑(命名常量比较)不受影响,仅枚举值和注释变更
2026-07-29 — 发布 V3.01 版本文档:技术规格书 + 产品说明书
文档产出
| 文档 | 路径 | 内容 |
|---|---|---|
| 技术规格书 | docs/technical-spec.md |
系统架构、电气参数、IO 引脚分配、检测算法全链路(频率测量/IIR/斜率限幅/灵敏度表/进入确认/平坦性离开/基线跟踪/冻结超时)、时序状态机、7 种输出融合模式状态机、指示灯、上电稳定期、线圈故障处理、通信协议(BLE/700BS/Modbus)、Flash 存储布局 |
| 产品说明书 | docs/product-manual.md |
面向终端用户:产品概述、技术参数、硬件接口(端子定义/指示灯)、BLE 配置项、灵敏度档位、输出模式、输出融合模式(含人车混行防砸和ETC工作原理)、安装指南、故障排查、RS485总线集成速查、订购信息 |
源数据来源
peripheral_main.c: 算法参数 (MEASUREMENT_BASE=524288, ALFA_CAP1=79, MAX_SLOPE_RATE=5%, ENTRY_CONFIRM=3, FREEZE_TIMEOUT=1000, WINDOW_ORIGIN=500, STABLE_SAMPLES=128)cmcng.h: 版本号 (FW 3.01 / HW 3.01), 全局变量声明storage.h: Flash 布局, 配置结构体,DLD_OUTPUT_MODE枚举dbn_ble_srv.h: BLE 命令码docs/DLD154Pro硬件资源.md: IO 分配docs/rs485-modbus-protocol.md/docs/rs485-700bs-protocol.md: 通信协议
与 DLD154V4B 的关键差异
| 项目 | DLD154V4B | DLD154Pro |
|---|---|---|
| MCU | AT32F421 (ARM M4) | CH591R (RISC-V) |
| 配置方式 | 物理 DIP 开关 | BLE 小程序 |
| 通信接口 | TTL Tx 调试口 | RS485 (双协议) + BLE |
| 继电器 | 2 路 | 1 路 |
| 指示灯 | 红+绿+黄 (3 LED) | 红呼吸+绿 (2 LED) |
| 光耦 | 无 | 有 (7 种融合模式) |
2026-07-28 (傍晚) — 光耦参与模式下 LEDA 同步继电器状态
光耦参与模式 (MODE 2-6) 下,绿色 LED 原先跟随线圈 FLAG_IN/FLAG_OUT 变化,
在雷达单独触发(如人车混行防砸窗口)时 LED 不亮。修正为:
- TMR1 ISR 50ms 块末尾,
g_output_radar_mode >= 2且正常运行(非断开/非稳定期)时, LEDA 直接跟随g_loop_acs_info.relay1_state - 断开/稳定期 200ms 闪烁优先级不变(5ms 段优先处理)
效果:继电器吸合→绿灯亮,继电器释放→绿灯灭,与线圈或雷达触发源无关。
2026-07-28 (午后) — 光耦输出模式完整实现:6 种融合逻辑 + 状态机
架构
opt_input_poll() 处理光耦输入 → 产出 g_opt_trigger (1=有效) → TMR1 ISR 继电器输出段 case 0 根据 g_output_radar_mode 做融合判决。
光耦 PB10 → 3样本多数表决防抖 → opt_input_poll() → g_opt_trigger
↓
线圈 VD_FLAG/FLAG_OUT → coil_sig ──────────→ 融合判决 → RLY1
↑
g_output_radar_mode
各模式实现
| 模式 | 值 | opt_input_poll() |
继电器 case 0 融合公式 |
|---|---|---|---|
| LOOP_X_RESET | 0 | 光耦复位 (400ms低→上升沿→SYS_ResetExecute) | coil_sig |
| LOOP_ONLY | 1 | return, g_opt_trigger=0 | coil_sig |
| RADAR_ONLY | 2 | g_opt_trigger = 光耦信号 | g_opt_trigger |
| LOOP_OR_RADAR | 3 | g_opt_trigger = 光耦信号 | coil_sig || g_opt_trigger |
| LOOP_AND_RADAR | 4 | g_opt_trigger = 光耦信号 | coil_sig && g_opt_trigger |
| HUMAN_VD_MIX | 5 | 状态机 (见下) | coil_sig || g_opt_trigger |
| ETC | 6 | 状态机 (见下) | coil_sig || g_opt_trigger |
注:
coil_sig = (loop1_VD_FLAG | loop1_FLAG_OUT)— 含离开脉冲保持
HUMAN_VD_MIX 状态机 (人车混行防砸)
IDLE (雷达屏蔽, 仅线圈)
│ 线圈检测到车
▼
ARMED (雷达解禁, 线圈||雷达)
│ 两者均释放
▼
WINDOW (3s 防砸窗口)
│ 雷达触发 → g_opt_trigger=1 → 继电器吸合, 窗口复位
│ 线圈上线 → 回到 ARMED
│ 3s 超时无触发 → 回到 IDLE, 落杆
定时参数: OPT_VM_WINDOW_TICK = 600 (600×5ms = 3s)
ETC 状态机
IDLE (雷达屏蔽, 仅线圈)
│ 线圈检测到车
▼
ARMED (雷达解禁, 线圈||雷达)
│ 两者均释放
▼
DEBOUNCE (500ms 防抖)
│ 线圈/雷达重新触发 → 回到 ARMED
│ 500ms 超时 → 回到 IDLE, 落杆
定时参数: OPT_ETC_DEBOUNCE_TICK = 100 (100×5ms = 500ms)
光耦防抖
所有非复位模式共用 3 样本多数表决 (OPT_DEBOUNCE_CNT=6): 最近 3 次采样中 ≥2 票即判定有效,等效 ~30ms 消抖。
文件变更
| 文件 | 变更 |
|---|---|
peripheral_main.c |
+g_opt_trigger 全局变量, opt_input_poll() 重写 (120→180行), TMR1 ISR case 0 融合判决 |
cmcng.h |
+extern uint8_t g_opt_trigger |
2026-07-28 — 光耦输出模式升级:DLD_OUTPUT_MODE 枚举 + direction_mode 低四位取值
背景
光耦输入功能从原来的「二值化开关」(使能/复位)升级为 7 种输出模式,
由 direction_mode 字节的低四位选择。g_fm_radar_input_disable(来自 function_mode bit1)
更名为 g_output_radar_mode,语义从布尔值变为枚举值。
DLD_OUTPUT_MODE 枚举
typedef enum _DLD_OUTPUT_MODE
{
OUTPUT_MODE_LOOP_X_RESET = 0, // 光耦输入为复位信号,仅地感检测输出
OUTPUT_MODE_LOOP_ONLY, // 仅地感,光耦输入无效
OUTPUT_MODE_RADAR_ONLY, // 仅光耦(雷达输出接光耦输入),地感无效
OUTPUT_MODE_LOOP_OR_RADAR, // 地感或雷达
OUTPUT_MODE_LOOP_AND_RADAR, // 地感和雷达
OUTPUT_MODE_HUMAN_VD_MIX, // 人车混行防砸:有车后光耦/地感"或",离场 3s 内光耦有效持续防砸
OUTPUT_MODE_ETC, // ETC:有车后光耦/地感"或",光耦断开需 500ms 防抖才释放继电器
}DLD_OUTPUT_MODE;
变量与取值变更
| 项目 | 旧 | 新 |
|---|---|---|
| 全局变量名 | g_fm_radar_input_disable |
g_output_radar_mode |
| 符号类型 | bit (0/1) | uint8_t (0~6) |
| 取值来源 | (function_mode >> 1) & 0x01 |
direction_mode & 0x0F |
| 解析位置 | peripheral_main.c:para_store_init() + dbn_ble_srv.c:unpack_pkg_set_cjq_param() |
同上 |
| BLE 回读字段 | g_function_mode |
g_loop_cng_unit.direction_mode (完整 8 位) |
opt_input_poll 门控 |
if (g_fm_radar_input_disable == 0) → 雷达模式 return |
if (g_output_radar_mode) → 非 0 模式 return |
实现状态
| 模式 | 状态 | 说明 |
|---|---|---|
| 0 — LOOP_X_RESET | ✅ 已实现 | PB10 低电平 ≥400ms(80 tick×5ms)后上升沿 SYS_ResetExecute() 芯片复位 |
| 1~6 | ❌ 未实现 | opt_input_poll() 中直接 return |
文件变更
| 文件 | 变更 |
|---|---|
storage.h |
+DLD_OUTPUT_MODE 枚举 (7 种模式) |
cmcng.h |
g_fm_radar_input_disable → g_output_radar_mode |
peripheral_main.c |
变量更名 + 解析路径改 direction_mode & 0x0F |
dbn_ble_srv.c |
同上 + BLE 回读改用 direction_mode 完整字段 |
2026-07-22 — BLE 新增 RS485 地址/波特率读写 + 空闲关蓝牙超时 + 功能码细分
新增 BLE 命令
CMD_DBN_RW_UART_BAUD (0x31) — 读写 RS485 通信参数:
| 字节偏移 | 字段 | 说明 |
|---|---|---|
| [4] | RW | 0=读, 1=写 |
| [5] | BT_close_min | 蓝牙空闲超时关闭时间 (分钟), 0=不关闭 |
| [6:8] | baud_rate | RS485 波特率 (3 字节, little-endian) |
| [9] | rs485_id | RS485 从机地址 (1-247) |
| [10:12] | reserved | 预留 |
- 读:返回当前存储值 + status=0
- 写:写入 RAM 并持久化到 DataFlash (
ADDR_BT_Close_TIMEOUT_Offset起 5 字节)
Flash 存储布局
0x10 ADDR_BT_Close_TIMEOUT_Offset 1B 蓝牙空闲超时 (分钟)
0x11 Addr_RS485_Baud_Offset 3B RS485 波特率 (LE32)
0x14 Addr_RS485_ID_Offset 1B RS485 从机地址
出厂默认:RS485 ID=1, 波特率=9600, 蓝牙超时=0(不关闭)
功能码细分 (g_function_mode)
g_function_mode 取自 direction_mode 高 4 位,低 2 位细分:
| bit | 字段 | 0 | 1 |
|---|---|---|---|
| bit0 | g_fm_700bs_disable |
700BS 协议 | Modbus 协议 |
| bit1 | g_fm_radar_input_disable |
光耦输入使能 | 光耦输入复位 |
RS485 将支持两种协议:700BS(后续上传)和 Modbus。通过小程序设置
direction_mode高 4 位的 bit0 切换。
文件变更
| 文件 | 变更 |
|---|---|
dbn_ble_srv.h |
+CMD_DBN_RW_UART_BAUD 0x31 |
cmcng.h |
+extern 声明: fm_700bs_disable, fm_radar_input_disable, uart/bt 配置 |
storage.h |
+Flash 地址宏: BT_timeout, RS485_baud, RS485_ID |
peripheral_main.c |
+全局变量定义, factory_dev 默认值, para_store_init 恢复 |
dbn_ble_srv.c |
+CMD_DBN_RW_UART_BAUD handler, unpack 中解析 function_mode bits |
待办
- RS485 700BS 协议定义
- RS485 Modbus 协议定义
- RS485 串口中断收发实现 (UART0)
- 蓝牙空闲超时自动关闭逻辑
2026-07-21 — 灵敏度等级与 ΔL/L 的物理关系分析
参数表
// sens_in: 进入阈值, sens_out: 离开阈值 (0=最低, 3=最高)
SensTable = { 108, 54, 28, 14 }; // 进入
SensTable1 = { 81, 32, 16, 12 }; // 离开
计算链路
Step 1:阈值差值
loop1_dlt_ORG = (Origin * sens) >> 16; // = Origin × sens / 65536
Step 2:进入判定
if (CAPVD < Origin - dlt_ORG) // ← ΔCAPVD / Origin > sens / 65536
Step 3:CAPVD → 电感
线圈振荡频率 f ∝ 1/√L,周期 T ∝ √L。测量窗 CAPVD 正比于平均周期:
ΔCAPVD / Origin = ΔT / T₀ = (√L - √L₀) / √L₀
对微小变化泰勒展开:dT/T ≈ dL/(2L),即:
ΔL / L ≈ 2 × ΔCAPVD / Origin
Step 4:最终 ΔL/L 公式
ΔL/L_entry = 2 × sens_in / 65536
ΔL/L_exit = 2 × sens_out / 65536
灵敏度等级对应 ΔL/L
| 等级 | sens_in | ΔL/L 进入 | sens_out | ΔL/L 离开 | 迟滞比 |
|---|---|---|---|---|---|
| 低 (0) | 108 | 0.330% | 81 | 0.247% | 1.33 |
| 中 (1) | 54 | 0.165% | 32 | 0.098% | 1.69 |
| 高 (2) | 28 | 0.085% | 16 | 0.049% | 1.75 |
| 最高(3) | 14 | 0.043% | 12 | 0.037% | 1.17 |
物理验证
典型 100μH 线圈:
- 现代轿车经过:ΔL/L ≈ 5%–15%,任一灵敏度均能可靠触发
- 高灵敏度 0.085%:足够敏感,需注意温漂(~20°C 引起约 0.1% 的感量偏移)和邻道串扰
- 迟滞比 1.33–1.75:防止车辆边界状态反复跳变,低灵敏度迟滞最小
快速换算
sens 值直接对应 千分之 2×sens 的感量变化百分比——除以 1000 就是 ΔL/L(%)。
2026-07-21 (午后) — 修复灵敏度 bug + 有限存在时间 + 版本号
BLE 灵敏度无法修改
根因: 硬件适配时删了 poll_sens_key(),在 INIT_VD() 中硬编码了 g_freq_sens = 2,
但未在 BLE 参数解包 unpack_pkg_set_cjq_param() 中同步更新,导致小程序修改灵敏度无效。
修复:
peripheral_main.c:g_freq_sens从INIT_VD()移到para_store_init(), 从存储的g_loop_cng_unit.sensitvity读取:(sensitvity > 0) ? (sensitvity - 1) : 0dbn_ble_srv.c:unpack_pkg_set_cjq_param()中同样增加g_freq_sens同步更新, 确保 BLE 小程序实时修改后立即生效
有限存在时间公式对齐
dbn_ble_srv.c 中 g_hold_time 计算写的是 exist_mode * 30 * 20,
但 para_store_init() 中用的是 exist_mode * 20 * 5(50ms tick)。
统一为 20 * 5(对应参数值 × 100ms × 5s 基础周期)。
版本号
- 固件:
4.01→3.00 - 硬件:
1.00→3.01
2026-07-21 — 项目初始化:从 DLD110SV4 复制基线 + 按硬件资源文档调整 IO
背景
DLD154Pro 是 DLD110SV4 的硬件升级版(同 MCU CH591R),核心变更:
- 继电器 双路→单路(删 RLY2)
- 删除拨码开关(灵敏度改由小程序设置)
- 线圈调频 两级→一级(删 PA13 FLEVEL_L)
- 新增 RS485 接口(PA14/PA15/PA13,协议待定)
- 新增光耦输入(PB10,逻辑待定)
- 指示灯从单色→双色(LEDA 绿 + LEDB 红呼吸灯)
- DEBUG UART0 被 RS485 占用,删除全部
仓库
- 远程: http://118.178.252.17:3000/wangfq/DLD154Pro
- 本地:
/home/wfq/projects/vd_detector/DLD154Pro - commit
5f5f697: init 基线 - commit
91ba844: feat 硬件适配
IO 宏重定义
| 引脚 | 旧(DLD110SV4) | 新(DLD154Pro) |
|---|---|---|
| PA8 | RLY1 (存在) | RLY1 (存在,不变) |
| PB23 | RLY2 (功能/脉冲) | LEDB (红色呼吸灯) |
| PA12 | FLEVEL_H (33nF) | FLEVEL (33nF,一级) |
| PA13 | FLEVEL_L (10nF) | UART0_RE (RS485 方向) |
| PA14 | KEY_SA1 / DEBUG_TX | UART0_TX (RS485) |
| PA15 | KEY_SA2 / DEBUG_RX | UART0_RX (RS485) |
| PB10 | - | IN_1 (光耦输入) |
| PB22 | LEDA (绿色) | LEDA (绿色,不变) |
删除项
RLY2_ON/OFF宏及全部 RLY2 输出逻辑KEY_SA1/KEY_SA2宏及poll_sens_key()函数FLEVEL_L_LOW/HIGH,FLEVEL_H_LOW/HIGH→ 改为FLEVEL_LOW/HIGHg_flag_output,g_xn_counter全局变量- DEBUG UART0 初始化 (
gpio_uart_init中#ifdef DEBUG块) Main_Circulation中#ifdef DEBUGPRINT 块- TMR1_ISR 中
_cnt/g_flag_outputDEBUG 定时器 - TMR0_ISR 中
g_xn_counterDEBUG 计数器 para_store_init()中频率四档 switch → 双档 if/else
新增/预留
- RS485 引脚宏:
RS485_TX_PIN,RS485_RX_PIN,RS485_RE_PIN,RS485_RE_TX(),RS485_RE_RX()(仅初始化引脚,协议待定) - 光耦输入宏:
OPT_IN1(仅初始化 PB10 输入上拉,逻辑待定) - LEDB 宏:
LEDB_ON/OFF(PB23,低电平有效) g_freq_sens = 2默认最高灵敏度(取代 poll_sens_key 拨码逻辑)
继电器输出简化
| 模式 | 旧 (双继电器) | 新 (单继电器) |
|---|---|---|
| case 0: 存在输出 | RLY1 跟随 VD, RLY2 跟随 VD | RLY1 跟随 VD |
| case 1: 进入脉冲 | RLY2=存在, RLY1=进入脉冲 | RLY1=进入脉冲 |
| case 2: 离开脉冲 | RLY2=存在, RLY1=离开脉冲 | RLY1=离开脉冲 |
| default | RLY2=存在 | RLY1=存在 |
保留(协议兼容)
storage.h的Loop_ACS_Info.relay2_cng/relay2_state字段保留,默认值=0dbn_ble_srv.c:468上报字节 relay2 位自动为 0(字段初始化为 0 后无写入)
待办
- RS485 通信协议定义 + UART0 中断/收发实现
(2026-07-24 完成) - 光耦输入逻辑(与其他检测器联动 / 综合判断)
- IAP/OTA 项目文件中的 DLD110S 引用更新(
592OnlyUpdateApp_*) .mrs/工作区文件清理(大量 DLD110S 历史快照)
2026-07-23~24 — RS485 700BS 协议实现 & 四级灵敏度
RS485 700BS 从机协议
| 项目 | 说明 |
|---|---|
| 物理层 | RS485 半双工, 9600 8N1, PA14=TX PA15=RX PA13=RE |
| 帧格式 | 主机 3 字节 (STX ADDR XOR), 从机 3~9 字节变长 |
| 心跳 | 空闲 5s / 故障(线圈断开) 1s / 事件(car_state翻转)立即 |
| 命令 | 0xFA 查询状态, 0x1B 查询频率, 0x2C 复位线圈, 0x3D 查询DIP |
文件: APP/rs485_700bs.c (新增), APP/include/rs485_700bs.h (新增)
踩坑记录
-
UART0 API 不兼容 — CH592 SDK 中
UART0_GetITFlag()是无参宏(非函数),UART0_ClearITFlag()不存在。改用switch(UART0_GetITFlag())标准模式,参考 UART1 例程。 -
while(R8_UART0_TFC == 0)死循环 — TX FIFO 空时条件永真,主循环卡死导致地感不工作。修正为!= 0(等 FIFO 空再写下一字节)。 -
rs485_init()从未被调用 —gpio_uart_init()只写了注释/* 由 rs485_init() 统一初始化 */但未实际调用,UART0/GPIO 未配置。修复:替换注释为函数调用。 -
频率始终为 0 —
g_loop_acs_info.frequent只在 BLE 报告路径usart_packet_processing_acs_loop中更新,BLE 断开时永不执行 → freq=0。 -
频率非实时 — 改用
g_loop_acs_info.loop_capvd仍有问题:该值被flag_change门控冻结(上电/车辆进出时flag_change=1→capvd 不更新,清零只在 BLE 报告路径)。最终方案:直接使用loop1_CAPVD(vd1_task()每次实时 IIR 滤波值),不经过 BLE 通道。
最终频率计算:
freq = (uint64_t)FREQ_SYS * loop1_LPCNT / loop1_CAPVD + 360
四级灵敏度
MAX_LOOP_SENS_AMOUNT: 3 → 4
新增第四档:进入阈值 14, 离开阈值 12 (ΔL/L≈0.04%),适用于极高灵敏度场景(如摩托车/小型车辆检测)。需注意温漂影响——20°C 温度变化可引起约 0.1% 感量偏移,第四档信噪比余量仅约 2:1。
2026-07-24 (傍晚) — 光耦输入复位功能 & mstick() 时间单位修正
光耦输入复位 (opt_input_poll)
| 项目 | 说明 |
|---|---|
| 引脚 | PB10 (IN_1), 内部上拉, 光耦干接点输入 |
| 使能条件 | g_fm_radar_input_disable == 1 |
| 触发逻辑 | 干接点接通(PB10=0) ≥500ms → 断开(上升沿) → SYS_ResetExecute() |
| 消抖 | <500ms 短脉冲上升沿清零计时, 不触发 |
关键修复:PB10 数字输入使能
R32_PIN_CONFIG2 寄存器中 RB_PIN_PB10_15_DIS 默认置位(关闭数字输入省电)。GPIOB_ModeCfg(..., GPIO_ModeIN_PU) 只配置了上下拉和方向,数字输入通路在更底层被掐断。修复:R32_PIN_CONFIG2 &= ~(1UL << 26)。
mstick() 时间单位修正
mstick() = TimingDelayInc,在 TMR1 ISR (5ms 间隔) 中递增。单位是 5ms/tick,不是毫秒。
| 位置 | 原来 | 修正后 | 实际时间 |
|---|---|---|---|
opt_input_poll 阈值 |
>= 500 |
>= 100 |
500ms |
RS485_HEARTBEAT_MS |
5000 | 1000 | 5s |
RS485_FAULT_MS |
1000 | 200 | 1s |
帧超时
mstick() - _rx_last_tick > 10(=50ms)保留未改,对 9600 波特率够用。