使用 SocketCAN 插件
SocketCAN 插件封装了用于访问 CAN 设备的 Linux 套接字 API。该 API 是一套由大众汽车研发中心贡献给 Linux 内核的开源 CAN 驱动程序和网络协议栈。
该插件需要支持 SocketCAN 的 Linux 内核,以及适用于所用 CAN 硬件的 SocketCAN 设备驱动程序。
SocketCAN 的使用方法
要列出所有(包括未配置的)网络接口,可以使用命令ifconfig -a 。
要使用 SocketCAN,必须加载相应的 Linux 内核模块,并配置网络接口。
设置真实的 CAN 硬件
本节假设设备驱动程序已加载(通常在连接 CAN 硬件时会自动加载)。
默认设置
要将设备 can0 的波特率设置为 250 kBit/s:
sudo ip link set up can0 type can bitrate 250000若要在“总线断开”错误发生100毫秒后自动恢复,可使用以下命令:
sudo ip link set up can0 type can bitrate 250000 restart-ms 100CAN FD 设置
要将设备 can0 的仲裁波特率设置为 500 kBit/s,数据波特率设置为 4 MBit/s(适用于带有波特率切换标志的帧):
sudo ip link set can0 up type can bitrate 500000 dbitrate 4000000 fd on设置虚拟 CAN 总线
注意:若要使用 CAN FD,必须将 MTU(最大传输单元)设置为 72 字节。
sudo modprobe vcan
sudo ip link add dev vcan0 type vcan
sudo ip link set up vcan0 mtu 72下文中使用的命令行测试程序来自can-utils软件包:
# Display received CAN messages with absolute timestamps and flags
candump -ta -x vcan0
# Send a CAN FD message with flags BRS and EFI set
cansend vcan0 123##3112233445566778899aabbccddeeff
# Generate random CAN messages
cangen vcan0创建 CAN 总线设备
首先需要检查QCanBus 是否提供了所需的插件:
if (QCanBus::instance()->plugins().contains(QStringLiteral("socketcan"))) {
// plugin available
}其中socketcan是插件名称。
接下来,可以建立与特定接口的连接:
QString errorString;
QCanBusDevice*device =QCanBus::instance()->createDevice(
QStringLiteral("socketcan"), QStringLiteral("can0"), &errorString);
if(!device) {
// 错误处理代码在此处
qDebug << errorString;
}else{
device->connectDevice();
}其中`can0` 是活动的 CAN 接口名称。在 Linux 系统中,CAN 接口的行为与普通网络接口类似,可通过 `ifconfig` 进行发现。此外,`availableDevices()` 方法会返回当前可用设备的列表。
现在该设备已打开,可用于读写 CAN 帧:
QCanBusFrame frame;
frame.setFrameId(8);
QByteArray payload("A36E");
frame.setPayload(payload);
device->writeFrame(frame);读取操作可通过readFrame() 方法实现。当至少有一个新帧可供读取时,会触发framesReceived() 信号:
QCanBusFrame frame = device->readFrame();SocketCAN 支持以下配置,这些配置可通过setConfigurationParameter() 进行控制:
| 配置参数键 | 描述 |
|---|---|
| QCanBusDevice::LoopbackKey | 为满足多用户需求,本地环回功能默认处于启用状态。这意味着,每当在 CAN 总线上传输一个 CAN 帧时,该帧的本地回显都会发送给连接到该 CAN 设备的所有应用程序。如果启用此选项,因此接收到的帧将被标记为QCanBusFrame::hasLocalEcho() |
| QCanBusDevice::ReceiveOwnKey | 默认情况下,禁止在发送 CAN 帧的同一套接字上接收该 CAN 帧。启用此选项后,发送到 CAN 总线的所有 CAN 帧会立即出现在接收缓冲区中。这可用于检查发送是否成功。如果启用此选项,因此接收到的帧将标记为QCanBusFrame::hasLocalEcho() |
| QCanBusDevice::ErrorFilterKey | CAN 接口驱动程序可以生成所谓的“错误消息帧”,这些帧可选择性地以与其他 CAN 帧相同的方式传递给用户应用程序。可能出现的错误被划分为不同的错误类,可通过相应的错误掩码进行过滤。错误掩码的值在linux/can/error.h 中定义。 |
| QCanBusDevice::RawFilterKey | 此配置可包含多个类型为QCanBusDevice::Filter 的过滤器。默认情况下,连接配置为接受任何CAN总线消息。 |
| QCanBusDevice::BitRateKey | 确定 CAN 总线连接的比特率。 支持以下波特率:5000、10000、20000、33000、47000、50000、83000、95000、100000、 125000、250000、500000、800000、1000000。 请注意,此配置参数仅在QCanBusDevice 未连接时才能调整。要设置此配置参数,运行时需要 libsocketcan 库 http://www.pengutronix.de/software/libsocketcan。通常,设置 CAN 总线波特率需要 root 权限。 |
| QCanBusDevice::CanFdKey | 此配置选项决定是否允许发送或接收 CANFD 帧。默认情况下,此选项处于禁用状态。它控制 CAN 套接字的 CAN_RAW_FD_FRAMES 选项。 |
| QCanBusDevice::DataBitRateKey | socketcan 插件不支持此配置。但在使用ip link 命令配置 CAN 网络接口时,可以设置数据速率。 |
| QCanBusDevice::ProtocolKey | 允许在 PF_CAN 协议族内使用其他协议。此配置选项的默认值为 CAN_RAW (1)。 |
例如:
QList<QCanBusDevice::Filter> list;
QCanBusDevice::Filter f;
// only accept odd numbered frame id of type remote request
// frame can utilize extended or base format
f.frameId = 0x1;
f.frameIdMask = 0x1;
f.format = QCanBusDevice::Filter::MatchBaseAndExtendedFormat;
f.type = QCanBusFrame::RemoteRequestFrame;
list.append(f);
device->setConfigurationParameter(QCanBusDevice::RawFilterKey, QVariant::fromValue(list));
device->setConfigurationParameter(QCanBusDevice::ErrorFilterKey,
QVariant::fromValue(QCanBusFrame::FrameErrors(QCanBusFrame::AnyError)));SocketCAN 支持扩展帧格式和灵活的数据速率。
SocketCAN 还支持以下附加功能:
- QCanBusDevice::resetController()(需要 libsocketcan)
- QCanBusDevice::busStatus()(需要 libsocketcan)
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.