使用 SocketCAN 插件
SocketCAN 插件封装了用于访问 CAN 设备的 Linux 套接字 API。该 API 是一套开放源码 CAN 驱动程序和网络协议栈,由大众汽车研究院向 Linux 内核提供。
该插件需要一个支持 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 100
CAN 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是插件名称。
接下来,就可以建立与特定接口的连接了:
QStringerrorString;QCanBusDevice*设备 =QCanBus::instance()->createDevice( QStringLiteral("socketcan")、 QStringLiteral("can0"), &errorString);if(!device) {// 错误处理到此为止 qDebug << errorString; }else{ device->connectDevice(); }
其中,can0是活动 CAN 接口的名称。CAN 接口就像 Linux 系统上的普通网络接口,可以通过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)
© 2025 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.