CAN (控制器局域网) 为允许微控制器和设备在没有主计算机的应用程序中相互通信,而设计的车辆总线标准。
它是最初为汽车内多路复用电线而设计,但也用于许多其它场合的基于消息的协议。
CAN 总线 API 为访问 CAN 设备提供了一些公共 API:
从 Qt 6.5 开始,模块提供从原生 CAN 帧解码实际信号值,并将用户数据编码成 CAN 帧的 API:
注意: 用于编码和解码 CAN 帧的所有 API 都是实验性的,且可能改变。
多个供应商提供具有各种访问 API 的 CAN 设备。 QtSerialBus 模块支持下列 CAN 总线插件集:
供应商 | 插件 (关键) | 简要描述 |
---|---|---|
CAN over Linux sockets |
SocketCAN
(
socketcan
)
|
CAN 总线插件使用 Linux sockets 和开源驱动程序。 |
CAN via SAE J2534 Pass-Thru |
PassThruCAN
(
passthrucan
)
|
CAN 总线插件使用 SAE J2534 Pass-Thru 接口。 |
SYS TEC 电子 |
SystecCAN
(
systeccan
)
|
CAN 总线后端使用 SYS TEC CAN 适配器。 |
PEAK-System |
PeakCAN
(
peakcan
)
|
CAN 总线插件使用 PEAK CAN 适配器。 |
MHS 电子 |
TinyCAN
(
tinycan
)
|
CAN 总线插件使用 MHS CAN 适配器。 |
Vector Informatik |
VectorCAN
(
vectorcan
)
|
CAN 总线插件使用 Vector CAN 适配器。 |
虚拟 CAN 接口 |
VirtualCAN
(
virtualcan
)
|
CAN 总线插件使用虚拟 TCP/IP 连接。 |
If the plugins provided by Qt are not suitable for the required target platform, a custom CAN bus plugin can be implemented. The implementation follows the standard way of implementing Qt plug-ins. The custom plugin must be deployed to
$QTDIR/plugins/canbus
.
Each plugin must define a key, which is used to load the plugin. This is done via a small json file. For example, the socketcan plugin uses the following
plugin.json
:
{ "Key": "socketcan" }
此键必须被传递给 QCanBus::createDevice () together with the interface name of the CAN bus adapter. QCanBus loads and instantiates the plugin using the QCanBusFactoryV2 interface which each plugin must implement as central entry point. The interface acts as a factory and its sole purpose is to return a QCanBusDevice instance. The above mentioned interface name is passed on via the factory's QCanBusFactory::createDevice () method. The following is the factory implementation of the 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; } };
The next step is to provide an implementation of QCanBusDevice . At the very least, the following pure virtual functions must be implemented:
The open () 和 close () methods are used in conjunction with QCanBusDevice::connectDevice () 和 QCanBusDevice::disconnectDevice () respectively. Check the function documentation for implementation details.
QCanBusDevice::writeFrame () is responsible for sanity checks such as the validity of the QCanBusFrame and that the device is still connected. Provided that the checks passed, it writes the frame to the CAN bus. Upon success it emits the QCanBusDevice::framesWritten () signal; otherwise QCanBusDevice::setError () is called with an appropriate error message. This function may also be used to implement an asynchronous write operation. It is the plugin implementors responsibility to emit the appropriate signals at the appropriate time.
最后但最重要, QCanBusDevice::interpretErrorFrame provides a convenient way to translate the content of an CAN bus error frame to a human-readable error string.