彩票走势图

Qt新功能! 用于解析 CAN 帧的新 API拓展

翻译|行业资讯|编辑:颜馨|2023-04-21 14:28:21.590|阅读 143 次

概述:本文将为大家介绍最新的Qt 6.5版本引入的许多新功能,欢迎下载相关组件体验~

# 慧都年终大促·界面/图表报表/文档/IDE等千款热门软控件火热促销中 >>

Qt 是目前最先进、最完整的跨平台C++开发工具。它不仅完全实现了一次编写,所有平台无差别运行,更提供了几乎所有开发过程中需要用到的工具。如今,Qt已被运用于超过70个行业、数千家企业,支持数百万设备及应用。

The Qt Company是Digia Plc旗下的全资子公司。负责所有Qt活动,包括产品开发,商业和开源授权模式以及在开放管理模式下的Qt工程。其许可、支持和服务能力能够和开发者紧密合作以确保他们的Qt项目准时部署,不超预算并拥有竞争优势。

简史

Qt CAN总线模块始终提供API用于CAN总线的高级操作:

  • QCanBusDevice 表示 CAN 设备。此类可用于读取和写入CAN帧。
  • QCanBusFrame表示一个实际的CAN帧。

CAN总线帧由帧ID和有效负载组成。在现有的 API 中,FrameId 表示为无符号整数,有效负载只是一个保存一些原始字节的 QByteArray。

实际上,更高级别的协议应用于CAN总线帧之上。这克服了任意有效负载和 FrameId 的通用定义,该定义将其替换为可能发生的总线设备、消息和信号类型的唯一标识符,并为信号中的值提供类型信息。

在Qt 6.5之前,用户必须提供自己的实现来提取这些值。在Qt 6.5中,我们引入了一组API来简化此过程。

用于解析 CAN 帧的新 API

新的 API 提供了一种描述顶级协议的方法。稍后,这些规则可用于解码传入的CAN帧,以及在将数据发送到设备之前将数据编码为CAN帧。

让我们仔细看看 API:

  • QCanUniqueIdDescription定义了在CAN帧内存储和提取唯一标识符的规则。
  • QCanSignalDescription定义了在CAN帧内存储和提取单个信号值的规则。
  • QCanMessageDescription定义了CAN报文。消息包含一个唯一标识符和多个信号。
  • QCanFrameProcessor可用于解码传入的CAN帧或将提供的值编码为CAN帧以发送到接收器。

QCanFrameProcessor 类使用其他新类提供的描述。它提供了两种主要方法来编码和解码帧:

  • QCanFrameProcessor::p arseFrame() 来解析传入的帧。
  • QCanFrameProcessor::p repareFrame() 基于输入数据生成帧。

让我们开发一个小示例来演示运行中的新 API。

演示时间

让我们考虑一个具有以下格式的协议:

  • 唯一标识符编码到 FrameID 的前 11 位中。
  • 有效负载包含 8 个字节。
  • 前两个字节表示称为“信号 0”的信号。此信号包含一个无符号整数。
  • 接下来的 4 个字节表示称为“信号 1”的信号。此信号包含一个有符号整数。
  • 字节采用小端格式。

可以使用下图可视化此格式。

有效载荷

让我们看看如何用新的 API 来描述这个协议。

唯一标识符

让我们从唯一标识符开始。

QCanUniqueIdDescription uid; 
uid.setSource(QtCanBus::DataSource::FrameId); 
uid.setEndian(QSysInfo::Endian::LittleEndian); 
uid.setStartBit(0); 
uid.setBitLength(11); 

我们定义源(FrameId),字节序(Little-Endian),起始位和唯一标识符的位长度。

源定义了CAN帧的一部分,该帧将用于提取值。它可以是帧 ID 或有效负载。

信号和消息描述

接下来,让我们定义信号描述。

QCanSignalDescription s0;
s0.setName(u"signal 0"_s);
s0.setDataSource(QtCanBus::DataSource::Payload);
s0.setDataEndian(QSysInfo::Endian::LittleEndian);
s0.setDataFormat(QtCanBus::DataFormat::UnsignedInteger);
s0.setStartBit(0);
s0.setBitLength(16);

QCanSignalDescription s1;
s1.setName(u"signal 1"_s);
s1.setDataSource(QtCanBus::DataSource::Payload);
s1.setDataEndian(QSysInfo::Endian::LittleEndian);
s1.setDataFormat(QtCanBus::DataFormat::SignedInteger);
s1.setStartBit(16);
s1.setBitLength(32);

对于这两个信号,我们定义信号名称、源(有效载荷)、字节序(小端)、数据类型、起始位和位长度。请注意,对于整个有效负载,位编号是连续的。位 0 表示字节 0 的第一个位,位 63 表示字节 7 的最后一位。信号名称在消息描述中必须是唯一的。信号名称用于在解析帧时提供有意义的结果,并标识将值编码到新生成的帧中的正确规则。允许您指定更多参数。有关完整列表,请参阅文档。

指定信号描述后,我们可以定义消息描述。

