Files
P4-USB-transfer/蓝牙指令测试文档.md
zhengxinandCursor 851e347cf5 初始提交卡包 USB 工程
纳入固件源码、屏幕组件、nand_xfer 工具和文档。忽略本机构建产物、sdkconfig,以及含本机路径的依赖锁。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-13 21:54:50 +08:00

337 lines
19 KiB
Markdown
Raw Permalink 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.
# 车机 & 机器人蓝牙指令测试文档
本文档用于蓝牙协议联调与测试。**所有完整帧中的 CRC16 均按下方计算规则得出**。
---
## 一、协议约定
### 1. 帧结构
| 字段 | 帧头 | 类(Cmd) | 指令 | 动作/参数 | 方向等 | CRC16 | 帧尾 |
|--------|------|---------|------|-----------|--------|-------|------|
| 长度 | 1 | 2 | 2 | 视指令 | 视指令 | 2 | 1 |
| 取值 | 0xAA | 大端 | 大端 | — | — | 见下节 | 0x55 |
### 2. CRC16 计算规则
与工程内 `main/ALGORITHM/crc.c` 中 `crc16_ccitt_calculate()` 行为一致,本文档中**所有完整帧的 CRC16 均按下列规则计算并填入**。
- **算法**:CRC16-CCITT
- **多项式**:0x1021
- **初始值**:0xFFFF
- **校验范围**:从**帧头(0xAA)到 CRC 前一字节**(不含 CRC 两字节、不含帧尾 0x55)
- **字节序**:CRC 结果 2 字节按**大端**填入帧(高字节在前,低字节在后)
- **无反转、无异或**:计算得到的 16 位值直接取高 8 位、低 8 位写入
**计算步骤**:从 0xFFFF 开始,按字节顺序对“校验范围”内每一字节做迭代:当前 CRC 高 8 位与数据字节异或后,若最高位为 1 则左移 1 位再异或 0x1021,否则仅左移 1 位;重复 8 位后得到更新后的 CRC。全部字节处理完后得到的 16 位值,高字节、低字节依次写入帧。
### 3. 方向 (direction)
| 值 | 含义 |
|-------|----------------|
| 0x00 | 电机无动作 |
| 0x01 | 电机转向主驾 |
| 0x02 | 电机转向副驾 |
| 0x03 | 电机转向后背 |
| 0x04 | 主驾+副驾 |
| 0x05 | 左后唤醒 |
| 0x06 | 右后唤醒 |
| 0x07 | 行驶中转头 180° |
### 4. 类 (Cmd)
- **0xFFFE**:车机下发指令 (Cmd)
- **0xFFFF**:机器人反馈 (Feedback)
---
## 二、指令类协议 (Play_stick, Cmd=0xFFFE, 指令=0x0001)
帧格式:`帧头(1) + 类(2) + 指令(2) + 动作Action_id(2) + 方向(1) + CRC16(2) + 帧尾(1)`
CRC16 按上述规则对前 8 字节计算。
### 2.1 无方向指令 (direction=0x00)
| 序号 | 指令名称 | Action_id | 完整帧 (十六进制,含 CRC16) |
|------|----------------|-----------|-----------------------------|
| 1.1 | 驾车出发 | 0x0001 | AA FF FE 00 01 00 01 00 D7 40 55 |
| 1.2 | 开始播放音乐 | 0x0002 | AA FF FE 00 01 00 02 00 82 13 55 |
| 1.3 | 暂停播放音乐 | 0x0003 | AA FF FE 00 01 00 03 00 B1 22 55 |
| 1.4 | 停止播放音乐 | 0x0004 | AA FF FE 00 01 00 04 00 28 B5 55 |
| 1.5 | 播放音乐中(表情 40%~75% 循环) | 0x0005 | AA FF FE 00 01 00 05 00 1B 84 55 |
| 1.6 | 冷风 | 0x0006 | AA FF FE 00 01 00 06 00 4E D7 55 |
| 1.7 | 暖风 | 0x0007 | AA FF FE 00 01 00 07 00 7D E6 55 |
| 1.8 | 打开窗户 | 0x0008 | AA FF FE 00 01 00 08 00 6D D8 55 |
| 1.9 | 开始充电 | 0x0009 | AA FF FE 00 01 00 09 00 5E E9 55 |
| 1.10 | 完成充电 | 0x000A | AA FF FE 00 01 00 0A 00 0B BA 55 |
| 1.11 | 接听电话 | 0x000B | AA FF FE 00 01 00 0B 00 38 8B 55 |
| 1.12 | 挂断电话 | 0x000C | AA FF FE 00 01 00 0C 00 A1 1C 55 |
| 1.13 | 开始导航 | 0x000D | AA FF FE 00 01 00 0D 00 92 2D 55 |
| 1.14 | 结束导航 | 0x000E | AA FF FE 00 01 00 0E 00 C7 7E 55 |
| 1.15 | 露营模式 | 0x000F | AA FF FE 00 01 00 0F 00 F4 4F 55 |
| 1.16 | 小憩模式 | 0x0010 | AA FF FE 00 01 00 10 00 E7 02 55 |
| 1.17 | 洗车模式 | 0x0011 | AA FF FE 00 01 00 11 00 D4 33 55 |
| 1.18 | 迎宾模式 | 0x0012 | AA FF FE 00 01 00 12 00 81 60 55 |
| 1.19 | 唤醒机器人 | 0x0013 | AA FF FE 00 01 00 13 00 B2 51 55 |
| 1.20 | 到达 | 0x0014 | AA FF FE 00 01 00 14 00 2B C6 55 |
| 1.21 | 哨兵模式guard | 0x0015 | AA FF FE 00 01 00 15 00 18 F7 55 |
| 1.22 | 哨兵模式protect| 0x0016 | AA FF FE 00 01 00 16 00 4D A4 55 |
| 1.23 | 冥想 | 0x0017 | AA FF FE 00 01 00 17 00 7E 95 55 |
| 1.24 | 星座 | 0x0018 | AA FF FE 00 01 00 18 00 6E AB 55 |
| 1.24 | 抽签 | 0x0019 | AA FF FE 00 01 00 19 00 5D 9A 55 |
电机微调代码
1.向主驾微调 | AA FF FE 00 01 00 00 11 E6 61 55|
1.向副驾微调 | AA FF FE 00 01 00 00 12 D6 02 55 |
### 2.2.1 带方向指令(direction 置 0x00 变体)
上述 2.2 中指令的**方向字节统一置为 0x00**(电机无动作)、并重新计算 CRC16 后的完整帧,便于测试“仅动作、不转向”场景。
| 序号 | 指令名称 | Action_id | direction | 完整帧 (十六进制,含 CRC16) |
|--------|--------------------|-----------|-----------|-----------------------------|
| 1.2.1 | 主驾唤醒 | 0x0020 | 0x00 | AA FF FE 00 01 00 20 00 E2 97 55 |
| 1.2.2 | 副驾唤醒 | 0x0021 | 0x00 | AA FF FE 00 01 00 21 00 D1 A6 55 |
| 1.2.3 | 主驾系安全带 | 0x0022 | 0x00 | AA FF FE 00 01 00 22 00 84 F5 55 |
| 1.2.4 | 副驾系安全带 | 0x0023 | 0x00 | AA FF FE 00 01 00 23 00 B7 C4 55 |
| 1.2.5 | 震惊(turn_to_back)| 0x0024 | 0x00 | AA FF FE 00 01 00 24 00 2E 53 55 |
| 1.2.6 | 查看后排 | 0x0025 | 0x00 | AA FF FE 00 01 00 25 00 1D 62 55 |
| 1.2.7 | 主驾开门 | 0x0026 | 0x00 | AA FF FE 00 01 00 26 00 48 31 55 |
| 1.2.8 | 副驾开门 | 0x0027 | 0x00 | AA FF FE 00 01 00 27 00 7B 00 55 |
| 1.2.9 | 全车开门 | 0x0028 | 0x00 | AA FF FE 00 01 00 28 00 6B 3E 55 |
| 1.2.10 | 主驾未系好安全带 | 0x0029 | 0x00 | AA FF FE 00 01 00 29 00 58 0F 55 |
| 1.2.11 | 副驾未系好安全带 | 0x002A | 0x00 | AA FF FE 00 01 00 2A 00 0D 5C 55 |
| 1.2.12 | 主驾开窗 | 0x002B | 0x00 | AA FF FE 00 01 00 2B 00 3E 6D 55 |
| 1.2.13 | 主驾制冷 | 0x002C | 0x00 | AA FF FE 00 01 00 2C 00 A7 FA 55 |
| 1.2.14 | 左后唤醒 | 0x002E | 0x00 | AA FF FE 00 01 00 2E 00 C1 98 55 |
| 1.2.15 | 右后唤醒 | 0x002F | 0x00 | AA FF FE 00 01 00 2F 00 F2 A9 55 |
| 1.2.16 | 行驶中转头 180° | 0x0030 | 0x00 | AA FF FE 00 01 00 30 00 E1 E4 55 |
| 1.2.17 | 主驾制热 | 0x002D | 0x00 | AA FF FE 00 01 00 2D 00 94 CB 55 |
### 2.2 带方向指令
| 序号 | 指令名称 | Action_id | direction | 完整帧 (十六进制,含 CRC16) |
|--------|--------------------|-----------|-----------|-----------------------------|
| 1.2.1 | 主驾唤醒 | 0x0020 | 0x01 | AA FF FE 00 01 00 20 01 F2 B6 55 |
| 1.2.2 | 副驾唤醒 | 0x0021 | 0x02 | AA FF FE 00 01 00 21 02 F1 E4 55 |
| 1.2.3 | 主驾系安全带 | 0x0022 | 0x01 | AA FF FE 00 01 00 22 01 94 D4 55 |
| 1.2.4 | 副驾系安全带 | 0x0023 | 0x02 | AA FF FE 00 01 00 23 02 97 86 55 |
| 1.2.5 | 震惊(turn_to_back)| 0x0024 | 0x03 | AA FF FE 00 01 00 24 03 1E 30 55 |
| 1.2.6 | 查看后排 | 0x0025 | 0x03 | AA FF FE 00 01 00 25 03 2D 01 55 |
| 1.2.7 | 主驾开门 | 0x0026 | 0x01 | AA FF FE 00 01 00 26 01 58 10 55 |
| 1.2.8 | 副驾开门 | 0x0027 | 0x02 | AA FF FE 00 01 00 27 02 5B 42 55 |
| 1.2.9 | 全车开门 | 0x0028 | 0x04 | AA FF FE 00 01 00 28 04 2B BA 55 |
| 1.2.10 | 主驾未系好安全带 | 0x0029 | 0x01 | AA FF FE 00 01 00 29 01 48 2E 55 |
| 1.2.11 | 副驾未系好安全带 | 0x002A | 0x02 | AA FF FE 00 01 00 2A 02 2D 1E 55 |
| 1.2.12 | 主驾开窗 | 0x002B | 0x01 | AA FF FE 00 01 00 2B 01 2E 4C 55 |
| 1.2.13 | 主驾制冷 | 0x002C | 0x01 | AA FF FE 00 01 00 2C 01 B7 DB 55 |
| 1.2.14 | 左后唤醒 | 0x002E | 0x05 | AA FF FE 00 01 00 2E 05 91 3D 55 |
| 1.2.15 | 右后唤醒 | 0x002F | 0x06 | AA FF FE 00 01 00 2F 06 92 6F 55 |
| 1.2.16 | 行驶中转头 180° | 0x0030 | 0x07 | AA FF FE 00 01 00 30 07 91 03 55 |
| 1.2.17 | 主驾制热 | 0x002D | 0x01 | AA FF FE 00 01 00 2D 01 84 EA 55 |
### 2.3 待机表情(随机待机表情包 action_id 0x0201-0x020A)
| 序号 | 指令名称 | Action_id | direction | 完整帧 (十六进制,含 CRC16) |
|--------|--------------------|-----------|-----------|-----------------------------|
| 1.2.513 | 左转弯 | 0x0201 | 0x09 | AA FF FE 00 01 02 01 09 28 09 55 |
| 1.2.514 | 右转弯 | 0x0202 | 0x08 | AA FF FE 00 01 02 02 08 6D 7B 55 |
| 1.2.515 | drink coffee | 0x0203 | 0x00 | AA FF FE 00 01 02 03 00 DF 42 55 |
| 1.2.516 | 急加速 | 0x0204 | 0x00 | AA FF FE 00 01 02 04 00 46 D5 55 |
| 1.2.517 | 眩晕 | 0x0205 | 0x00 | AA FF FE 00 01 02 05 00 75 E4 55 |
| 1.2.518 | 蜗牛 | 0x0206 | 0x00 | AA FF FE 00 01 02 06 00 20 B7 55 |
| 1.2.519 | 散金币 | 0x0207 | 0x00 | AA FF FE 00 01 02 07 00 13 86 55 |
| 1.2.520 | 唱歌 | 0x0208 | 0x00 | AA FF FE 00 01 02 08 00 03 B8 55 |
| 1.2.521 | 庆祝 | 0x0209 | 0x00 | AA FF FE 00 01 02 09 00 30 89 55 |
| 1.2.522 | 深呼吸/冷静 | 0x020A | 0x00 | AA FF FE 00 01 02 0A 00 65 DA 55 |
## 三、哨兵模式 (Cmd=0xFFFE, 指令=0x0002)
帧格式:`帧头(1) + 类(2) + 指令(2) + 动作Action_id(2) + CRC16(2) + 帧尾(1)`。CRC16 对前 8 字节计算。
- 进入哨兵后:**先显示 guard_emojo**,约 5s 后**持续播放 protect_emojo**,直到退出哨兵模式。
| 序号 | 指令名称 | Action_id | 完整帧 (十六进制,含 CRC16) |
|------|------------------|-----------|-----------------------------|
| 1.3.1 | 开启监听脉冲模式 | 0x0001 | AA FF FE 00 02 00 01 1D 8F 55 |
| 1.3.2 | 关闭监听脉冲模式 | 0x0002 | AA FF FE 00 02 00 02 2D EC 55 |
| 1.3.3 | 打开哨兵模式 | 0x0003 | AA FF FE 00 02 00 03 3D CD 55 |
| 1.3.4 | 关闭哨兵模式 | 0x0004 | AA FF FE 00 02 00 04 4D 2A 55 |
---
## 四、退出所有模式 (Cmd=0xFFFE, 指令=0x0003, Cancel_all_modes)
帧格式:`帧头(1) + 类(2) + 指令(2) + 动作 Action_id(2) + CRC16(2) + 帧尾(1)`。CRC16 对前 8 字节计算。
| 字段 | 帧头 | 类(Cmd) | 指令(Cancel_all_modes) | 动作(Action_id) | CRC16 | 帧尾 |
|--------|------|---------|-------------------------|------------------|-------|------|
| 长度 | 1 | 2 | 2 | 2 | 2 | 1 |
| 取值 | 0xAA | 0xFFFE | 0x0003 | 0x0000 | 3A 9E | 0x55 |
接收到**退出所有模式**指令后:**仅退出哨兵模式**,不处理持续播放音乐等其它持续运行表情。
| 序号 | 指令名称 | 完整帧 (十六进制,含 CRC16) |
|--------|------------|-----------------------------|
| 1.4.1 | 退出所有模式 | AA FF FE 00 03 00 00 3A 9E 55 |
---
## 五、调节屏幕亮度 (Cmd=0xFFFE, 指令=0x0004)
帧格式:`帧头(1) + 类(2) + 指令(2) + 亮度(2) + CRC16(2) + 帧尾(1)`。亮度 0~100,大端。CRC16 对前 8 字节计算。
| 示例 | 亮度值 | 完整帧 (十六进制,含 CRC16) |
|----------|--------|-----------------------------|
| 亮度 50 | 0x0032 | AA FF FE 00 04 00 32 A9 1F 55 |
| 亮度 0 | 0x0000 | AA FF FE 00 04 00 00 BF 0E 55 |
| 亮度 100 | 0x0064 | AA FF FE 00 04 00 64 93 2C 55 |
---
## 六、发送日期 (Cmd=0xFFFE, 指令=0x0005)
帧格式:`帧头(1) + 类(2) + 指令(2) + 年(2) + 月(1) + 日(1) + CRC16(2) + 帧尾(1)`。CRC16 对前 8 字节计算。
| 示例 | 年(2) | 月 | 日 | 完整帧 (十六进制,含 CRC16) |
|-------------|---------|------|------|-----------------------------|
| 2026-01-28 | 0x07EA | 0x01 | 0x1C | AA FF FE 00 05 07 EA 01 1C 93 FD 55 |
---
## 七、发送时间 (Cmd=0xFFFE, 指令=0x0006)
帧格式:`帧头(1) + 类(2) + 指令(2) + 时(1) + 分(1) + 秒(1) + CRC16(2) + 帧尾(1)`。CRC16 对前 8 字节计算。
| 示例 | 时 | 分 | 秒 | 完整帧 (十六进制,含 CRC16) |
|-----------|------|------|------|-----------------------------|
| 22:53:10 | 0x16 | 0x35 | 0x0A | AA FF FE 00 06 16 35 0A 1F B5 55 |
---
## 八、发送城市 (Cmd=0xFFFE, 指令=0x0007)
帧格式:`帧头(1) + 类(2) + 指令(2) + 城市名长度(2) + 城市名(UTF-8) + CRC16(2) + 帧尾(1)`。CRC16 校验范围为帧头到 CRC 前一字节(含城市名字节)。
| 示例 | 长度 | 城市名(UTF-8) | 完整帧说明 |
|--------|------|---------------|------------|
| 芜湖市 | 0x0009 | 9 字节 UTF-8 | AA FF FE 00 07 00 09 E8 8A 9C E6 B9 96 E5 B8 82 [CRC16 2 字节] 55(CRC 对前 6+9=15 字节计算) |
---
## 九、发送天气与温度 (Cmd=0xFFFE, 指令=0x0008)
帧格式:`帧头(1) + 类(2) + 指令(2) + 时机(1) + 温度(2) + 天气长度(2) + 天气(UTF-8) + CRC16(2) + 帧尾(1)`。CRC16 校验范围为帧头到 CRC 前一字节。
- 温度:Temp = 实际温度×10 + 1000(如 -4.3℃ → 957 → 0x03BD)。
- 时机:0x00=当前,0x01~0x06=1~6 小时后。
| 示例 | 时机 | 温度(2) | 天气 | 说明 |
|------------|------|---------|--------|------|
| 当前晴天 | 0x00 | 0x03BD | 晴天(6字节) | 帧头+类+指令+0x00+03 BD+00 03+E6 99 B4+[CRC16]+55,CRC 对前述全部数据计算 |
---
## 十、WiFi 配网 (Cmd=0xFFFE, 指令=0x0009)
帧格式:`帧头(1) + 类(2) + 指令(2) + Wifi_info(1) + 长度(2) + SSID/密码(x) + CRC16(2) + 帧尾(1)`。CRC16 校验范围:帧头到 CRC 前一字节(含可变长度数据)。
- **Wifi_info**:0x00=发送 SSID,0x01=发送密码。
- **长度**:2 字节大端,表示后续 SSID 或密码的字节数。
- 获取到 SSID 和密码并尝试连接后,**无论连上与否**,机器人都会通过 BLE 发送 **WiFi 状态反馈**(见下方 1.10_A)。
**示例:SSID = "11111111",密码 = "11111111"(各 8 字节)**
- 发 SSID:数据部分为 `00 00 08 31 31 31 31 31 31 31 31`,再计算 CRC16(对 AA FF FE 00 09 00 00 08 31 31 31 31 31 31 31 31 共 15 字节),填入 2 字节后加 55。
- 发密码:数据部分为 `01 00 08 31 31 31 31 31 31 31 31`,同样按 CRC16 规则计算后填入。
(31 31 31 31 31 31 31 31 为 ASCII "11111111")
**1.10_A 反馈:WiFi 状态(机器人发出)**
- 帧格式:`AA FF FF 00 10 [Wifi状态] [CRC16] 55`,CRC16 对前 6 字节计算。
- Wifi 状态:0x01=已连接,0x00=断开/未连上。连接尝试完成后会主动上报。
**WiFi 配网流程与目的**
1. **目的**:车机通过 BLE 把当前要连接的 WiFi 的 SSID 和密码下发给机器人,机器人尝试连接该热点;无论连上与否,都通过 1.10_A 把结果反馈给车机。
2. **流程**:车机先发 SSID 帧、再发密码帧;机器人收到后缓存,收齐后发起连接;连接结果通过 1.10_A 反馈。
3. **可变长度**:协议中“长度”为 x 的字段均由帧内“长度(2)”指定,x 不能为 0;解析时严格按 `帧长 = 固定头 + 长度字段值 + CRC + 帧尾` 校验。
---
## 十一、OTA / 表情包下载 (Cmd=0xFFFE)
CRC16 均按**校验范围从帧头到 CRC 前一字节**计算。
| 序号 | 指令名称 | 指令 | 说明 | 完整帧 (十六进制,含 CRC16) |
|--------|--------------|---------|------|-----------------------------|
| 1.11 | OTA_request | 0x000A | 无参数 | AA FF FE 00 0A 6F 7C 55 |
| 1.12 | 表情包下载 | 0x000B | Target_pack 2 字节,如 A=0x0041 | AA FF FE 00 0B 00 41 CB DA 55(下载 A 系列) |
| 1.13 | OTA_升级取消 | 0x000C | 无参数 | AA FF FE 00 0C 0F BA 55 |
1.13 帧格式:帧头(1)+类(2)+指令(2)+CRC16(2)+帧尾(1),共 8 字节。CRC16 对前 5 字节计算。
---
## 十二、车机查询 get_system_info (Cmd=0xFFFE, 指令=0x0010)
帧格式:帧头(1)+类(2)+指令(2)+CRC16(2)+帧尾(1)。CRC16 对前 5 字节计算。
| 序号 | 指令名称 | 完整帧 (十六进制,含 CRC16) |
|------|-------------------|-----------------------------|
| 2.1 | get_system_info | AA FF FE 00 10 DC 07 55 |
---
## 十三、表情包使用 (Cmd=0xFFFE, 指令=0x0020)
帧格式:帧头(1)+类(2)+指令(2)+op(1)+[可选 Target_pack 等]+CRC16(2)+帧尾(1)。CRC16 对帧头到 CRC 前一字节计算。
| 序号 | 操作 | 操作码 | 完整帧 (十六进制,含 CRC16) |
|--------|----------------|--------|-----------------------------|
| 3.1 | 查询已安装表情包 | 0x00 | AA FF FE 00 20 00 08 64 55 |
| 3.2 | 查询正在使用 | 0x01 | AA FF FE 00 20 01 18 45 55 |
| 3.3 | 切换到表情包 A | 0x02 + 0x41 | AA FF FE 00 20 02 41 DB 8F 55 |
| 3.4 | 删除指定的表情包 | 0x03 + Target_pack | 示例删除 A:AA FF FE 00 20 03 41 E8 BE 55 |
**3.4 删除表情包反馈 (Feedback 3.4)**:帧头(1)+类(0xFFFF)(2)+指令(0x0020)(2)+op(0x03)(1)+Exchange_result(1)+CRC16(2)+帧尾(1)=10 字节。Exchange_result:0x00 删除失败,0x01 删除成功。CRC16 对前 8 字节计算。
---
## 十四、机器人反馈帧 (Feedback, Cmd=0xFFFF)
机器人端回复的 CRC16 同样按 **CRC16-CCITT,初始 0xFFFF,多项式 0x1021**,校验范围从帧头到 CRC 前一字节,大端写入。
| 反馈类型 | 指令(2) | 说明 |
|----------------|---------|------|
| get_system_ok | 0x0004 | AA FF FF 00 04 01 [CRC16] 55 |
| brightness | 0x0005 | AA FF FF 00 05 [0-100] [CRC16] 55 |
| version | 0x0006 | AA FF FF 00 06 [长度(2)][版本号] [CRC16] 55 |
| WiFi 状态 | 0x0010 | AA FF FF 00 10 [0x00/0x01] [CRC16] 55 |
| OTA 结果 | 0x0001 | AA FF FF 00 01 [0x00/0x01] [CRC16] 55 |
| OTA 进度 | 0x0002 | AA FF FF 00 02 [0-100] [CRC16] 55 |
| 表情包下载结果 | 0x0003 | AA FF FF 00 03 [0x00/0x01] [CRC16] 55 |
| 表情包查询/切换 | 0x0020 | 按协议格式,CRC16 对帧头到 CRC 前一字节计算 |
| 表情包删除结果 (Feedback 3.4) | 0x0020 op=0x03 | 帧头+FFFF+0020+03+[0x00/0x01]+CRC16+55 |
---
## 十五、可变长度字段约定
协议中“长度”标为 **x** 的字段表示**由帧内“长度(2)”指定,且不能为 0**:
- 城市名、天气、SSID/密码等:均以帧内 2 字节大端“长度”为准,解析时用 `总帧长 = 固定头 + 长度值 + CRC(2) + 帧尾(1)` 校验,不假定固定 x。
- 代码中对 x=0 的帧会直接报错并丢弃。
## 十六、使用说明
1. **CRC16**:本文档中所有完整帧的 CRC16 均按**第一节“CRC16 计算规则”**对“帧头~CRC 前一字节”计算后填入(大端);与代码中 `crc16_ccitt_calculate()` 行为一致。
2. **校验**:接收端校验不通过则丢弃该帧,不执行后续处理。
3. 多字节字段均为**大端序**(高字节在前)。