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. 推荐学习路径
- 先跑通 虚拟 CAN(vcan0)环境
- 掌握 发送单条 / 周期发送 / 接收循环
- 学会 设置过滤器
- 结合 cantools + DBC 做信号解析
- 最后对接真实硬件(PCAN / Vector / SocketCAN)
需要我针对某个具体硬件(PCAN、USBCAN、Vector、CANalyzer 配合等)给出详细示例,或者帮你写某个特定功能的完整脚本吗?直接告诉我需求~