QCanMessageDescription msg;
msg.setName(u"example message"_s);
msg.setSize(8);
msg.setUniqueId(QtCanBus::UniqueId{0x123});
msg.setSignalDescriptions({s0, s1});

对于消息描述,我们指定有效负载大小、此消息中包含的信号描述列表以及唯一标识符。唯一标识符将用于在解码传入CAN帧时选择正确的消息描述。与信号描述一样,QCanMessageDescription 类允许您指定更多参数,因此请务必查看文档。

帧处理器

一旦我们为唯一标识符和消息创建了描述,我们就可以创建 QCanFrameProcessor 的实例。

QCanFrameProcessor processor;
processor.setUniqueIdDescription(uid);
processor.setMessageDescriptions({msg});

帧处理器使用先前生成的唯一 ID 描述和消息描述列表进行初始化。在我们的例子中,列表只包含一个元素。

处理 CAN 帧

本节介绍如何使用上述消息描述来解析传入帧和对新帧进行编码。

为简单起见,让我们手动创建一个CAN帧。

QCanBusFrame frame(0x123, QByteArray::fromHex("ABCD123456780000"));

实际上,这样的帧将从QCanBusDevice接收。请注意,框架具有与之前创建的消息描述的唯一标识符匹配的唯一标识符。

要解析此帧,只需调用 parseFrame() 方法:

QCanFrameProcessor::ParseResult result = processor.parseFrame(frame);
qDebug() << Qt::hex << Qt::showbase << Qt::uppercasedigits
<< "Unique ID:" << result.uniqueId << Qt::endl
<< "Values:" << result.signalValues;

此方法返回一个 ParseResult 结构,其中包含一个唯一标识符和一个保存信号名称和信号值的映射。qDebug() 调用的输出如下所示。

Unique ID: 0x123
Values: QMap(("signal 0", QVariant(qulonglong, 0xCDAB))("signal 1", QVariant(qlonglong, 0x78563412)))

要生成帧,我们需要调用 prepareFrame() 方法,并将唯一标识符以及信号名称和信号值的映射作为参数传递。信号名称必须与信号描述的名称匹配。对于此示例,我们将重用 parseFrame()&nbsp;方法返回的值。

QCanBusFrame generated = processor.prepareFrame(result.uniqueId,
result.signalValues);
qDebug() << Qt::hex << Qt::showbase << Qt::uppercasedigits
<< generated.frameId() << generated.payload().toHex().toUpper();

生成的帧应与初始帧相似。这就是我们在 qDebug() 输出中看到的。

自动提取总线信息

上一节中的示例演示如何手动指定CAN报文描述。这种方法相当冗长且容易出错。

我们能做得更好吗?

幸运的是,已经有一些众所周知的描述CAN总线参数的标准。其中一个标准是DBC。它是一种基于文本的格式,广泛用于各个行业。

在Qt 6.5中,我们引入了QCanDbcFileParser类。此类分析输入 DBC 文件,并自动生成消息说明。DBC 格式还包含对唯一标识符的明确定义要求,因此该类还具有生成唯一标识符描述的静态方法。

此示例可以说明使用此类的典型模式。

QCanDbcFileParser dbcParser;
if (dbcParser.parse("path/to/file.dbc")) {
QCanFrameProcessor processor;
processor.setUniqueIdDescription(QCanDbcFileParser::uniqueIdDescription());
processor.setMessageDescriptions(dbcParser.messageDescriptions());
// Do the actual processing
} else {
// Failed to extract data from DBC file
qDebug() << "Got error:" << dbcParser.error();
qDebug() << "Error details:" << dbcParser.errorString();
}

如果DBC文件解析成功,我们可以使用生成的消息和唯一标识符描述来创建帧处理器并开始处理。如果解析失败,API 会提供一些方便的方法来处理错误。

Qt Widget组件推荐
  • QtitanRibbon - Ribbon UI组件:是一款遵循Microsoft Ribbon UI Paradigm for Qt技术的Ribbon UI组件,QtitanRibbon致力于为Windows、Linux和Mac OS X提供功能完整的Ribbon组件。
  • QtitanChart - Qt类图表组件:是一个C ++库,代表一组控件,这些控件使您可以快速地为应用程序提供漂亮而丰富的图表。
  • QtitanDataGrid - Qt网格组件:提供了一套完整的标准 QTableView 函数和传统组件无法实现的独特功能。使您能够将不同来源的各类数据加载到一个快速、灵活且功能强大的可编辑网格中,支持排序、分组、报告、创建带状列、拖放按钮和许多其他方便的功能。
  • QtitanDocking:允许您像 Visual Studio 一样为您的伟大应用程序配备可停靠面板和可停靠工具栏。黑色、白色、蓝色调色板完全支持 Visual Studio 2019 主题!

  • 欢迎下载|体验更多Qt相关组件

    获取更多信息请咨询  ;Qt技术交流群:166830288


    标签:

    本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@cahobeh.cn


    为你推荐

    • 推荐视频
    • 推荐活动
    • 推荐产品
    • 推荐文章
    • 慧都慧问
    扫码咨询


    添加微信 立即咨询

    电话咨询

    客服热线
    023-68661681

    TOP