|
|
@@ -9,16 +9,16 @@
|
|
|
- 标准 Modbus RTU 使用从机地址、功能码和 Modbus CRC。
|
|
|
- 存储访问协议使用 `CMD + ADDR + LEN + DATA + CRC16-CCITT-FALSE`。
|
|
|
- 复位使用 `bit6=1` 的特殊指令帧;当前仅定义复位特殊指令。
|
|
|
-- CodeInfo 同步先读取普通区域 `area=0x00` 的 codeinfo 描述符,再用 `addr32` 读取 TLV 信息块。
|
|
|
+- CodeInfo 同步先读取普通区域 `area=0x00` 的 codeinfo 描述符,再按描述符地址位宽读取 TLV 信息块。
|
|
|
|
|
|
## 2. 字节序与 CRC
|
|
|
|
|
|
-除 CRC 算法内部计算外,所有多字节协议控制字段均为大端序。当前目标内存变量的多字节值默认按大端解释和编辑。
|
|
|
+除 CRC 算法内部计算外,所有多字节协议控制字段均为小端序。目标内存变量的多字节值在 CodeInfo 同步后按 `ENDIAN_MARK` 自动选择大端或小端;未同步或未声明时默认小端。
|
|
|
|
|
|
```text
|
|
|
-32 位地址 : ADDR_3 ADDR_2 ADDR_1 ADDR_0
|
|
|
-16 位长度 : LEN_H LEN_L
|
|
|
-CRC 输出 : CRC_H CRC_L
|
|
|
+32 位地址 : ADDR_0 ADDR_1 ADDR_2 ADDR_3
|
|
|
+16 位长度 : LEN_L LEN_H
|
|
|
+CRC 输出 : CRC_L CRC_H
|
|
|
```
|
|
|
|
|
|
CRC 使用 `CRC16-CCITT-FALSE`:
|
|
|
@@ -30,7 +30,7 @@ CRC 使用 `CRC16-CCITT-FALSE`:
|
|
|
| 输入反转 | 否 |
|
|
|
| 输出反转 | 否 |
|
|
|
| 结果异或 | `0x0000` |
|
|
|
-| 输出顺序 | 高字节在前 |
|
|
|
+| 输出顺序 | 低字节在前 |
|
|
|
|
|
|
CRC 覆盖除最后两个 CRC 字节外的整帧内容。
|
|
|
|
|
|
@@ -92,8 +92,8 @@ bit2~bit0 AREA 普通读写区域码
|
|
|
### 5.1 读请求
|
|
|
|
|
|
```text
|
|
|
-MODE=0x07: CMD ADDR_3 ADDR_2 ADDR_1 ADDR_0 LEN_H LEN_L CRC_H CRC_L
|
|
|
-MODE=0x01..0x04: CMD ADDR_H ADDR_L LEN_H LEN_L CRC_H CRC_L
|
|
|
+AREA=0x07: CMD ADDR_0 ADDR_1 ADDR_2 ADDR_3 LEN_L LEN_H CRC_L CRC_H
|
|
|
+AREA=0x01..0x04: CMD ADDR_L ADDR_H LEN_L LEN_H CRC_L CRC_H
|
|
|
```
|
|
|
|
|
|
长度分别为 9 字节或 7 字节。
|
|
|
@@ -101,8 +101,8 @@ MODE=0x01..0x04: CMD ADDR_H ADDR_L LEN_H LEN_L CRC_H CRC_L
|
|
|
### 5.2 写请求
|
|
|
|
|
|
```text
|
|
|
-MODE=0x07: CMD ADDR_3 ADDR_2 ADDR_1 ADDR_0 LEN_H LEN_L DATA... CRC_H CRC_L
|
|
|
-MODE=0x01..0x04: CMD ADDR_H ADDR_L LEN_H LEN_L DATA... CRC_H CRC_L
|
|
|
+AREA=0x07: CMD ADDR_0 ADDR_1 ADDR_2 ADDR_3 LEN_L LEN_H DATA... CRC_L CRC_H
|
|
|
+AREA=0x01..0x04: CMD ADDR_L ADDR_H LEN_L LEN_H DATA... CRC_L CRC_H
|
|
|
```
|
|
|
|
|
|
长度分别为 `9 + LEN` 或 `7 + LEN` 字节。
|
|
|
@@ -110,8 +110,8 @@ MODE=0x01..0x04: CMD ADDR_H ADDR_L LEN_H LEN_L DATA... CRC_H CRC_L
|
|
|
### 5.3 正常读响应
|
|
|
|
|
|
```text
|
|
|
-MODE=0x07: CMD ADDR_3 ADDR_2 ADDR_1 ADDR_0 LEN_H LEN_L DATA... CRC_H CRC_L
|
|
|
-MODE=0x01..0x04: CMD ADDR_H ADDR_L LEN_H LEN_L DATA... CRC_H CRC_L
|
|
|
+AREA=0x07: CMD ADDR_0 ADDR_1 ADDR_2 ADDR_3 LEN_L LEN_H DATA... CRC_L CRC_H
|
|
|
+AREA=0x01..0x04: CMD ADDR_L ADDR_H LEN_L LEN_H DATA... CRC_L CRC_H
|
|
|
```
|
|
|
|
|
|
长度分别为 `9 + LEN` 或 `7 + LEN` 字节。
|
|
|
@@ -121,8 +121,8 @@ MODE=0x01..0x04: CMD ADDR_H ADDR_L LEN_H LEN_L DATA... CRC_H CRC_L
|
|
|
### 5.4 正常写响应
|
|
|
|
|
|
```text
|
|
|
-MODE=0x07: CMD ADDR_3 ADDR_2 ADDR_1 ADDR_0 LEN_H LEN_L CRC_H CRC_L
|
|
|
-MODE=0x01..0x03: CMD ADDR_H ADDR_L LEN_H LEN_L CRC_H CRC_L
|
|
|
+AREA=0x07: CMD ADDR_0 ADDR_1 ADDR_2 ADDR_3 LEN_L LEN_H CRC_L CRC_H
|
|
|
+AREA=0x01..0x04: CMD ADDR_L ADDR_H LEN_L LEN_H CRC_L CRC_H
|
|
|
```
|
|
|
|
|
|
长度分别为 9 字节或 7 字节。
|
|
|
@@ -132,7 +132,7 @@ MODE=0x01..0x03: CMD ADDR_H ADDR_L LEN_H LEN_L CRC_H CRC_L
|
|
|
### 5.5 异常响应
|
|
|
|
|
|
```text
|
|
|
-CMD_ERR EXCEPTION_CODE CRC_H CRC_L
|
|
|
+CMD_ERR EXCEPTION_CODE CRC_L CRC_H
|
|
|
```
|
|
|
|
|
|
长度固定 4 字节。`CMD_ERR` 为原请求 `CMD | 0x80`。
|
|
|
@@ -142,9 +142,9 @@ CMD_ERR EXCEPTION_CODE CRC_H CRC_L
|
|
|
特殊指令使用 `CMD bit6=1`,`bit0~bit5` 表示特殊指令码。当前仅定义 `0x01` 复位。
|
|
|
|
|
|
```text
|
|
|
-请求: CMD DATA... CRC_H CRC_L
|
|
|
-响应: CMD DATA... CRC_H CRC_L
|
|
|
-异常: CMD_ERR EXCEPTION_CODE CRC_H CRC_L
|
|
|
+请求: CMD DATA... CRC_L CRC_H
|
|
|
+响应: CMD DATA... CRC_L CRC_H
|
|
|
+异常: CMD_ERR EXCEPTION_CODE CRC_L CRC_H
|
|
|
```
|
|
|
|
|
|
特殊指令执行失败时直接返回异常帧,成功响应不额外携带状态字节。
|
|
|
@@ -174,7 +174,7 @@ CMD_ERR EXCEPTION_CODE CRC_H CRC_L
|
|
|
|
|
|
CodeInfo 同步分两步:
|
|
|
|
|
|
-1. 读取普通区域 `area=0x00 CODEINFO` 的描述符,响应 DATA 为 9 字节。
|
|
|
+1. 读取普通区域 `area=0x00 CODEINFO` 的描述符,响应 DATA 为 11 字节。
|
|
|
2. 按描述符返回的 TLV 起始地址、`len16`、地址位宽和最大包长,读取完整 CodeInfo TLV 信息块。
|
|
|
|
|
|
### 8.1 读取 CODEINFO 描述符
|
|
|
@@ -182,13 +182,13 @@ CodeInfo 同步分两步:
|
|
|
请求:
|
|
|
|
|
|
```text
|
|
|
-00 CRC_H CRC_L
|
|
|
+00 CRC_L CRC_H
|
|
|
```
|
|
|
|
|
|
从机成功响应:
|
|
|
|
|
|
```text
|
|
|
-00 TLV_ADDR_3 TLV_ADDR_2 TLV_ADDR_1 TLV_ADDR_0 TLV_LEN_H TLV_LEN_L ADDR_WIDTH MAX_PACKET_H MAX_PACKET_L CRC_H CRC_L
|
|
|
+00 TLV_ADDR_0 TLV_ADDR_1 TLV_ADDR_2 TLV_ADDR_3 TLV_LEN_L TLV_LEN_H ADDR_WIDTH MAX_PACKET_L MAX_PACKET_H ENDIAN_MARK_0 ENDIAN_MARK_1 CRC_L CRC_H
|
|
|
```
|
|
|
|
|
|
响应 DATA 字段:
|
|
|
@@ -199,8 +199,9 @@ CodeInfo 同步分两步:
|
|
|
| `TLV_LEN` | 2 | CodeInfo TLV 信息块的字节长度 |
|
|
|
| `ADDR_WIDTH` | 1 | 读取 CodeInfo 信息块本体时使用的地址位宽,只允许 `16` 或 `32` |
|
|
|
| `MAX_PACKET` | 2 | 从机允许的最大完整协议帧长度,包含 CMD/ADDR/LEN/DATA/CRC;为 0 表示未声明 |
|
|
|
+| `ENDIAN_MARK` | 2 | 目标内存值字节序标记;按字节读取为 `55 AA` 表示大端,`AA 55` 表示小端 |
|
|
|
|
|
|
-描述符区域 `CODEINFO` 只读,不支持写入。`CMD`、`ADDR`、普通读写 `LEN`、`TLV_LEN`、`MAX_PACKET` 等多字节协议控制字段始终按大端序解析;TLV `LEN` 为单字节字段,不涉及大小端。
|
|
|
+描述符区域 `CODEINFO` 只读,不支持写入。`CMD`、`ADDR`、普通读写 `LEN`、`TLV_LEN`、`MAX_PACKET`、固定内存入口 `byte_addr/byte_len` 等多字节协议控制字段始终按小端序解析;TLV `LEN` 与 `name_len` 为单字节字段,不涉及大小端。`ENDIAN_MARK` 不作为协议控制数值转换,而作为原始两字节同步标记:按字节读取为 `55 AA` 表示目标内存多字节值大端,`AA 55` 表示目标内存多字节值小端。
|
|
|
|
|
|
### 8.2 读取完整 CodeInfo
|
|
|
|
|
|
@@ -259,8 +260,8 @@ TYPE LEN VALUE...
|
|
|
|
|
|
| 字段 | 长度 | 说明 |
|
|
|
|---|---:|---|
|
|
|
-| `byte_addr` | 2 | 结构体实例或单独变量所在区域的字节地址 |
|
|
|
-| `byte_len` | 2 | 结构体实例或单独变量的字节长度 |
|
|
|
+| `byte_addr` | 2 | 结构体实例或单独变量所在区域的字节地址,小端序 |
|
|
|
+| `byte_len` | 2 | 结构体实例或单独变量的字节长度,小端序 |
|
|
|
| `name_len` | 1 | `name` 字节长度 |
|
|
|
| `name` | `name_len` | 动态名称字段,UTF-8 或 ASCII;结构体定义名、变量名或 enum 类型名 |
|
|
|
|
|
|
@@ -270,8 +271,8 @@ TYPE LEN VALUE...
|
|
|
|
|
|
| 字段 | 长度 | 说明 |
|
|
|
|---|---:|---|
|
|
|
-| `byte_addr` | 4 | 结构体实例或单独变量所在统一地址空间内的字节地址 |
|
|
|
-| `byte_len` | 2 | 结构体实例或单独变量的字节长度 |
|
|
|
+| `byte_addr` | 4 | 结构体实例或单独变量所在统一地址空间内的字节地址,小端序 |
|
|
|
+| `byte_len` | 2 | 结构体实例或单独变量的字节长度,小端序 |
|
|
|
| `name_len` | 1 | `name` 字节长度 |
|
|
|
| `name` | `name_len` | 动态名称字段,UTF-8 或 ASCII;结构体定义名、变量名或 enum 类型名 |
|
|
|
|
|
|
@@ -290,9 +291,9 @@ TYPE LEN VALUE...
|
|
|
| `0x40` | `cave_freq` | 1 | `uint8_t` | 载波频率,单位 KHz |
|
|
|
| `0x41` | `ref_volt` | 1 | `uint8_t` | 基准电压实际值乘 10,显示时除以 10,单位 V |
|
|
|
| `0x42` | `amp_gain` | 1 | `uint8_t` | 运放倍数,无单位 |
|
|
|
-| `0x43` | `rs_shunt` | 2 | `uint16_t` | 采样电阻,单位 mΩ |
|
|
|
-| `0x44` | `bus_div` | 4 | `float32` | 母线电压分压比,大端序 |
|
|
|
-| `0x45` | `along_div` | 4 | `float32` | 模拟输入电压分压比,大端序 |
|
|
|
+| `0x43` | `rs_shunt` | 2 | `uint16_t` | 采样电阻,单位 mΩ,按 `ENDIAN_MARK` 解析 |
|
|
|
+| `0x44` | `bus_div` | 4 | `float32` | 母线电压分压比,按 `ENDIAN_MARK` 解析 |
|
|
|
+| `0x45` | `along_div` | 4 | `float32` | 模拟输入电压分压比,按 `ENDIAN_MARK` 解析 |
|
|
|
| `0x46` | `chip_model` | 可变 | UTF-8 或 ASCII 字符串 | 芯片型号,建议 0 结尾或 0 填充 |
|
|
|
| `0x47` | `model` | 可变 | UTF-8 或 ASCII 字符串 | 电机型号,建议最多 30 字节,可容纳至少 7 个常见 UTF-8 汉字 |
|
|
|
|
|
|
@@ -305,7 +306,7 @@ TYPE LEN VALUE...
|
|
|
3. 遇到固定结构体入口 `TYPE=0x01/0x03/0x05/0x07` 创建结构体组;结构体定义未导入时按字节占位。
|
|
|
4. 遇到固定变量入口 `TYPE=0x02/0x04/0x06/0x08` 创建单独变量组,初始按 `byte_len` 显示原始字节并标记为未配置。
|
|
|
5. 按固定 TLV `TYPE` 解析内存区域和地址宽度。
|
|
|
-6. 当前目标内存多字节值默认按大端解释;单字节值不受影响。
|
|
|
+6. 根据描述符 `ENDIAN_MARK` 自动确定目标内存多字节值字节序:`55 AA` 为大端,`AA 55` 为小端;单字节值不受影响。
|
|
|
7. 根据 `byte_addr`、`byte_len`、`TYPE`、`name` 创建参数组。
|
|
|
8. 如果导入了 C 结构体和 enum 定义,只有结构体入口且 `name` 与结构体定义名一致、长度一致时才补全结构体字段;结构体字段类型为 enum 时,读回值按枚举项显示。
|
|
|
9. 单独变量入口需要在 UI 中选择与 `byte_len` 一致的有符号/无符号整数或 `float` 类型;如果 `name` 匹配 enum 类型名,或导入文件中存在 `EnumType variable_name;` 且变量名匹配 `name`,读回值按枚举项显示。
|
|
|
@@ -320,8 +321,8 @@ TYPE LEN VALUE...
|
|
|
AREA = 0x03 XDATA
|
|
|
ADDR = 0x2000
|
|
|
LEN = 0x0040
|
|
|
-读请求 = 03 20 00 00 40 CRC_H CRC_L
|
|
|
-正常响应 = 03 20 00 00 40 DATA(64B) CRC_H CRC_L
|
|
|
+读请求 = 03 00 20 40 00 CRC_L CRC_H
|
|
|
+正常响应 = 03 00 20 40 00 DATA(64B) CRC_L CRC_H
|
|
|
```
|
|
|
|
|
|
### 11.2 读取 CodeInfo
|
|
|
@@ -333,18 +334,19 @@ TLV_ADDR = 0x00123456
|
|
|
TLV_LEN = 0x0120
|
|
|
ADDR_WIDTH = 32
|
|
|
MAX_PACKET = 0x0040
|
|
|
+ENDIAN_MARK = AA 55
|
|
|
```
|
|
|
|
|
|
先读取 `CODEINFO` 描述符:
|
|
|
|
|
|
```text
|
|
|
-00 CRC_H CRC_L
|
|
|
+00 CRC_L CRC_H
|
|
|
```
|
|
|
|
|
|
再按 `ADDR_WIDTH=32` 读取 TLV 信息块:
|
|
|
|
|
|
```text
|
|
|
-07 00 12 34 56 01 20 CRC_H CRC_L
|
|
|
+07 56 34 12 00 20 01 CRC_L CRC_H
|
|
|
```
|
|
|
|
|
|
`0x07` 表示 32 位统一地址模式。
|
|
|
@@ -356,7 +358,7 @@ MAX_PACKET = 0x0040
|
|
|
```text
|
|
|
TYPE = 0x05
|
|
|
LEN = 0x14
|
|
|
-VALUE = 20 00 00 40 0F 4D 6F 74 6F 72 5F 52 75 6E 74 69 6D 65 5F 74
|
|
|
+VALUE = 00 20 40 00 0F 4D 6F 74 6F 72 5F 52 75 6E 74 69 6D 65 5F 74
|
|
|
含义 = XDATA 0x2000 / 64 bytes / Motor_Runtime_t
|
|
|
```
|
|
|
|
|
|
@@ -365,14 +367,14 @@ VALUE = 20 00 00 40 0F 4D 6F 74 6F 72 5F 52 75 6E 74 69 6D 65 5F 74
|
|
|
```text
|
|
|
TYPE = 0x08
|
|
|
LEN = 0x10
|
|
|
-VALUE = 00 00 21 00 00 02 09 73 70 65 65 64 5F 72 65 66
|
|
|
+VALUE = 00 21 00 00 02 00 09 73 70 65 65 64 5F 72 65 66
|
|
|
含义 = ADDR32 0x00002100 / 2 bytes / speed_ref
|
|
|
```
|
|
|
|
|
|
## 12. 实现约束
|
|
|
|
|
|
1. 普通内存读写帧的 `LEN` 单位始终为字节,字段固定 16 位,有效范围为 `1..0xFFFF`;CodeInfo TLV 项内的 `LEN` 为 1 字节,只表示单项 `VALUE` 长度。
|
|
|
-2. `ADDR` 单位始终为字节;`MODE=0x07` 时地址字段为 32 位,`MODE=0x01..0x04` 时地址字段为 16 位;`MODE=0x00` 为 CODEINFO 短描述符请求;`MODE=0x05..0x06` 保留。
|
|
|
+2. `ADDR` 单位始终为字节;`AREA=0x07` 时地址字段为 32 位,`AREA=0x01..0x04` 时地址字段为 16 位;`AREA=0x00` 为 CODEINFO 短描述符请求;`AREA=0x05..0x06` 保留。
|
|
|
3. 普通读写响应必须回显请求的 `CMD`、`ADDR`、`LEN`。
|
|
|
4. 上位机必须校验响应 `CMD`、`ADDR`、`LEN`、CRC,并确认数据长度等于 `LEN`。
|
|
|
5. `CODEINFO` 和 `CODE` 区只读,写入必须返回 `WRITE_PROTECT`。
|
|
|
@@ -398,4 +400,4 @@ VALUE = 00 00 21 00 00 02 09 73 70 65 65 64 5F 72 65 66
|
|
|
| `ADDR` | 4 字节 | typed 扩展建议使用 32 位字节地址 |
|
|
|
| `VALUE_WIDTH` | `0x01`、`0x02`、`0x04` | 单个值 8/16/32 位 |
|
|
|
| `COUNT` | 16 位 | 值数量,不是字节数 |
|
|
|
-| `DATA` | `VALUE_WIDTH * COUNT` 字节 | 按协议大端序 |
|
|
|
+| `DATA` | `VALUE_WIDTH * COUNT` 字节 | 按协议小端序 |
|