电机寄存器通信协议
本文说明如何通过 CAN 对 BXI 电机程序中的配置寄存器进行读取、写入、保存和信息查询。不同电机固件版本的寄存器表并不完全一致,操作前建议先确认电机的软件版本、硬件/程序型号和配置版本。
除特别说明外,本文中的 CAN ID、寄存器地址、数据字节和示例数值均使用十六进制。其他进制会单独标出。
1. 先确认版本
电机上电后会输出启动信息,可用 bxi_tool 查看,常见字段如下:
========== BOOT INFO ==========
STATE : 00 STARTUP
BUILD : Aug 31 2026 10:00:00
VER : code=1.4.1 config=1.4
CAN : id=1(boot)
---------- DEVICE CHECK ----------
HW : Bxi_motor_85
PRO : NORMAL
CON : same
| 字段 | 含义 |
|---|---|
VER code | 电机软件程序版本。 |
VER config | 电机配置内容版本,也就是寄存器表版本。也可以通过 CAN 读取 0x7C 获取。需要与软件版本对应。 |
CAN id | 当前电机节点 ID,后续 CAN 命令中的 node_id 使用这个值。默认使用 boot 的 ID,可通过寄存器修改 ID 来源。 |
HW | 电机硬件识别结果。 |
PRO | 当前编译目标/程序型号。 |
CON | 配置版本与程序版本是否匹配。 |
Note
软件版本的前两位需要与配置版本对应。例如软件版本 1.4.1 对应配置版本 1.4,软件版本 0.3.1 对应配置版本 0.3。CAN 寄存器接口目前直接公开的是配置版本 config_version,不是完整 code=x.y.z 软件版本。完整软件版本建议从启动信息、固件文件名或升级包信息确认。
2. CAN 命令格式
寄存器命令使用标准 CAN ID 的高位表示命令,低 4 位表示电机节点:
CAN ID = (cmd << 4) | node_id
例如电机 can_id = 1 时,读取寄存器命令 REG_READ 的 cmd = 0x17,其中 0x17 是十六进制。发送 CAN ID 为:
(0x17 << 4) | 0x01 = 0x171
| 命令 | cmd | node_id=1 时 CAN ID | DLC | 作用 |
|---|---|---|---|---|
REG_READ | 0x17 | 0x171 | 4 | 读取一个寄存器 |
REG_WRITE | 0x18 | 0x181 | 8 | 写入一个 RAM 寄存器 |
REG_SAVE | 0x19 | 0x191 | 0 | 保存 RAM 配置到 Flash |
REG_INFO | 0x1A | 0x1A1 | 0 | 查询当前公开寄存器数量 |
3. 读取的发送和解析
读取寄存器使用 REG_READ,cmd = 0x17。
3.1 发送帧
| 字段 | 内容 |
|---|---|
| CAN ID | 0x17 为十六进制命令号。左移 4 位后,将电机 node_id 合并到低 4 位 |
| DLC | 4 |
data[0..3] | address,寄存器地址,按 32 位小端格式发送,见文末“小端法解析说明”。地址通常用十六进制表示 |
CAN ID 由两部分组成:
高位:cmd << 4,其中 cmd 是十六进制命令号
低位:node_id,也就是电机当前 CAN id;node_id 占低 4 位
最终 CAN ID:(cmd << 4) | node_id
读取命令的 cmd 固定为十六进制 0x17,所以先得到命令高位:
0x17 << 4 = 0x170
再把电机节点 ID 合并到低 4 位。下表中的计算过程均为十六进制按位或:
电机 node_id | 十六进制节点值 | 计算过程 | 发送 CAN ID |
|---|---|---|---|
1 | 0x01 | 0x170 与 0x01 按位或 | 0x171 |
3 | 0x03 | 0x170 与 0x03 按位或 | 0x173 |
8 | 0x08 | 0x170 与 0x08 按位或 | 0x178 |
因此,电机节点不是 1 时,需要替换 CAN ID 的低 4 位。例如 node_id=3 时,读取命令 CAN ID 为 0x173。
3.2 回复解析
电机使用相同 CAN ID 回复,回复长度为 8 字节:
data[0..3] = status | (value_type << 8)
data[4..7] = value_raw
所有多字节字段均为小端,见文末“小端法解析说明”。
| 字段 | 解析方式 |
|---|---|
status | data[0],0 表示成功。 |
value_type | (data[1] & 0x07),表示 value_raw 的数据类型。 |
value_raw | data[4..7],按 value_type 解析为实际值。 |
status 含义:
status | 含义 |
|---|---|
0 | OK |
1 | 地址无效,或请求 header 保留位非 0 |
2 | 只读,或当前状态不允许写入 |
3 | 保存失败 |
4 | DLC 不足 |
5 | 写入类型不匹配 |
value_type 含义:
value_type | 解析方式 |
|---|---|
0 | int32_t,小端有符号整数,见文末“小端法解析说明” |
1 | bool,0=false,非 0 为 true |
2 | float,IEEE754 单精度浮点数 |
3 | uint32_t,小端无符号整数,见文末“小端法解析说明” |
4 | version,先按 uint32_t 读取,再按 major=(value>>8)&0xFF、minor=value&0xFF 解析 |
3.3 解析示例
读取 0x7C 后,如果收到:
171#0004000004010000
按字节拆开:
data[0..3] = 00 04 00 00
data[4..7] = 04 01 00 00
解析过程:
| 项目 | 结果 |
|---|---|
status | 0x00,成功 |
value_type | 0x04,版本号 |
value_raw | 0x00000104 |
| 配置版本 | major=1,minor=4,即 1.4 |
读取 0x60 后,如果收到:
171#0000000001000000
value_type=0 表示 int32_t,value_raw=0x00000001,说明当前 can_id = 1。
4. 写入的发送和解析
写入寄存器使用 REG_WRITE,cmd = 0x18。写入只修改 RAM 中的配置值;需要掉电保存时,还需要再发送 REG_SAVE。
4.1 发送帧
| 字段 | 内容 |
|---|---|
| CAN ID | 0x18 为十六进制命令号。左移 4 位后,将电机 node_id 合并到低 4 位 |
| DLC | 8 |
data[0..3] | address 与 value_type << 8 按位或,小端格式,见文末“小端法解析说明” |
data[4..7] | value_raw,按目标寄存器类型编码,小端格式,见文末“小端法解析说明” |
写入时 value_type 必须与目标寄存器表中的类型一致。bool 类型写入 0 表示关闭,写入非 0 表示开启;float 使用 IEEE754 单精度浮点数。
4.2 回复解析
写入成功或失败都会返回 8 字节回复:
data[0..3] = status | (value_type << 8)
data[4..7] = value_raw
status=0 表示写入成功。回复中的 value_type 为目标寄存器的实际类型;value_raw 为写入后该寄存器当前值。若 status=5,说明请求中的 value_type 与寄存器类型不匹配;若 status=2,说明该寄存器只读,或电机当前状态不允许写入。
5. 保存的发送和解析
保存配置使用 REG_SAVE,cmd = 0x19。它会把当前 RAM 配置写入 Flash。
5.1 发送帧
| 字段 | 内容 |
|---|---|
| CAN ID | 0x19 为十六进制命令号。左移 4 位后,将电机 node_id 合并到低 4 位 |
| DLC | 0 |
| Data | 空 |
5.2 回复解析
回复长度为 8 字节:
data[0..3] = status | (3 << 8)
data[4..7] = register_count
status=0 表示保存成功,status=3 表示保存失败。data[4..7] 为当前公开寄存器总数,按 uint32_t 小端解析,见文末“小端法解析说明”。
6. 信息查询的发送和解析
查询寄存器数量使用 REG_INFO,cmd = 0x1A。上位机需要适配不同固件时,建议先查询 REG_INFO,再根据 0x7C 配置版本选择对应寄存器表。
6.1 发送帧
| 字段 | 内容 |
|---|---|
| CAN ID | 0x1A 为十六进制命令号。左移 4 位后,将电机 node_id 合并到低 4 位 |
| DLC | 0 |
| Data | 空 |
6.2 回复解析
回复长度为 8 字节:
data[0..3] = status | (3 << 8)
data[4..7] = (writable_count << 16) | register_count
其中 value_type=3,表示 value_raw 按 uint32_t 解析。例如 value_raw = 0x00280036 表示公开寄存器总数为 0x0036 = 54,可写寄存器数量为 0x0028 = 40。
7. 版本差异与寄存器表选择
本文只说明寄存器命令的发送和解析方式,不展开具体寄存器表。不同程序版本的寄存器表会单独给出,使用时应先确认电机当前配置版本,再查找对应版本的寄存器表。
查找寄存器表时,建议按下面顺序确认:
- 从启动信息读取
VER code和VER config。 - 也可以通过 CAN 读取
0x7C,确认当前config_version。 - 使用与
VER config一致的寄存器表。例如软件版本1.4.1使用 1.4.1 寄存器表,软件版本0.3.1使用 0.3.1 寄存器表。 - 如需做上位机自动适配,可先发送
REG_INFO查询公开寄存器数量,再结合0x7C的配置版本选择对应寄存器表。
Warning
不同程序版本的寄存器表会变化。上位机不要只根据地址硬编码全部参数,应先确认配置版本,并使用对应版本的寄存器表。
8. 小端法解析说明
小端法是多字节数据的排列方式:低位字节放在低地址,也就是先发送低字节,再发送高字节。本文的寄存器地址、status | (value_type << 8)、value_raw 都按小端法发送和解析。
以 32 位数据 0x0000007C 为例,按小端法发送时字节顺序为:
7C 00 00 00
因此读取寄存器 0x7C 时,data[0..3] 写成:
data[0] = 0x7C
data[1] = 0x00
data[2] = 0x00
data[3] = 0x00
再以回复中的 value_raw 为例,如果 data[4..7] 为:
04 01 00 00
按小端法还原为 32 位值:
value_raw = 0x00000104
如果该字段的 value_type=4,表示版本号,则解析为:
major = (value_raw >> 8) & 0xFF = 1
minor = value_raw & 0xFF = 4
配置版本 = 1.4
不同 value_type 的最终解释方式不同:int32_t 按有符号整数解析,uint32_t 按无符号整数解析,float 按 IEEE754 单精度浮点数解析,version 按上面的版本号规则解析。