import can
from can import BLFWriter
import time
def create_canfd_message(arbitration_id, data, is_extended=False):
"""
创建 CAN FD 消息对象
:param arbitration_id: 消息ID
:param data: 字节列表或字节数组
:param is_extended: 是否使用扩展ID (29位)
:return: can.Message 对象
"""
return can.Message(
arbitration_id=arbitration_id,
data=data,
is_extended_id=is_extended,
is_fd=True, # 标记为 CAN FD 帧
bitrate_switch=True, # 启用数据段波特率切换
error_state_indicator=False
)
def pad_data_to_64bytes(initial_data):
"""
将数据填充到64字节,不足部分补0
:param initial_data: 初始数据列表
:return: 64字节的列表
"""
if len(initial_data) > 64:
raise ValueError("数据长度不能超过64字节")
# 复制初始数据并填充0到64字节
padded = initial_data.copy()
padded.extend([0x00] * (64 - len(padded)))
return padded
# 定义4条CAN FD消息的数据(按需求指定)
# 注意:这些数据需要填充到64字节
raw_messages = [
{
'id': 0x33A, # CAN ID: 33A
'data': [0x00, 0x11, 0x12, 0xFF, 0x00, 0x00, 0x00, 0x00] # 前8字节指定,其余补0
},
{
'id': 0x33A, # CAN ID: 33A
'data': [0x01, 0x33, 0x33, 0xFF, 0x00, 0x00, 0x00, 0x00]
},
{
'id': 0x33A, # CAN ID: 33A
'data': [0x00, 0xAA, 0xAB, 0x00, 0x00, 0x00, 0x00, 0x00]
},
{
'id': 0x33A, # CAN ID: 33A
'data': [0x01, 0xCC, 0xDD, 0x56, 0x00, 0x00, 0x00, 0x00]
}
]
# 将这4条消息的数据填充到64字节
prepared_messages = []
for raw in raw_messages:
padded_data = pad_data_to_64bytes(raw['data'])
msg = create_canfd_message(
arbitration_id=raw['id'],
data=padded_data
)
prepared_messages.append(msg)
print("准备写入的4条CAN FD消息(64字节):")
for i, msg in enumerate(prepared_messages, 1):
print(f"消息{i}: ID=0x{msg.arbitration_id:03X}, 数据={msg.data[:8]}... (共{len(msg.data)}字节)")
# 生成最终的消息列表:每条消息重复2000次
total_messages = []
REPEAT_COUNT = 2000
print(f"\n开始生成 {REPEAT_COUNT} 轮循环...")
for cycle in range(REPEAT_COUNT):
# 每条消息都带有一个递增的时间戳(模拟实时采集)
base_timestamp = time.time() + cycle * 0.04 # 每轮4条消息,每条间隔10ms,总共40ms一轮
for i, msg_template in enumerate(prepared_messages):
# 复制消息并添加时间戳
msg = can.Message(
arbitration_id=msg_template.arbitration_id,
data=msg_template.data.copy(), # 复制数据
is_extended_id=msg_template.is_extended_id,
is_fd=msg_template.is_fd,
bitrate_switch=msg_template.bitrate_switch,
error_state_indicator=msg_template.error_state_indicator,
timestamp=base_timestamp + i * 0.01 # 每条消息间隔10ms
)
total_messages.append(msg)
print(f"总共生成 {len(total_messages)} 条消息 (4条 × {REPEAT_COUNT}轮)")
# 写入BLF文件
print("正在写入BLF文件...")
output_filename = 'canfd_33a_2000cycles.blf'
with BLFWriter(output_filename) as writer:
for idx, msg in enumerate(total_messages):
writer.on_message_received(msg)
# 每1000条打印一次进度
if (idx + 1) % 1000 == 0:
print(f" 已写入 {idx + 1}/{len(total_messages)} 条消息")
print(f"\n✅ BLF文件生成成功!")
print(f"📁 文件名: {output_filename}")
print(f"📊 总消息数: {len(total_messages)} 条")
print(f"🔄 循环轮数: {REPEAT_COUNT} 轮")
print(f"📋 每轮4条CAN FD消息,ID均为0x33A,数据长度64字节")
# 可选:验证文件内容
print("\n🔍 验证文件内容(读取前10条消息)...")
from can import BLFReader
with BLFReader(output_filename) as reader:
count = 0
for msg in reader:
if count < 10:
print(f" [{count}] ID=0x{msg.arbitration_id:03X}, FD={msg.is_fd}, "
f"len={len(msg.data)}, time={msg.timestamp:.3f}, "
f"data={msg.data[:8]}... (共{len(msg.data)}字节)")
count += 1
if count >= 10:
break
print(f" 验证完成,文件共包含 {count} 条消息(仅显示前10条)")