Files
DLD154Pro/docs/ble-protocol.md
T
wangfq fcbe7698a3 docs(DLD154Pro): 新增蓝牙小程序接口协议文档 (依据 dbn_ble_srv.c)
- §1 BLE 服务: 0xFFE0 服务, Char1(0xFFE1 RW 命令下发)/Char4(0xFFE4 Notify)
- §2 帧格式: Magic(8F/7F)+Header+Len+CMD+Data+XOR+SUM
- §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~4 (≠vd960Loop 0~3), 0xC5 超时疑bug, 0x8A 写表依赖重载
- devlog 置顶 2026-08-25 条目
2026-08-25 16:48:52 +08:00

11 KiB
Raw Blame History

DLD154Pro 蓝牙小程序接口协议

依据源码整理:BLE/DLD154Pro_Peripheral_28K/APP/dbn_ble_srv.c(主逻辑)、peripheral.c/Profile/gattprofile.cBLE 服务)、include/storage.h(配置结构)、include/cmcng.h(常量) 固件版本:V3.03cmcng.h FIRMWARE_VER)| 硬件版本:V3.01 | 产品型号:DLD154Pro


1. BLE 服务与特征

服务/特征 UUID 属性 长度 用途
服务 SIMPLEPROFILE 0xFFE0 广播服务 UUID
Char1 0xFFE1 读写 (RW) 64B 小程序 → 芯片:命令下发
Char2 0xFFE2 1B 预留
Char3 0xFFE3 8B 预留
Char4 0xFFE4 通知 (Notify) 32B 芯片 → 小程序:命令响应 + 主动上报
Char5 0xFFE5 5B 预留
  • 设备名:DLD154Pro(广播 + GATT Device Name
  • MTU:默认 23,连接后协商(ATT_MTU_UPDATED_EVENTperipheralMTU = clientRxMTU)。notify 单包 payload ≤ peripheralMTU 3peripheral.c:677 强制检查,超限返回 FAIL 不发送)
  • 交互模型:小程序写 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(高 4 位总包数,低 4 位当前序号,seq 从 1 起)
Len 1CMD+ NData 字节数)
CMD 命令码,见 §4
XOR 异或校验:从 Header 到 Data 末尾逐字节 XOR
SUM 和校验:从 Header 到 Data 末尾逐字节求和(低 8 位)

校验示例compute_ckbdbn_ble_srv.c:168):

dxor = Header ^ Len ^ CMD ^ Data[0] ^ ... ^ Data[N-1];
dsum = Header + Len + CMD + Data[0] + ... + Data[N-1];  // 取低 8 位
// 发送顺序: [dxor] [dsum & 0xFF]

接收校验check_pkgdbn_ble_srv.c:75):最小帧长 6Len + 5 < 实际长度 判非法;XOR/SUM 任一不符丢弃。


3. 分包机制

  • 发送(响应/上报)set_response_buf()MAX_BLE_DAT_RESPONSE_LEN = 14= BLE_BUFF_MAX_LEN4,基于 MTU=23 的旧假设)计算 pkg_amount = ceil(dat_len / 14)。多包时 Header = (amount<<4)|seqseq 从 1 递增,最后一包 amount == seq 后清除响应缓冲。
  • 接收(命令)unpack_packs() 支持按 (amount<<4)|seq 重组分包,校验 amount/cmd/seq 连续性,异常时清空缓冲。DLD154Pro 当前仅 0x1C/0x1D 使用(已注释),其余命令单包即可。
  • ⚠ 分包粒度写死 14:即使 MTU 协商到更大(如 96/185),分包仍按 14B 切——不丢包但效率低。小程序侧按 Header 分包重组即可。

4. 命令总览

