当前位置:首页>python>Python控制周立功CAN卡教程|读取CAN总线消息,一键保存为BLF文件(附完整可运行代码)

Python控制周立功CAN卡教程|读取CAN总线消息,一键保存为BLF文件(附完整可运行代码)

  • 2026-09-03 14:28:33
Python控制周立功CAN卡教程|读取CAN总线消息,一键保存为BLF文件(附完整可运行代码)
之前的文章介绍了CAN总线数据BLF文件的保存和读取。这里我们实际接上周立功CAN卡来测试下完整流程。Python控制周立功CAN卡USBCANFD-200U,实时接收总线报文,保存到BLF文件。

一、Python控制周立功USBCANFD卡前置准备

核心前提:确保周立功USBCANFD卡硬件、ZLG CAN驱动、Python环境三者匹配,这是Python代码能正常控制USBCANFD卡、读取CAN/CANFD总线消息的基础,缺一不可!

1. 硬件准备(适配周立功USBCANFD主流型号)

适配周立功主流USBCANFD卡型号(如:USBCANFD-200U、USBCANFD-400U、USBCANFD-800U),确保周立功USBCANFD卡正常连接电脑,CAN总线接线正确(CAN_H、CAN_L对应接好,终端电阻按需添加),避免影响Python读取CAN/CANFD总线消息。

2. ZLG CAN驱动安装

安装周立功官方ZLG CAN驱动,安装完成后打开“CAN测试工具”,确认能正常识别周立功USBCANFD卡、读取CAN/CANFD总线消息,避免因驱动缺失或版本不兼容导致Python无法调用zlgcan库控制USBCANFD卡。
✅ 驱动下载路径:周立功官网 → 技术支持 → 驱动下载 → 搜索对应USBCANFD卡型号(建议安装最新稳定版,避免兼容问题,确保Python能正常调用USBCANFD卡)。

3. Python环境配置(适配USBCANFD卡控制+BLF文件保存)

需安装2个核心依赖库(直接复制命令到CMD运行,无需额外配置),分别用于Python控制周立功USBCANFD卡、将CAN/CANFD总线消息保存为BLF文件:
控制USBCANFD卡的核心库:
pip install zlgcan
周立功官方适配的Python库,支持绝大多数周立功USBCANFD卡型号,用于Python连接、控制USBCANFD卡,是Python操作周立功USBCANFD卡的核心依赖)
BLF文件保存库:
pip install python-can

二、Python控制周立功CAN卡(读取总线消息+保存BLF文件,完整代码加注释)

完整Python代码(控制CAN卡+读取消息+保存BLF,可直接复制运行)

