【Python】python-can使用记录

python-can 是目前 Python 生态中最成熟、通用的 CAN 总线通信库,支持多种硬件接口(PCAN、Vector、Kvaser、SocketCAN、slcan、USB2CAN 等),同时也支持虚拟 CAN(vcan)和 PCAN 等。

下面整理一份实用的 python-can 使用记录(基于 2025–2026 年最新版本 4.6.x 系列),包含安装、基本用法、常见场景、注意事项等。

1. 安装

# 基本安装(推荐)
pip install python-can

# 如果需要 serial 接口(如 slcan、arduino-can)
pip install python-can[serial]

# 某些特定接口可能还需要额外驱动(如 PCAN 需要安装 Peak 驱动)

当前最新稳定版(2025年8月后):4.6.1
官方文档:https://python-can.readthedocs.io/en/stable/

2. 快速入门 – 创建 Bus 并收发消息

最经典的用法(以 SocketCAN 为例,Linux 常用):

import can
import time

# 方式一:使用 with 语句(推荐,自动关闭)
with can.Bus(interface='socketcan', channel='vcan0', receive_own_messages=True) as bus:
    # 发送一条标准 CAN 消息 (ID=0x123, 数据 8 字节)
    msg = can.Message(
        arbitration_id=0x123,
        is_extended_id=False,       # False=标准帧, True=扩展帧
        data=[0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88],
        is_fd=False,                # 是否 CAN-FD(默认 False)
        bitrate_switch=False        # FD 模式下是否切换速率
    )

    try:
        bus.send(msg, timeout=0.2)
        print("Message sent on", bus.channel_info)
    except can.CanError:
        print("Message NOT sent")

    # 接收消息(阻塞式)
    print("Waiting for messages...")
    for msg in bus:
        print(f"Received: {msg}")
        # msg.arbitration_id, msg.data, msg.timestamp, msg.dlc 等
        if msg.arbitration_id == 0x321:
            print("Target message found!")
            break

带超时接收单条消息(更常用):

msg = bus.recv(timeout=3.0)  # 等待最多 3 秒
if msg is not None:
    print(f"Got: ID=0x{msg.arbitration_id:x}  Data={msg.data.hex()}")
else:
    print("Timeout - no message received")

3. 常用接口类型(interface 参数)

接口名称interface= 值平台备注
SocketCAN‘socketcan’Linux最常用,虚拟 vcan0 / 真实 can0/can1
PCAN‘pcan’Windows/Linux需要 Peak 驱动
Vector‘vector’Windows需要 Vector XL Driver
Kvaser‘kvaser’Windows/Linux需要 Kvaser 驱动
slcan‘slcan’跨平台USB转CAN(如 Lawicel、Arduino CAN)
virtual‘virtual’跨平台纯内存虚拟总线,用于测试
cantact‘cantact’跨平台CANtact 设备

创建 bus 几种等价写法

# 最常用(自动从配置读取)
bus = can.Bus()   # 需要提前配置 ~/.can 或环境变量

# 显式指定(推荐生产环境)
bus = can.Bus(interface='socketcan', channel='can0', bitrate=500000)

# CAN-FD 示例
bus = can.Bus(interface='pcan', channel='PCAN_USBD', fd=True, f_clock=80000000,
              dbitrate=2000000, bitrate=500000)

4. 过滤器设置(提高接收效率)

# 只接收特定 ID 的消息
filters = [
    {"can_id": 0x7E0, "can_mask": 0x7FF, "extended": False},  # 精确匹配 0x7E0
    {"can_id": 0x18F, "can_mask": 0x1FF0000, "extended": True}  # 匹配 J1939 PGN
]

bus.set_filters(filters)

5. 周期发送(最常见需求)

def send_periodic():
    bus = can.Bus('socketcan', channel='vcan0')
    msg = can.Message(arbitration_id=0x100, data=[0x01, 0x02], is_extended_id=False)

    # 每 200ms 发送一次,持续运行
    task = bus.send_periodic(msg, period=0.2)

    try:
        time.sleep(10)  # 运行 10 秒
    finally:
        task.stop()

# 或者使用线程方式
from can.thread import ThreadSafeBus

6. 配合 DBC 文件解析(强烈推荐)

import can
from cantools import db

db = db.load_file('your_database.dbc')

with can.Bus() as bus:
    for msg in bus:
        decoded = db.decode_message(msg.arbitration_id, msg.data)
        print(decoded)

(需要额外安装:pip install cantools

7. 常用实用代码片段

打印所有收到的消息(带时间戳)

for msg in bus:
    print(f"{msg.timestamp:>16.3f} {msg.arbitration_id:03X} {'X' if msg.is_extended_id else ' '} {msg.data.hex(' ')}")

发送 CAN-FD 消息

msg = can.Message(
    arbitration_id=0x123,
    data=[i for i in range(64)],  # CAN-FD 支持最长 64 字节
    is_fd=True,
    bitrate_switch=True
)
bus.send(msg)

8. 注意事项 & 常见问题

  • bitrate 参数只在初始化时有效,后续不可改(除非重开 bus)
  • receive_own_messages=True 时自己发的消息也会被收到(Linux SocketCAN 默认行为)
  • Windows 下 PCAN/Vector 需要安装官方驱动
  • Linux 下 SocketCAN 需要先配置 can 接口:sudo ip link set can0 up type can bitrate 500000
  • 虚拟测试:sudo modprobe vcan; sudo ip link add dev vcan0 type vcan; sudo ip link set vcan0 up
  • 异常处理:几乎所有操作都要 try ... except can.CanError
  • 性能:大量消息时推荐使用 can.Notifier + 回调函数异步处理

9. 推荐学习路径

  1. 先跑通 虚拟 CAN(vcan0)环境
  2. 掌握 发送单条 / 周期发送 / 接收循环
  3. 学会 设置过滤器
  4. 结合 cantools + DBC 做信号解析
  5. 最后对接真实硬件(PCAN / Vector / SocketCAN)

需要我针对某个具体硬件(PCAN、USBCAN、Vector、CANalyzer 配合等)给出详细示例,或者帮你写某个特定功能的完整脚本吗?直接告诉我需求~

文章已创建 5268

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部