CMD 名称 方向 说明
0x10 GET_DEV_INFO 小程序→芯片 读设备信息(MAC/版本/型号)
0x1F RESET_DEV 小程序→芯片 复位设备(SYS_ResetExecute
0x23 SET_CJQ_PARAM 小程序→芯片 设置车检器参数(灵敏度/频率/延时/输出等)
0x24 GET_CJQ_PARAM 小程序→芯片 读车检器参数
0x31 RW_UART_BAUD 小程序→芯片 读写 RS485 波特率/地址/蓝牙空闲超时
0x8A LOOP_SENS_LIST 小程序→芯片 读写灵敏度表(sens_in/sens_out
0x92 SET_CJQ_FACTORY 小程序→芯片 恢复出厂
0xC5 SENS_ACS_ENABLE 小程序→芯片 主动上报使能
0xC0 SUB_SENS_REPORT 芯片→小程序 主动上报线圈动态(不可下发)

未实现(源码已注释)0x1C 校验密码 / 0x1D 修改密码 / 0x1E 出厂 / 0x20-0x22 notify 与子功能 / 0x6D 复位 / 0x87 采样参数 / 0x88 平衡参数 / 0x89 释放参数。小程序不应下发,芯片无响应。


5. 命令详述

5.1 0x10 读设备信息

无 Data。响应 Data

偏移 字节 内容
0-5 6 MAC 地址(MACAddr[6]
6-7 2 硬件版本 MAIN/SUBV3.01 → 03 01
8-9 2 固件版本 MAIN/SUBV3.03 → 03 03
10 1 产品型号长度
11.. N 产品型号 ASCII"DLD154Pro"
.. 6 设备编号(g_dev_number[6]
.. 2 sub_code(固定 0
.. 2 总线设备数(固定 0

5.2 0x1F 复位设备

无 Data。芯片执行 SYS_ResetExecute()(整机冷复位),无响应帧

5.3 0x23 设置车检器参数

Data5B):

偏移 内容
0 sensitvity(低4位) | loopFreq_Level(高4位)
1 delay_time(离开延时)
2 output_mode(低2位) | loopSafe_Timeout(高5位)
3 exist_mode(有限存在时长,单位 10s)
4 direction_mode(低 4 位=输出融合模式;高 4 位=功能模式)

sensitvity 语义(DLD154Pro 特有):协议层 1~41=最低灵敏度,4=最高),内部 g_freq_sens = sensitvity 103)索引灵敏度表。与 vd960Loop 的 03 不同,小程序发送 1~4

direction_mode 解析unpack_pkg_set_cjq_paramdbn_ble_srv.c:431):

g_function_mode     = direction_mode >> 4        (功能模式)
g_fm_700bs_disable  = g_function_mode & 0x01     (0=700BS协议, 1=Modbus)
g_output_radar_mode = direction_mode & 0x0F       (输出融合模式, 见 DLD_OUTPUT_MODE)
g_hold_time         = exist_mode * 20 * 5         (tick)

处理:更新全局 → write_cfg_to_store(4, tmp, 7) 写 flash → para_store_init() 重载。响应:1B status(固定 0)。

5.4 0x24 读车检器参数

无 Data。响应 Data8B):

偏移 内容
0 (g_freq_sens + 1) | (loopFreq_Level << 4)sensitvity 回读为 1~4
1 delay_time
2 output_mode | (loopSafe_Timeout << 3)
3 exist_mode
4 sens_list.total << 4(灵敏度档数,高 4 位)
5 线圈断开次数低字节(g_loop_cut_amount
6 线圈断开次数高字节
7 direction_mode

5.5 0x31 读写 UART 参数

Data[rw] [status] ...

读(rw=0:响应 Data8B):

[0] rw=0
[1] status=0
[2] 蓝牙空闲超时(分钟, g_max_counter_bt_min)
[3-5] RS485 波特率 3B LE (g_storage_uart_baud)
[6] RS485 从机地址 (g_rs485_id)
[7-9] Reserved 3B

写(rw≠0Data 后续:[bt_timeout] [baud 3B LE] [rs485_id] [3B reserved],共 5B 有效写入 write_cfg_to_store(0x10, 5B)。响应回读当前值(同读格式)。

5.6 0x8A 读写灵敏度表

读(pkg[4]=0:响应 Data

[0] 0x10 (读标志)
[1] total (灵敏度档数)
[2..] total × [sens_in 2B LE | sens_out 2B LE]

写(pkg[4]≠0Data 从 pkg[5] 起:[total] [sens0_in LE2 | sens0_out LE2] [sens1...]。写 flash Addr_Loop_Sens_List_Offset(0x20) + para_store_init() 重载。注意:写路径不直接改 RAM 的 g_loop_sens_list,依赖 para_store_init 从 flash 重读生效

出厂默认 4 档(storage.c):{108,54,28,14}sens_in/ {81,32,16,12}sens_out,滞回 ~75/59/57/86%)。

5.7 0x92 恢复出厂

无 Data。执行 set_factory_param() + factory_dev() → flash 重写出厂配置 → para_store_init() 重载。响应:1B status=0。

5.8 0xC5 主动上报使能

Data[enable] [interval] [timeout_min]

  • enable1=开启,0=关闭
  • interval:上报间隔系数,实际 interval × 0x7F127
  • timeout_min:超时分钟数(0=不限时)

处理(dbn_ble_srv.c:830):开启时 timeout_counter = timeout_min × 60 × 100源码 TODO 标注 min→ms60×100=6000 疑应为 60000,若按 6000 则实际超时 = timeout_min 分钟 ÷ 10,注意现场验证)。关闭时 flag=0。


6. 主动上报 0xC0(芯片 → 小程序)

组包:usart_packet_processing_acs_loop()dbn_ble_srv.c:452),type = 5SENS_LOOP_DYNAMIC)。

偏移 字节 内容
0 1 0x05SENS_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 线圈断开次数(LEpower_up_state==0 时为 1
7-9 3 实际频率(LEfreq = sclk_freq/CAPVD×LPCNT + 360 补偿)
10-12 3 variation 变化量(3B 有符号补码 LE,正=车/金属进入方向)

触发条件report_sens_acsdbn_ble_srv.c:531):

  • 事件:flag_event 置位(车进出等事件)立即上报
  • 周期:report_counter >= 120 周期上报(120 × 50ms ≈ 6s
  • 前提:g_dbn_ble_state_acs_enable.enable == 10xC5 开启)

variation 接收端注意:int32_t 截断 3B,负值需符号扩展(if (v & 0x800000) v |= 0xFF000000),与 vd960Loop V1.05 同口径。

condition:环境状态评估值 0~15g_env_activity/10,>150 取 15;线圈断开强制 15),值越大干扰越大。


