Python使用CAN总线传输超8字节数据时DLC报错求助
CAN FD周期消息发送报错(XL_ERR_INVALID_DLC/IndexError)解决方法
问题场景
使用cantools工具解析DBC,通过Vector CANalyzer建立CAN FD总线连接,发送周期CAN FD消息时:
- 当DLC大于8时,触发
XL_ERR_INVALID_DLC错误(错误码513) - 当data长度超过8字节时,触发
IndexError
原始代码
can_bus = can.interface.Bus(channel='0',bitrate=500000, bustype='vector' ,app_name='CANalyzer',data_bitrate=2000000) can_bus2 = can.interface.Bus(channel='0',bitrate=500000,bustype='vector',app_name='CANalyzer',data_bitrate=2000000) for i,j in zip(ggg,dlcs): example_messages = db.get_message_by_frame_id(i) message = can.Message(arbitration_id=example_messages.frame_id,is_rx=False,data=[1,2,3,4,5,6,7,8],is_extended_id = True,dlc=int(j),is_fd=True,bitrate_switch=True) #can_bus.send(message) ##send single messages can_bus.send_periodic(message,0.100,30,True) # /send periodic messages example_message = can_bus2.recv(3) #/recieve messages
报错信息
DLC大于8时的报错
Traceback (most recent call last): File "C:\Users\AppData\Local\Programs\Python\Python310\lib\site-packages\can\broadcastmanager.py", line 281, in _run self.bus.send(self.messages[msg_index]) File "C:\Users\AppData\Local\Programs\Python\Python310\lib\site-packages\can\interfaces\vector\canlib.py", line 536, in send self._send_sequence([msg]) File "C:\Users\AppData\Local\Programs\Python\Python310\lib\site-packages\can\interfaces\vector\canlib.py", line 543, in _send_sequence return self._send_can_msg_sequence(msgs) File "C:\Users\AppData\Local\Programs\Python\Python310\lib\site-packages\can\interfaces\vector\canlib.py", line 560, in _send_can_msg_sequence self.xldriver.xlCanTransmit( File "C:\Users\AppData\Local\Programs\Python\Python310\lib\site-packages\can\interfaces\vector\xldriver.py", line 37, in check_status_operation raise VectorOperationError( can.interfaces.vector.exceptions.VectorOperationError: xlCanTransmit failed (XL_ERR_INVALID_DLC) [Error Code 513] xlCanTransmit failed (XL_ERR_INVALID_DLC) [Error Code 513]
data长度超过8字节时的报错
Traceback (most recent call last): File "C:\Users\AppData\Local\Programs\Python\Python310\lib\site-packages\can\broadcastmanager.py", line 281, in _run self.bus.send(self.messages[msg_index]) File "C:\Users\AppData\Local\Programs\Python\Python310\lib\site-packages\can\interfaces\vector\canlib.py", line 536, in send self._send_sequence([msg]) File "C:\Users\AppData\Local\Programs\Python\Python310\lib\site-packages\can\interfaces\vector\canlib.py", line 543, in _send_sequence return self._send_can_msg_sequence(msgs) File "C:\Users\AppData\Local\Programs\Python\Python310\lib\site-packages\can\interfaces\vector\canlib.py", line 556, in _send_can_msg_sequence xl_event_array = (xlclass.XLevent * message_count.value)( File "C:\Users\AppData\Local\Programs\Python\Python310\lib\site-packages\can\interfaces\vector\canlib.py", line 580, in _build_xl_event xl_event.tagData.msg.data = tuple(msg.data) RuntimeError: (c_ubyte_Array_8) <class 'IndexError'>: invalid index (c_ubyte_Array_8) <class 'IndexError'>: invalid index
问题根源
- CAN FD DLC规范不匹配:CAN FD的DLC值与数据长度并非直接相等,比如DLC=9对应12字节、DLC=10对应16字节,手动设置的DLC不符合规范会触发
XL_ERR_INVALID_DLC - 接口未正确启用CAN FD模式:Vector底层接口默认使用CAN帧的8字节数据数组,未启用FD模式时无法处理超过8字节的数据,导致
IndexError - BroadcastManager兼容性问题:旧版本python-can的BroadcastManager对CAN FD周期消息支持不完善
解决步骤
1. 确保总线初始化正确启用CAN FD
初始化总线时显式指定fd=True,同时确认CANalyzer已配置为CAN FD模式(仲裁波特率500k,数据波特率2000k)
2. 严格遵循CAN FD DLC映射规范
CAN FD的DLC与数据长度映射表:
| DLC | 数据长度(字节) |
|---|---|
| 0-8 | 0-8 |
| 9 | 12 |
| 10 | 16 |
| 11 | 20 |
| 12 | 24 |
| 13 | 32 |
| 14 | 48 |
| 15 | 64 |
发送消息时必须保证data长度与DLC对应,或直接由python-can自动推导DLC(不手动指定dlc参数)
3. 修正代码实现
import can import cantools import time # 加载DBC文件(替换为你的DBC路径) db = cantools.database.load_file("your_dbc_file.dbc") # 初始化CAN FD总线(单实例即可,无需重复创建) can_bus = can.interface.Bus( channel='0', bitrate=500000, bustype='vector', app_name='CANalyzer', data_bitrate=2000000, fd=True # 显式启用CAN FD模式 ) # CAN FD DLC到数据长度的映射 FD_DLC_MAP = {0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:12,10:16,11:20,12:24,13:32,14:48,15:64} for msg_id, dlc in zip(ggg, dlcs): message_def = db.get_message_by_frame_id(msg_id) # 根据DLC获取合法的数据长度 data_len = FD_DLC_MAP.get(dlc, 8) # 生成对应长度的测试数据 data = list(range(data_len)) if data_len <= 64 else list(range(64)) # 创建CAN FD消息 message = can.Message( arbitration_id=message_def.frame_id, is_rx=False, data=data, is_extended_id=True, dlc=dlc, # 使用符合规范的DLC is_fd=True, bitrate_switch=True ) try: # 尝试发送周期消息 periodic_task = can_bus.send_periodic(message, 0.1, 30, True) # 接收测试 recv_msg = can_bus.recv(3) if recv_msg: print(f"收到消息: ID={hex(recv_msg.arbitration_id)}, 数据={recv_msg.data}") periodic_task.stop() except Exception as e: # 兼容性 fallback:手动循环发送 print(f"周期发送失败,切换手动发送: {str(e)}") for _ in range(30): can_bus.send(message) recv_msg = can_bus.recv(0.1) if recv_msg: print(f"收到消息: ID={hex(recv_msg.arbitration_id)}, 数据={recv_msg.data}") time.sleep(0.1)
4. 版本适配
- 确保python-can版本 >= 4.0,旧版本对Vector CAN FD的支持存在缺陷
- 升级Vector CAN驱动到最新版本,保证底层接口支持CAN FD
内容的提问来源于stack exchange,提问作者Lakshmi Srikanta
相关产品推荐
相关产品推荐

