翻譯|行業(yè)資訊|編輯:顏馨|2023-04-21 14:28:21.590|閱讀 241 次
概述:本文將為大家介紹最新的Qt 6.5版本引入的許多新功能,歡迎下載相關(guān)組件體驗(yàn)~
# 界面/圖表報(bào)表/文檔/IDE等千款熱門(mén)軟控件火熱銷售中 >>
Qt 是目前最先進(jìn)、最完整的跨平臺(tái)C++開(kāi)發(fā)工具。它不僅完全實(shí)現(xiàn)了一次編寫(xiě),所有平臺(tái)無(wú)差別運(yùn)行,更提供了幾乎所有開(kāi)發(fā)過(guò)程中需要用到的工具。如今,Qt已被運(yùn)用于超過(guò)70個(gè)行業(yè)、數(shù)千家企業(yè),支持?jǐn)?shù)百萬(wàn)設(shè)備及應(yīng)用。
The Qt Company是Digia Plc旗下的全資子公司。負(fù)責(zé)所有Qt活動(dòng),包括產(chǎn)品開(kāi)發(fā),商業(yè)和開(kāi)源授權(quán)模式以及在開(kāi)放管理模式下的Qt工程。其許可、支持和服務(wù)能力能夠和開(kāi)發(fā)者緊密合作以確保他們的Qt項(xiàng)目準(zhǔn)時(shí)部署,不超預(yù)算并擁有競(jìng)爭(zhēng)優(yōu)勢(shì)。
Qt CAN總線模塊始終提供API用于CAN總線的高級(jí)操作:
CAN總線幀由幀ID和有效負(fù)載組成。在現(xiàn)有的 API 中,F(xiàn)rameId 表示為無(wú)符號(hào)整數(shù),有效負(fù)載只是一個(gè)保存一些原始字節(jié)的 QByteArray。
實(shí)際上,更高級(jí)別的協(xié)議應(yīng)用于CAN總線幀之上。這克服了任意有效負(fù)載和 FrameId 的通用定義,該定義將其替換為可能發(fā)生的總線設(shè)備、消息和信號(hào)類型的唯一標(biāo)識(shí)符,并為信號(hào)中的值提供類型信息。
在Qt 6.5之前,用戶必須提供自己的實(shí)現(xiàn)來(lái)提取這些值。在Qt 6.5中,我們引入了一組API來(lái)簡(jiǎn)化此過(guò)程。
新的 API 提供了一種描述頂級(jí)協(xié)議的方法。稍后,這些規(guī)則可用于解碼傳入的CAN幀,以及在將數(shù)據(jù)發(fā)送到設(shè)備之前將數(shù)據(jù)編碼為CAN幀。
讓我們仔細(xì)看看 API:
QCanFrameProcessor 類使用其他新類提供的描述。它提供了兩種主要方法來(lái)編碼和解碼幀:
讓我們開(kāi)發(fā)一個(gè)小示例來(lái)演示運(yùn)行中的新 API。
讓我們考慮一個(gè)具有以下格式的協(xié)議:
可以使用下圖可視化此格式。
讓我們看看如何用新的 API 來(lái)描述這個(gè)協(xié)議。
唯一標(biāo)識(shí)符
讓我們從唯一標(biāo)識(shí)符開(kāi)始。
QCanUniqueIdDescription uid; uid.setSource(QtCanBus::DataSource::FrameId); uid.setEndian(QSysInfo::Endian::LittleEndian); uid.setStartBit(0); uid.setBitLength(11);
我們定義源(FrameId),字節(jié)序(Little-Endian),起始位和唯一標(biāo)識(shí)符的位長(zhǎng)度。
源定義了CAN幀的一部分,該幀將用于提取值。它可以是幀 ID 或有效負(fù)載。
信號(hào)和消息描述
接下來(lái),讓我們定義信號(hào)描述。
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);
對(duì)于這兩個(gè)信號(hào),我們定義信號(hào)名稱、源(有效載荷)、字節(jié)序(小端)、數(shù)據(jù)類型、起始位和位長(zhǎng)度。請(qǐng)注意,對(duì)于整個(gè)有效負(fù)載,位編號(hào)是連續(xù)的。位 0 表示字節(jié) 0 的第一個(gè)位,位 63 表示字節(jié) 7 的最后一位。信號(hào)名稱在消息描述中必須是唯一的。信號(hào)名稱用于在解析幀時(shí)提供有意義的結(jié)果,并標(biāo)識(shí)將值編碼到新生成的幀中的正確規(guī)則。允許您指定更多參數(shù)。有關(guān)完整列表,請(qǐng)參閱文檔。
指定信號(hào)描述后,我們可以定義消息描述。
QCanMessageDescription msg; msg.setName(u"example message"_s); msg.setSize(8); msg.setUniqueId(QtCanBus::UniqueId{0x123}); msg.setSignalDescriptions({s0, s1});
對(duì)于消息描述,我們指定有效負(fù)載大小、此消息中包含的信號(hào)描述列表以及唯一標(biāo)識(shí)符。唯一標(biāo)識(shí)符將用于在解碼傳入CAN幀時(shí)選擇正確的消息描述。與信號(hào)描述一樣,QCanMessageDescription 類允許您指定更多參數(shù),因此請(qǐng)務(wù)必查看文檔。
幀處理器
一旦我們?yōu)槲ㄒ粯?biāo)識(shí)符和消息創(chuàng)建了描述,我們就可以創(chuàng)建 QCanFrameProcessor 的實(shí)例。
QCanFrameProcessor processor; processor.setUniqueIdDescription(uid); processor.setMessageDescriptions({msg});
幀處理器使用先前生成的唯一 ID 描述和消息描述列表進(jìn)行初始化。在我們的例子中,列表只包含一個(gè)元素。
處理 CAN 幀
本節(jié)介紹如何使用上述消息描述來(lái)解析傳入幀和對(duì)新幀進(jìn)行編碼。
為簡(jiǎn)單起見(jiàn),讓我們手動(dòng)創(chuàng)建一個(gè)CAN幀。
QCanBusFrame frame(0x123, QByteArray::fromHex("ABCD123456780000"));
實(shí)際上,這樣的幀將從QCanBusDevice接收。請(qǐng)注意,框架具有與之前創(chuàng)建的消息描述的唯一標(biāo)識(shí)符匹配的唯一標(biāo)識(shí)符。
要解析此幀,只需調(diào)用 parseFrame() 方法:
QCanFrameProcessor::ParseResult result = processor.parseFrame(frame); qDebug() << Qt::hex << Qt::showbase << Qt::uppercasedigits << "Unique ID:" << result.uniqueId << Qt::endl << "Values:" << result.signalValues;
此方法返回一個(gè) ParseResult 結(jié)構(gòu),其中包含一個(gè)唯一標(biāo)識(shí)符和一個(gè)保存信號(hào)名稱和信號(hào)值的映射。qDebug() 調(diào)用的輸出如下所示。
Unique ID: 0x123 Values: QMap(("signal 0", QVariant(qulonglong, 0xCDAB))("signal 1", QVariant(qlonglong, 0x78563412)))
要生成幀,我們需要調(diào)用 prepareFrame() 方法,并將唯一標(biāo)識(shí)符以及信號(hào)名稱和信號(hào)值的映射作為參數(shù)傳遞。信號(hào)名稱必須與信號(hào)描述的名稱匹配。對(duì)于此示例,我們將重用 parseFrame() 方法返回的值。
QCanBusFrame generated = processor.prepareFrame(result.uniqueId, result.signalValues); qDebug() << Qt::hex << Qt::showbase << Qt::uppercasedigits << generated.frameId() << generated.payload().toHex().toUpper();
生成的幀應(yīng)與初始幀相似。這就是我們?cè)?nbsp;qDebug() 輸出中看到的。
上一節(jié)中的示例演示如何手動(dòng)指定CAN報(bào)文描述。這種方法相當(dāng)冗長(zhǎng)且容易出錯(cuò)。
我們能做得更好嗎?
幸運(yùn)的是,已經(jīng)有一些眾所周知的描述CAN總線參數(shù)的標(biāo)準(zhǔn)。其中一個(gè)標(biāo)準(zhǔn)是DBC。它是一種基于文本的格式,廣泛用于各個(gè)行業(yè)。
在Qt 6.5中,我們引入了QCanDbcFileParser類。此類分析輸入 DBC 文件,并自動(dòng)生成消息說(shuō)明。DBC 格式還包含對(duì)唯一標(biāo)識(shí)符的明確定義要求,因此該類還具有生成唯一標(biāo)識(shí)符描述的靜態(tài)方法。
此示例可以說(shuō)明使用此類的典型模式。
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文件解析成功,我們可以使用生成的消息和唯一標(biāo)識(shí)符描述來(lái)創(chuàng)建幀處理器并開(kāi)始處理。如果解析失敗,API 會(huì)提供一些方便的方法來(lái)處理錯(cuò)誤。
歡迎下載|體驗(yàn)更多Qt相關(guān)組件
獲取更多信息請(qǐng)咨詢 ;Qt技術(shù)交流群:166830288
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請(qǐng)務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請(qǐng)郵件反饋至chenjj@fc6vip.cn