本页内容

Qt CAN总线

控制器局域网(CAN)是一种车载总线标准,旨在让微控制器和设备在没有主计算机的应用中相互通信。

概述

这是一种基于消息的协议,最初是为汽车内的多路复用电气布线而设计的,但也被应用于许多其他场合。

CAN 总线 API 提供了一些通用的 API 来访问 CAN 设备:

从 Qt 6.5 开始,该模块提供了用于从原始 CAN 帧中解码实际信号值,以及将用户数据编码到 CAN 帧中的 API:

注意:所有 用于编码和解码 CAN 帧的 API 均处于实验阶段,可能会发生变更。

CAN 总线插件

多家厂商提供的CAN设备具有各不相同的访问API。QtSerialBus 模块支持以下系列CAN总线插件:

厂商插件(键)简要说明
基于 Linux 套接字的 CANSocketCAN(socketcan)使用 Linux 套接字和开源驱动程序的 CAN 总线插件。
通过 SAE J2534 直通实现的 CANPassThruCAN(passthrucan)使用 SAE J2534 直通接口的 CAN 总线插件。
SYS TEC electronicSystecCAN(systeccan)基于 SYS TEC CAN 适配器的 CAN 总线后端。
PEAK-SystemPeakCAN(peakcan)使用 PEAK CAN 适配器的 CAN 总线插件。
MHS ElektronikTinyCAN(tinycan)使用 MHS CAN 适配器的 CAN 总线插件。
Vector InformatikVectorCAN(vectorcan)使用 Vector CAN 适配器的 CAN 总线插件。
虚拟 CAN 接口VirtualCAN(virtualcan)使用虚拟 TCP/IP 连接的 CAN 总线插件。

实现自定义 CAN 插件

如果 Qt 提供的插件不适用于所需的目标平台,可以实现自定义 CAN 总线插件。其实现遵循 Qt 插件的标准实现方式。自定义插件必须部署到$QTDIR/plugins/canbus 上。

每个插件都必须定义一个密钥,用于加载该插件。这通过一个小型 JSON 文件来实现。例如,socketcan 插件使用的plugin.json 如下:

{
    "Key": "socketcan"
}

该键必须与 CAN 总线适配器的接口名称一同传递给QCanBus::createDevice()。QCanBus 通过 QCanBusFactoryV2 接口加载并实例化插件,每个插件都必须实现该接口作为中央入口点。 该接口充当工厂,其唯一目的是返回一个 `QCanBusDevice ` 实例。上述接口名称通过工厂的 `QCanBusFactory::createDevice()` 方法传递。以下是socketcan插件的工厂实现:

class SocketCanBusPlugin : public QObject, public QCanBusFactory
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QCanBusFactory" FILE "plugin.json")
    Q_INTERFACES(QCanBusFactory)

public:
    QList<QCanBusDeviceInfo> availableDevices(QString *errorMessage) const override
    {
        Q_UNUSED(errorMessage);
        return SocketCanBackend::interfaces();
    }

    QCanBusDevice *createDevice(const QString &interfaceName, QString *errorMessage) const override
    {
        Q_UNUSED(errorMessage);
        auto device = new SocketCanBackend(interfaceName);
        return device;
    }
};

下一步是实现QCanBusDevice 。至少必须实现以下纯虚函数:

open() 和close() 方法分别与QCanBusDevice::connectDevice() 和QCanBusDevice::disconnectDevice() 配合使用。具体实现细节请查阅函数文档。

QCanBusDevice::writeFrame() 负责执行合理性检查,例如验证QCanBusFrame 的有效性以及设备是否仍处于连接状态。只要检查通过,它就会将帧写入 CAN 总线。 成功时,它会发出QCanBusDevice::framesWritten() 信号;否则,将调用QCanBusDevice::setError() 并附带相应的错误消息。该函数也可用于实现异步写入操作。在适当的时候发出相应的信号是插件实现者的责任。

最后但同样重要的是,QCanBusDevice::interpretErrorFrame 提供了一种便捷的方式,可将 CAN 总线错误帧的内容转换为可供人类阅读的错误字符串。

© 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.