10 KiB
DLD110SV4 蓝牙小程序接口协议
依据源码整理:
BLE/DLD110S_Peripheral_28K/APP/dbn_ble_srv.c(主逻辑)、peripheral.c/Profile/gattprofile.c(BLE 服务)、peripheral_main.c(灵敏度/检测)、include/storage.h(配置结构)、include/cmcng.h(常量) 固件版本:V4.20(cmcng.hFIRMWARE_VER)| 硬件版本:V4.01 | 产品型号:DLD110S(BLE 单线圈)
⚠ 与 DLD154Pro 协议的三处关键差异(先读这节)
| # | 差异 | DLD110SV4 | DLD154Pro |
|---|---|---|---|
| 1 | 灵敏度来源 | 硬件拨码 KEY_SA1/SA2 决定(poll_sens_key,peripheral_main.c:263),协议 0x23 设置的 sensitvity 不参与检测 |
BLE 配置(无拨码),sensitvity 1~4 直接生效 |
| 2 | 灵敏度档数 | 3 档 {108,54,28} / {81,32,16}(sens_in/sens_out) |
4 档 {108,54,28,14} / {81,32,16,12} |
| 3 | 命令 0x31 | 无(无 RS485) | 有(读写波特率/地址) |
灵敏度拨码映射(
poll_sens_key,每周期刷新g_freq_sens,检测阈值 =g_loop_sens_list.sens[g_freq_sens]):
KEY_SA1 KEY_SA2 g_freq_sens 档位 检测阈值 sens_in 1 1 0 最低 108(0.165% Δf/f) 0 1 1 中 54(0.082%) 1 0 2 最高 28(0.043%) 0 0 — 保持上次 — DEBUG 编译时固定
g_freq_sens = 2。
1. BLE 服务与特征
| 服务/特征 | UUID | 属性 | 长度 | 用途 |
|---|---|---|---|---|
| 服务 SIMPLEPROFILE | 0xFFE0 | — | — | 广播服务 UUID |
| Char1 | 0xFFE1 | 读写 (RW) | 64B | 小程序 → 芯片:命令下发 |
| Char2 | 0xFFE2 | 读 | 1B | 预留 |
| Char3 | 0xFFE3 | 写 | 8B | 预留 |
| Char4 | 0xFFE4 | 通知 (Notify) | 32B | 芯片 → 小程序:命令响应 + 主动上报 |
| Char5 | 0xFFE5 | 读 | 5B | 预留 |
- 设备名:
DLD110S(广播 + GATT Device Name) - MTU:默认 23,连接后协商(
ATT_MTU_UPDATED_EVENT)。notify 单包 payload ≤peripheralMTU − 3 - 交互模型:写 Char1 下发命令帧 → 芯片处理 → Char4 notify 返回响应帧;主动上报也走 Char4
2. 帧格式与校验
| Magic 1B | Header 1B | Len 1B | CMD 1B | Data N B | XOR 1B | SUM 1B |
| 字段 | 说明 |
|---|---|
| Magic | 0x8F = 车检器默认协议;0x7F = 透传 |
| Header | 单包 = 0x00;分包 = (pkg_amount << 4) | pkg_seq(seq 从 1) |
| Len | 1(CMD)+ N(Data 字节数) |
| XOR | 从 Header 到 Data 末尾逐字节异或 |
| SUM | 从 Header 到 Data 末尾逐字节求和(低 8 位) |
校验算法(dbn_ble_srv.c compute_ckb/check_pkg)与 DLD154Pro 完全一致:最小帧长 6,XOR/SUM 任一不符丢弃。
3. 分包机制
与 DLD154Pro 相同(同一模板):
- 发送:
MAX_BLE_DAT_RESPONSE_LEN = 14(= BLE_BUFF_MAX_LEN−4,MTU=23 旧假设),多包 Header =(amount<<4)|seq - 接收:
unpack_packs()支持重组(当前仅 0x1C/0x1D 使用,已注释) - ⚠ 分包粒度写死 14B,MTU 协商更大后不重新分包
4. 命令总览
| CMD | 名称 | 方向 | 说明 |
|---|---|---|---|
| 0x10 | GET_DEV_INFO | 小程序→芯片 | 读设备信息(MAC/版本/型号) |
| 0x1F | RESET_DEV | 小程序→芯片 | 复位设备(SYS_ResetExecute) |
| 0x23 | SET_CJQ_PARAM | 小程序→芯片 | 设置车检器参数(灵敏度不生效,见 §5.3) |
| 0x24 | GET_CJQ_PARAM | 小程序→芯片 | 读车检器参数 |
| 0x8A | LOOP_SENS_LIST | 小程序→芯片 | 读写灵敏度表(sens_in/sens_out) |
| 0x92 | SET_CJQ_FACTORY | 小程序→芯片 | 恢复出厂 |
| 0xC5 | SENS_ACS_ENABLE | 小程序→芯片 | 主动上报使能 |
| 0xC0 | SUB_SENS_REPORT | 芯片→小程序 | 主动上报线圈动态(不可下发) |
不存在:0x31(DLD154Pro 有,本产品无 RS485)。 未实现(注释):0x1C/0x1D/0x1E/0x20-0x22/0x6D/0x87/0x88/0x89。
5. 命令详述
5.1 0x10 读设备信息
无 Data。响应 Data:
| 偏移 | 字节 | 内容 |
|---|---|---|
| 0-5 | 6 | MAC 地址 |
| 6-7 | 2 | 硬件版本 MAIN/SUB(V4.01 → 04 01) |
| 8-9 | 2 | 固件版本 MAIN/SUB(V4.20 → 04 14) |
| 10 | 1 | 产品型号长度 |
| 11.. | N | 产品型号 ASCII("DLD110S") |
| .. | 6 | 设备编号 |
| .. | 2 | sub_code(固定 0) |
| .. | 2 | 总线设备数(固定 0) |
5.2 0x1F 复位设备
无 Data。SYS_ResetExecute() 整机冷复位,无响应帧。
5.3 0x23 设置车检器参数
Data(5B):
| 偏移 | 内容 |
|---|---|
| 0 | sensitvity(低4位) | loopFreq_Level(高4位) |
| 1 | delay_time(离开延时) |
| 2 | output_mode(低2位) | loopSafe_Timeout(高5位) |
| 3 | exist_mode(有限存在时长) |
| 4 | direction_mode(高 4 位 = g_function_mode) |
⚠ 灵敏度字段不生效:g_loop_cng_unit.sensitvity 仅写入 flash 存档,检测阈值由拨码 g_freq_sens 决定(见开头差异表)。小程序设置灵敏度无效,现场改灵敏度必须拨码。
内部换算(unpack_pkg_set_cjq_param):
g_function_mode = direction_mode >> 4
g_hold_time = exist_mode * 30 * 20 (600 tick ≈ 30s × exist_mode, @50ms tick)
处理:更新全局 → write_cfg_to_store(4, tmp, 7) → para_store_init()。响应:1B status=0。
5.4 0x24 读车检器参数
无 Data。响应 Data(11B):
| 偏移 | 内容 |
|---|---|
| 0 | (g_freq_sens + 1) | (loopFreq_Level << 4)(灵敏度回读 = 拨码档位 + 1,值域 1~3) |
| 1 | delay_time |
| 2 | output_mode | (loopSafe_Timeout << 3) |
| 3 | exist_mode |
| 4 | sens_list.total << 4(= 3,高 4 位) |
| 5 | 线圈断开次数低字节 |
| 6 | 线圈断开次数高字节 |
| 7 | g_function_mode(注意:DLD154Pro 此处是 direction_mode) |
| 8-10 | 归一化基数 LOOP_MEASURE_BASE(3B LE,= 524288)(V1.1 追加) |
⚠ 偏移 8-10 用途(协议 V1.1,2026-08-26 追加):variation 换算 ΔL/L 的归一化基数。 第三方应用连接后读一次 0x24 缓存该值:
Δf/f ≈ variation / LOOP_MEASURE_BASE,ΔL/L ≈ -2 × variation / LOOP_MEASURE_BASE。 背景:DLD110S 的 MEASUREMENT_BASE = 524288(2^19 @60MHz),与 DLD154V4B 的 131072 不同——小程序曾照搬 131072 导致所有百分比放大 4 倍。固件显式上报后第三方无需猜测。 向后兼容:老小程序只读前 8B 不受影响;新小程序读 11B。
5.5 0x8A 读写灵敏度表
读(pkg[4]=0):响应 Data:[0x10] [total=3] [sens0_in LE2 | sens0_out LE2] [sens1...]
写(pkg[4]≠0):Data 从 pkg[5] 起:[total] [表...]。写 flash Addr_Loop_Sens_List_Offset(0x20) + para_store_init()。不直接更新 RAM,依赖重读生效。
出厂默认 3 档:sens_in {108, 54, 28} / sens_out {81, 32, 16}(peripheral_main.c:187,滞回 ~75/59/57%)。
5.6 0x92 恢复出厂
set_factory_param() + factory_dev() → para_store_init()。响应:1B status=0。
5.7 0xC5 主动上报使能
Data:[enable] [interval] [timeout_min]
- enable:1=开启,0=关闭
- interval:间隔系数,实际
interval × 0x7F(127) - timeout_min:超时分钟数(0=不限时)
处理:开启时 timeout_counter = timeout_min × 60 × 100(源码 TODO 标注 min→ms,60×100=6000 疑应为 60000,待现场验证)。关闭时 flag=0。
6. 主动上报 0xC0(芯片 → 小程序)
与 DLD154Pro 相同模板(type = 5 SENS_LOOP_DYNAMIC):
| 偏移 | 字节 | 内容 |
|---|---|---|
| 0 | 1 | 0x05(SENS_LOOP_DYNAMIC) |
| 1 | 1 | loop_num<<6 | freq_level<<4 | condition&0x0F |
| 2 | 1 | relay2_state<<6 | relay2_cng<<4 | relay1_state<<2 | relay1_cng&0x3 |
| 3 | 1 | loop1_FLAG_CUT<<7 | car_state<<4 | direction&0x0F |
| 4-6 | 3 | 线圈断开次数(LE,上电未连时为 1) |
| 7-9 | 3 | 实际频率(LE,freq = sclk_freq/CAPVD×LPCNT + 360 补偿) |
| 10-12 | 3 | variation(3B 有符号补码 LE,正=车/金属进入方向) |
触发:事件(flag_event)立即上报;周期 report_counter >= 120(120 × 50ms ≈ 6s);前提 0xC5 开启。
variation 接收端注意:3B 有符号,负值需符号扩展(if (v & 0x800000) v |= 0xFF000000)。
condition:环境评估 0~15(g_env_activity/10,>150 取 15;线圈断开强制 15)。
7. 实现细节与坑(对照源码)
- ⚠ 灵敏度是拨码的不是协议的:检测阈值 =
g_loop_sens_list.sens[g_freq_sens](peripheral_main.c:609),g_freq_sens 由poll_sens_key()读 KEY_SA1/SA2 每周期刷新。0x23 的 sensitvity 只存档不生效,0x24 回读的是拨码档位+1 - 3 档灵敏度(MAX_LOOP_SENS_AMOUNT=3),0x8A 写表 total 上限 3
- 无 0x31:DLD110SV4 无 RS485,小程序不应下发 0x31
- 0xC5 超时疑似 bug:
timeout_min × 60 × 100(若意图 ms 应为 ×1000,待现场验证) - 0x8A 写表不直接更新 RAM:依赖
para_store_init()重读 - 0xC0 frequent +360 补偿:经验值,示波器标定用
- 0x1F/0x92 无响应帧:复位/出厂类命令执行后设备重启
- notify 超限静默丢弃:
len > (peripheralMTU-3)返回 FAIL 不重发,长响应必须分包 - 0x24 偏移 7 是 g_function_mode(非 direction_mode)——与 DLD154Pro 不同,解析别混
- g_hold_time 换算差异:
exist_mode × 600 tick(≈30s/单位,DLD154Pro 为 ×100 tick ≈5s/单位)——产品差异,协议层语义一致
8. 交互示例
读取设备信息(无 Data,Len=1):
下发: 8F 00 01 10 11 11
│ │ │ │ │ └ SUM = 0x00+0x01+0x10 = 0x11
│ │ │ │ └─ XOR = 0x00^0x01^0x10 = 0x11
│ │ │ └─ CMD = 0x10
│ │ └─ Len = 1 (CMD only)
│ └─ Header = 0 (单包)
└─ Magic = 0x8F
芯片 → Char4 notify: 8F 00 10 XX [MAC6][04 01][04 14][07 "DLD110S"][dev_no6][00 00][00 00] [XOR] [SUM]
设置参数(如延时/输出,灵敏度不生效):
下发: 8F 00 06 23 20 00 00 00 00 [XOR] [SUM]
Len=6: CMD(0x23)+Data5
Data[0]=0x20: sensitvity=2(仅存档) | freq_level=0
Data[1..4]=延时/输出/存在/方向模式