"""周立功USBCANFD200U数据读取并保存到BLF文件 (使用zlgcan Python库)此程序使用zlgcan Python库连接周立功USBCANFD200U设备,读取通道0的CAN数据,并保存到BLF文件。使用前请确保:1. 已安装python-can库: pip install python-can2. 已安装zlgcan库: pip install zlgcan3. 已安装周立功USBCANFD200U设备驱动4. 设备已正确连接到电脑"""from zlgcan import *import timeimport canfrom can import Messagedef read_canfd_and_save_to_blf(device_type, device_index, channel, blf_file_path):    """    读取CANFD设备数据并保存到BLF文件    Args:        device_type: 设备类型        device_index: 设备索引        channel: 通道号        blf_file_path: BLF文件保存路径    """    print(f"开始读取周立功USBCANFD200U设备数据...")    print(f"设备类型: USBCANFD-200U")    print(f"设备索引: {device_index}")    print(f"通道: {channel}")    print(f"BLF文件: {blf_file_path}")    print("=" * 70)    try:1. 初始化zcanlib        print("正在初始化zcanlib...")        zcanlib = ZCAN()                # 2. 打开设备        print("正在打开设备...")        device_handle = zcanlib.OpenDevice(device_type, device_index, 0)        if device_handle == INVALID_DEVICE_HANDLE:            print("✗ 打开设备失败")            return        print(f"✓ 设备打开成功,句柄: {device_handle}")                # 3. 获取设备信息        info = zcanlib.GetDeviceInf(device_handle)        print(f"设备信息: {info}")                # 4. 配置通道        print("正在配置通道...")                # 设置仲裁域波特率 和 数据域波特率        ret = zcanlib.ZCAN_SetValue(device_handle, str(channel) + "/canfd_abit_baud_rate", "500000".encode("utf-8"))        ret = zcanlib.ZCAN_SetValue(device_handle, str(channel) + "/canfd_dbit_baud_rate", "2000000".encode("utf-8"))        if ret != ZCAN_STATUS_OK:            print("✗ 设置波特率失败!")            zcanlib.CloseDevice(device_handle)            return                # 终端电阻        ret = zcanlib.ZCAN_SetValue(device_handle, str(channel) + "/initenal_resistance", "1".encode("utf-8"))        if ret != ZCAN_STATUS_OK:            print("✗ 设置终端电阻失败!")            zcanlib.CloseDevice(device_handle)            return                # 初始化通道        chn_init_cfg = ZCAN_CHANNEL_INIT_CONFIG()        chn_init_cfg.can_type = ZCAN_TYPE_CANFD  # USBCANFD 必须选择CANFD        chn_init_cfg.config.canfd.mode = 0  # 0-正常模式 1-只听模式        chn_handle = zcanlib.InitCAN(device_handle, channel, chn_init_cfg)        if chn_handle is None:            print("✗ 初始化通道失败!")            zcanlib.CloseDevice(device_handle)            return                # 启动通道        ret = zcanlib.StartCAN(chn_handle)        if ret != ZCAN_STATUS_OK:            print("✗ 启动通道失败!")            zcanlib.CloseDevice(device_handle)            return        print(f"✓ 通道启动成功,句柄: {chn_handle}")                # 5. 创建BLF文件记录器        logger = can.Logger(blf_file_path)        print(f"✓ BLF文件创建成功: {blf_file_path}")                message_count = 0        start_time = time.time()                print("开始接收CAN数据...")        print("按Ctrl+C停止")        print("=" * 70)                try:            while True:                # 读取CAN消息                rcv_num = zcanlib.GetReceiveNum(chn_handle, ZCAN_TYPE_CAN)                if rcv_num:                    if rcv_num > 100:                        rcv_msg, rcv_num = zcanlib.Receive(chn_handle, 100, 100)                    else:                        rcv_msg, rcv_num = zcanlib.Receive(chn_handle, rcv_num, 100)                                        for msg in rcv_msg[:rcv_num]:                        message_count += 1                        frame = msg.frame                        direction = "TX" if frame._pad & 0x20 else "RX"                        frame_type = "扩展帧" if frame.can_id & (1 << 31) else "标准帧"                        frame_format = "远程帧" if frame.can_id & (1 << 30) else "数据帧"                        can_id = frame.can_id & 0x1FFFFFFF                                                if frame.can_id & (1 << 30):                            data = []                            dlc = 0                        else:                            dlc = frame.can_dlc                            data = list(frame.data[:dlc])                                                # 转换为python-can的Message对象                        can_msg = Message(                            arbitration_id=can_id,                            data=data,                            is_extended_id=(frame.can_id & (1 << 31) != 0),                            timestamp=time.time()                        )                                                # 写入BLF文件                        logger(can_msg)                                                # 显示接收到的消息                        data_str = " ".join([f"{num:02X}" for num in data])                        print(f"CAN消息 #{message_count}:")                        print(f"  ID: 0x{can_id:X}")                        print(f"  DLC: {dlc}")                        print(f"  数据: {data_str}")                        print(f"  方向: {direction}")                        print(f"  类型: {frame_type} {frame_format}")                        print(f"  时间: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())}")                        print("-" * 70)                                # 读取CANFD消息                rcv_canfd_num = zcanlib.GetReceiveNum(chn_handle, ZCAN_TYPE_CANFD)                if rcv_canfd_num:                    if rcv_canfd_num > 100:                        rcv_canfd_msgs, rcv_canfd_num = zcanlib.ReceiveFD(chn_handle, 100, 100)                    else:                        rcv_canfd_msgs, rcv_canfd_num = zcanlib.ReceiveFD(chn_handle, rcv_canfd_num, 100)                                        for msg in rcv_canfd_msgs[:rcv_canfd_num]:                        message_count += 1                        frame = msg.frame                        brs = "加速" if frame.flags & 0x1 else "   "                        direction = "TX" if frame.flags & 0x20 else "RX"                        frame_type = "扩展帧" if frame.can_id & (1 << 31) else "标准帧"                        frame_format = "远程帧" if frame.can_id & (1 << 30) else "数据帧"                        can_id = frame.can_id & 0x1FFFFFFF                        data = list(frame.data[:frame.len])                                                # 转换为python-can的Message对象                        can_msg = Message(                            arbitration_id=can_id,                            data=data,                            is_extended_id=(frame.can_id & (1 << 31) != 0),                            timestamp=time.time()                        )                                                # 写入BLF文件                        logger(can_msg)                                                # 显示接收到的消息                        data_str = " ".join([f"{num:02X}" for num in data])                        print(f"CANFD消息 #{message_count}:")                        print(f"  ID: 0x{can_id:X}")                        print(f"  DLC: {frame.len}")                        print(f"  数据: {data_str}")                        print(f"  方向: {direction}")                        print(f"  类型: {frame_type} {frame_format} {brs}")                        print(f"  时间: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())}")                        print("-" * 70)                                # 每100条消息显示一次进度                #if message_count % 100 == 0:                    #print(f"... 已接收 {message_count} 条消息 ...")                            except KeyboardInterrupt:            print("\n用户停止程序")        finally:            # 停止记录器            logger.stop()                        # 关闭通道            zcanlib.ResetCAN(chn_handle)                        # 关闭设备            zcanlib.CloseDevice(device_handle)                        elapsed_time = time.time() - start_time            print("=" * 70)            print(f"✓ 数据读取完成")            print(f"✓ 共接收 {message_count} 条CAN消息")            print(f"✓ 数据已保存到: {blf_file_path}")            print(f"✓ 运行时间: {elapsed_time:.2f} 秒")            print("=" * 70)                except Exception as e:        print(f"✗ 发生错误: {e}")        import traceback        traceback.print_exc()def main():    """    主函数    """    print("周立功USBCANFD200U数据读取工具 (使用zlgcan Python库)")    print("=" * 70)        # 设备配置    device_type = ZCAN_USBCANFD_200U    device_index = 0  # 设备索引,通常为0    channel = 0  # 通道0        # BLF文件路径    blf_file_path = input("请输入BLF文件保存路径 (默认: canfd_data_zlg_lib.blf): ") or "canfd_data_zlg_lib.blf"        print("=" * 70)        # 开始读取数据    read_canfd_and_save_to_blf(device_type, device_index, channel, blf_file_path)if name == "main":    main()
运行结果显示:

三、Python控制周立功CAN卡常见问题排查

问题1:运行Python代码报错“找不到zlgcan库”→ 解决方案:重新安装zlgcan库,若仍失败,更换Python版本(建议Python 3.7-3.10,兼容性最佳),确保能正常调用zlgcan库控制周立功CAN卡;
问题2:Python初始化周立功CAN卡失败,提示“无法打开CAN卡”→ 解决方案:检查CAN卡是否插好、ZLG CAN驱动是否安装成功,打开周立功官方测试工具确认能识别CAN卡,排除硬件和驱动问题;
问题3:Python能初始化CAN卡但读不到CAN总线消息→ 解决方案:检查CAN总线接线是否正确、波特率是否与总线一致,发送报文是否有错误帧。

持续分享Labview / 测试 / 自动化/机械手/视觉定位/PLC实战干货,每周更新,欢迎关注。

最新文章

随机文章