QtQuick串口編程Demo
一、目標:
實現QtQuick界面,操控串口通信,進行串口數據的接收和發送
二、核心思想:
利用Qt庫的QSerialPort類,使用C++實現串口數據的邏輯通信,并接受QtQuick界面的參數設置,在QML中調用C++實現的函數進行實際的數據收發
(QML與C++混合編程)
三、具體實現:
(1)C++中的邏輯實現
首先看serialport.h文件
#ifndef SERIALPORT_H
#define SERIALPORT_H
#include <QObject>
#include <QSerialPort>
class SerialPort : public QObject
{
Q_OBJECT
public:
explicit SerialPort(QObject *parent = nullptr);
~SerialPort();
Q_INVOKABLE bool serialConnect(QString port,QString baudrate,QString databits,QString parity,QString stopbits);
Q_INVOKABLE QString serialRead();
Q_INVOKABLE bool serialWrite(QString sendStr);
signals:
public slots:
private:
QSerialPort *m_serial;
};
#endif // SERIALPORT_H
其中,注冊到QML環境中的類必須繼承自QObject,在類中聲明“Q_OBJECT”才能在C++中定義信號和槽,需要注冊到QML環境中的,變量屬性加關鍵字“Q_PROPERTY”,函數方法加關鍵字“Q_INVOKABLE”,定義了一個QSerialPort的對象,將在后續連接和通信中實現
serialport.cpp
#include "serialport.h"
SerialPort::SerialPort(QObject *parent) : QObject(parent)
{
m_serial = new QSerialPort;
}
bool SerialPort::serialConnect(QString port,QString baudrate,QString databits,QString parity,
QString stopbits)
{
m_serial->setPortName(port);
if(!m_serial->open(QIODevice::ReadWrite))
{
printf("Open Error");
return 0;
}
switch (baudrate.toInt()) {
case 4800:
m_serial->setBaudRate(QSerialPort::Baud4800);
break;
case 9600:
m_serial->setBaudRate(QSerialPort::Baud9600);
break;
case 115200:
m_serial->setBaudRate(QSerialPort::Baud115200); //設置波特率為115200
break;
default:
printf("BaudRate Error");
return 0;
}
switch (databits.toInt()) {
case 6:
m_serial->setDataBits(QSerialPort::Data6);
break;
case 7:
m_serial->setDataBits(QSerialPort::Data7);
break;
case 8:
m_serial->setDataBits(QSerialPort::Data8); //設置數據位8
break;
default:
printf("DataBits Error");
return 0;
}
switch (parity.toInt()) {
case 0:
m_serial->setParity(QSerialPort::NoParity); //校驗位設置為0
break;
case 2:
m_serial->setParity(QSerialPort::EvenParity);
break;
case 3:
m_serial->setParity(QSerialPort::OddParity);
break;
default:
printf("Parity Error");
return 0;
}
switch (stopbits.toInt()) {
case 1:
m_serial->setStopBits(QSerialPort::OneStop); //停止位設置為1
break;
case 2:
m_serial->setStopBits(QSerialPort::TwoStop);
break;
case 3:
m_serial->setStopBits(QSerialPort::OneAndHalfStop);
break;
default:
printf("StopBits Error");
return 0;
}
m_serial->setFlowControl(QSerialPort::NoFlowControl);//設置為無流控制
return 1;
}
QString SerialPort::serialRead()
{
return m_serial->readAll();
}
bool SerialPort::serialWrite(QString sendStr)
{
if(m_serial->write(sendStr.toLatin1().data(),strlen(sendStr.toLatin1().data())))
return 1;
else
return 0;
}
SerialPort::~SerialPort()
{
if(m_serial->isOpen())
{
m_serial->clear();
m_serial->close();
}
m_serial->deleteLater();
}
與傳統Qt中使用的函數一致,其中serialConnect函數中,接受Qt界面的參數設置,先打開串口,然后通過switch匹配,分別設置串口通信的串口名稱、波特率、數據位、校驗位、停止位
(2)將C++中的類注冊到QML中
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "serialport.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
qmlRegisterType<SerialPort>("an.qt.mySerialPort",1,0,"SerialPort");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
關鍵在中間的一句使用qmlRegisterType進行注冊,尖括號中為我們前面定義的新類名字,小括號中分別為import將要導入的名稱,主、次版本號,QML中所能使用的對象名稱為雙引號中的SerialPort(3)在QML中調用C++的邏輯實現
import QtQuick 2.0
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
import an.qt.mySerialPort 1.0
Page{
SerialPort{
id:serialport;
}
header: ToolBar{
RowLayout{
anchors.fill: parent
Text{
text: qsTr("SerialPort客戶端")
font.pointSize: 20
horizontalAlignment: Qt.AlignHCenter
Layout.fillWidth: true
}
}
}
GridLayout{
id:grid
anchors.verticalCenter: parent.verticalCenter;
anchors.left: parent.left;
anchors.leftMargin: 10;
rows:6;
rowSpacing: 5;
columns: 2;
columnSpacing: 5
Label{
text:qsTr("串口")
}
ComboBox{
id:port;
model: ["COM1","COM2","COM3"];
}
Label{
text:qsTr("波特率")
}
ComboBox{
id:baudrate;
model: ["4800","9600","115200"];
}
Label{
text:qsTr("數據位")
}
ComboBox{
id:databits
model: ["6","7","8"];
}
Label{
text:qsTr("校驗位")
}
ComboBox{
id:parity
model: ["0","2","3"];
}
Label{
text:qsTr("停止位")
}
ComboBox{
id:stopbits
model: ["1","2","3"];
}
Button{
text: qsTr("打開串口")
highlighted: true
Layout.columnSpan: 2;
onClicked: {
serialport.serialConnect(port.currentText,baudrate.currentText,
databits.currentText,parity.currentText,stopbits.currentText);
}
}
}
ColumnLayout{
anchors.left: grid.right
anchors.leftMargin: 60;
anchors.verticalCenter: parent.verticalCenter
spacing: 5
TextArea{
id:receive;
Layout.preferredWidth: 200;
Layout.preferredHeight: 200;
text: qsTr("Receive:")
readOnly: true;
background: Rectangle{
color: "gray"
}
}
Button{
text: qsTr("接收數據")
highlighted: true;
onClicked: {
receive.append(serialport.serialRead());
}
}
TextField{
id:send;
Layout.preferredWidth: 200
}
Button{
text:qsTr("發送數據")
highlighted: true
onClicked: {
serialport.serialWrite(send.text)
}
}
}
}
注意前幾行的導入方法“import an.qt.mySerialPort 1.0”,Page前幾行中定義了我們將要使用的對象的id,在按鈕槽函數中調用對象id所包含的C++方法四、運行結果:
五、補充:
本界面風格使用的谷歌Style=Material,該風格定義在qtquickcontrols2.conf配置文件中
智能推薦
串口編程案例
前提準備 虛擬串口 串口調試助手 其他資源 模擬COM1串口發送信息到COM2接收 首先、下載虛擬串口進行安裝,安裝完后打開軟件(漢化過程忽略) 右鍵打開計算機–>管理–>設備管理器–>端口 打開VS,新建項目(Windows 應用程序) 下載串口調試助手,打開 用串口調試助手發送,效果如圖: 簡單串口編程結束!...
比特說串口編程
要說一種植物,從種子發芽開始.要說計算機,從源頭開始. 在1.X系列的文章中,我們從最開始的燈泡的例子開始,一步步深入,知道了CPU是怎么工作的,配合內存可以自動工作。 前面的內容基本上是CPU工作原理的完整輪廓了。 我們知道現在使用的各種形態的計算機除了CPU還有很多別的設備,這些所有的設備都不在CPU里面,都是外部設備,簡稱:外設。常見外設有:鍵盤,鼠...
七、Linux串口編程
Linux下的串口編程過程如下(我就不給大家再講串口是什么了,不懂得朋友自行補上串口相關知識): 目錄 一、打開串口 二、初始化串口 1、 串口的初始化結構介紹 2、串口的初始化常用函數介紹 函數 tcgetattr 波特率相關的函數 cfsetispeed 和 cfsetospeed、cfgetispeed 、cfgetospeed 函數 tcflush 函數 tcseta...
樹莓派串口編程
串口通信通常用在多機通信中 比如樹莓派和語言模塊的通信 數據在T和R之間通信,這時全雙工的 全雙工:兩個人互相罵 半雙工: 講話的時候另一個人閉嘴 通信要求:1、語言相通 ——》數據格式 2、語速正常 ——》波特率 比如用串口使用樹莓派時,選擇了115200。 數據位,停止位,奇偶校驗位就是數據格式 如果不寫驅動,就要用到wiringPi 參考如下 ...
猜你喜歡
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...
電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!
Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...
requests實現全自動PPT模板
http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...
Linux C系統編程-線程互斥鎖(四)
互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...