USB 转 CAN
协议说明
模式 |
模式切换 |
适用场景 |
USB 发送协议(USB->CAN) |
USB 接收协议(CAN->USB) |
|---|---|---|---|---|
透传模式(CAN 扩展帧) |
AT+ET |
使用 CAN 扩展帧 |
固定帧头 2 字节(0x45 0x54)+ CANID 扩展帧 4 字节 + 数据帧 8 字节 + 固定帧尾 2 字节(0x0D 0x0A) |
固定帧头 2 字节(0x45 0x54)+ CANID 扩展帧 4 字节 + 数据帧 8 字节 + 固定帧尾 2 字节(0x0D 0x0A) |
透传模式(CAN 标准帧,固件 V4.1+) |
AT+ET |
使用 CAN 标准帧 |
固定帧头 2 字节(0x53 0x54)+ 固定 2 字节(0x00 0x00)+ CANID 标准帧 2 字节 + 数据帧 8 字节 + 固定帧尾 2 字节(0x0D 0x0A) |
固定帧头 2 字节(0x53 0x54)+ 固定 2 字节(0x00 0x00)+ CANID 标准帧 2 字节 + 数据帧 8 字节 + 固定帧尾 2 字节(0x0D 0x0A) |
高级模式 |
AT+AT |
同时支持 CAN 标准帧、扩展帧,支持可变数据长度 |
固定帧头 2 字节(0x41 0x54)+ 帧标识符 4 字节 + 帧数据长度 1 字节 + 帧数据最大 8 字节 + 固定帧尾 2 字节(0x0D 0x0A) |
固定帧头 2 字节(0x41 0x54)+ 帧标识符 4 字节 + 帧数据长度 1 字节 + 帧数据最大 8 字节 + 固定帧尾 2 字节(0x0D 0x0A) |
查询固件版本:发送
AT+VER。开发板每次上电后默认切换为透传模式。
手动切换透传模式:发送
AT+ET。手动切换高级模式:发送
AT+AT。
示例代码
Python 样例代码,下载地址:test_usb2can.py
高级模式样例
发送数据前请先发送 AT+AT 切换到高级模式。
固定帧头(2 字节) |
帧标识符(4 字节) |
帧数据长度(1 字节) |
帧数据(最大 8 字节) |
固定帧尾部(2 字节) |
|---|---|---|---|---|
0x41 0x54 |
0x00 0x00 0x00 0x00 |
0x08 |
0x48 0x45 0x4C 0x4F 0x01 0x02 0x03 0x04 |
0x0D 0x0A |
帧标识符总共 4 字节(32 位),位段如下:
Bit31-Bit21 |
Bit20-Bit3 |
Bit2 |
Bit1 |
Bit0 |
|---|---|---|---|---|
CAN 标准帧 ID 或扩展帧 ID 前 11 位 |
CAN 扩展帧 ID 后 18 位 |
1=扩展帧,0=标准帧 |
1=远程帧,0=数据帧 |
固定为 0 |
# USB 转 CAN 测试工具使用方法
pip3 install pyserial
python3 test_usb2can.py
# CAN 标准帧 代码样例
# 先发送 AT+AT 切换到高级模式
std_can_id = 0x142
rtr_bit = 0
frame_id_val = (std_can_id << 21) | (rtr_bit << 1) | (0 << 2)
frame_id_bytes = frame_id_val.to_bytes(4, "big")
dlc = 8
data_bytes = bytes([0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00])
payload = b"\x41\x54" + frame_id_bytes + bytes([dlc]) + data_bytes[:dlc] + b"\x0D\x0A"
# 接收解析(标准帧)
frame_id_val = int.from_bytes(frame_id_bytes, "big")
ide_bit = (frame_id_val >> 2) & 0x01
rtr_bit = (frame_id_val >> 1) & 0x01
std_can_id = (frame_id_val >> 21) & 0x7FF
# CAN 扩展帧 代码样例
ext_can_id = 0x0000FD01
rtr_bit = 0
frame_id_val = (ext_can_id << 3) | (rtr_bit << 1) | (1 << 2)
frame_id_bytes = frame_id_val.to_bytes(4, "big")
dlc = 8
data_bytes = bytes([0x00] * 8)
payload = b"\x41\x54" + frame_id_bytes + bytes([dlc]) + data_bytes[:dlc] + b"\x0D\x0A"
# 接收解析(扩展帧)
frame_id_val = int.from_bytes(frame_id_bytes, "big")
ide_bit = (frame_id_val >> 2) & 0x01
rtr_bit = (frame_id_val >> 1) & 0x01
ext_can_id = (frame_id_val >> 3) & 0x1FFFFFFF