7. 实现细节与坑(对照源码)

  1. sensitvity 14 vs 03DLD154Pro 协议层 14,内部 g_freq_sens = sensitvity-1。0x24 回读 +1。**与 vd960Loop03)不一致,小程序需按产品区分**
  2. 分包粒度 14B 写死MAX_BLE_DAT_RESPONSE_LEN = BLE_BUFF_MAX_LEN - 4 = 14(基于 MTU 23);MTU 协商更大后不重新分包——正确但低效
  3. 0xC5 超时疑似 bugtimeout_min × 60 × 100,若意图 ms 则应为 ×1000(待现场验证)
  4. 0x8A 写灵敏度表不直接更新 RAM:依赖 para_store_init() 重读 flash;写完立即读可能拿到旧值
  5. 0xC0 frequent +360 补偿_current_freq = freq_tmp + 360(经验补偿值,示波器标定用)
  6. 0x1F/0x1E 无响应:复位/出厂类命令执行后设备重启,小程序不应等待响应帧
  7. notify 超限静默丢弃peripheralChar4Notifylen > (peripheralMTU-3) 时返回 FAIL,不重发——长响应必须分包
  8. 密码命令未实现:0x1C/0x1D 已注释,小程序不应依赖加密鉴权

8. 交互示例

读取设备信息(无 DataLen=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][03 01][03 03][0A "DLD154Pro"][dev_no6][00 00][00 00] [XOR] [SUM]
      Len=0x10(16): CMD + 15B Data

设置灵敏度为 2 档(协议值 2

下发: 8F 00 06 23 20 00 00 00 00 [XOR] [SUM]
      Len=6: CMD(0x23)+Data5
      Data[0]=0x20: sensitvity=2(低4位) | freq_level=0(高4位)
      Data[1..4]=延时/输出/存在/方向模式