【Qt5.8】Qt5.8中串口类QSerialPort
00. 目錄
- 00. 目錄
- 01. 串口通信基礎
- 02. QtSerialPort模塊簡介
- 03. QSerialPort簡介
- 04. QSerialPort類成員函數
- 05. 參考示例(簡單的串口示例)
- 06. 圖形界面設計
- 07. 測試結果
01. 串口通信基礎
串口通信(Serial Communications)的概念非常簡單,串口按位(bit)發送和接收字節。盡管比按字節(byte)的并行通信慢,但是串口可以在使用一根線發送數據的同時用另一根線接收數據。它很簡單并且能夠實現遠距離通信。比如IEEE488定義并行通行狀態時,規定設備線總長不得超過20米,并且任意兩個設備間的長度不得超過2米;而對于串口而言,長度可達1200米。典型地,串口用于ASCII碼字符的傳輸。通信使用3根線完成,分別是地線、發送、接收。由于串口通信是異步的,端口能夠在一根線上發送數據同時在另一根線上接收數據。其他線用于握手,但不是必須的。串口通信最重要的參數是波特率、數據位、停止位和奇偶校驗。對于兩個進行通信的端口,這些參數必須匹配。
a,波特率:這是一個衡量符號傳輸速率的參數。指的是信號被調制以后在單位時間內的變化,即單位時間內載波參數變化的次數,如每秒鐘傳送240個字符,而每個字符格式包含10位(1個起始位,1個停止位,8個數據位),這時的波特率為240Bd,比特率為10位*240個/秒=2400bps。一般調制速率大于波特率,比如曼徹斯特編碼)。通常電話線的波特率為14400,28800和36600。波特率可以遠遠大于這些值,但是波特率和距離成反比。高波特率常常用于放置的很近的儀器間的通信,典型的例子就是GPIB設備的通信。
b,數據位:這是衡量通信中實際數據位的參數。當計算機發送一個信息包,實際的數據往往不會是8位的,標準的值是6、7和8位。如何設置取決于你想傳送的信息。比如,標準的ASCII碼是0~127(7位)。擴展的ASCII碼是0~255(8位)。如果數據使用簡單的文本(標準 ASCII碼),那么每個數據包使用7位數據。每個包是指一個字節,包括開始/停止位,數據位和奇偶校驗位。由于實際數據位取決于通信協議的選取,術語“包”指任何通信的情況。
c,停止位:用于表示單個包的最后一位。典型的值為1,1.5和2位。由于數據是在傳輸線上定時的,并且每一個設備有其自己的時鐘,很可能在通信中兩臺設備間出現了小小的不同步。因此停止位不僅僅是表示傳輸的結束,并且提供計算機校正時鐘同步的機會。適用于停止位的位數越多,不同時鐘同步的容忍程度越大,但是數據傳輸率同時也越慢。
d,奇偶校驗位:在串口通信中一種簡單的檢錯方式。有四種檢錯方式:偶、奇、高和低。當然沒有校驗位也是可以的。對于偶和奇校驗的情況,串口會設置校驗位(數據位后面的一位),用一個值確保傳輸的數據有偶個或者奇個邏輯高位。例如,如果數據是011,那么對于偶校驗,校驗位為0,保證邏輯高的位數是偶數個。如果是奇校驗,校驗位為1,這樣就有3個邏輯高位。高位和低位不真正的檢查數據,簡單置位邏輯高或者邏輯低校驗。這樣使得接收設備能夠知道一個位的狀態,有機會判斷是否有噪聲干擾了通信或者是否傳輸和接收數據是否不同步。
來源:百度百科
02. QtSerialPort模塊簡介
QtSerialPort模塊是QT5中附加模塊的一個模塊,為硬件和虛擬的串口提供統一的接口。
串口由于其簡單和可靠,目前在像嵌入式系統、機器人等工業中依舊用得很多。使用QtSerialPort模塊,開發者可以大大縮短開發串口相關的應用程的周期。
Qt SerialPort提供了基本的功能,包括配置、I/O操作、獲取和設置RS-232引腳的信號。
Qt SerialPort模塊暫不支持以下特性:
A、終端的特性,例如回顯,控制CR/LF等等
B、文本模式
C、讀或寫操作的超時和延時配置
D、當RS-232引腳信號變化通知
要在應用程序中使用QtSerialPort,需要包括如下的聲明:
#include <QtSerialPort/QtSerialPort>
要鏈接QtSerialPort模塊,需要在.pro文件中添加如下內容:
QT += serialport
03. QSerialPort簡介
QSerialPort提供了訪問串口的接口函數。使用輔助類QSerialPortInfo可以獲取可用的串口信息。將QSerialPortInfo輔助類對象做為參數,使用setPort()或setPortName()函數可以設置要訪問的串口設備。
設置好端口后,可以使用open()函數以只讀、只寫或讀寫的模式打開使用。
注意,串口使用獨占方式打開。使用close()函數關閉串口并且取消IO操作。
串口成功打開后,QSerialPort會嘗試確定串口的當前配置并初始化。可以使用setBaudRate()、setDataBits()、setParity()、setStopBits()和setFlowControl()函數重新配置端口設置。
有一對名為QSerialPort::dataTerminalReady、QSerialPort::requestToSend的屬性
QSerialPort提供了中止正在調用線程直到信號觸發的一系列函數。這些函數用于阻塞串口。
waitForReadyRead():阻塞調用,直到有新的數據可讀
waitForBytesWritten():阻塞調用,直到數據以及寫入串口
阻塞串口編程與非阻塞串口編程完全不同。阻塞串口不會要求時間循環并且通常會簡化代碼。然而,在GUI程序中,為了避免凍結用戶界面,阻塞串口編程只能用于非GUI線程。
QSerialPort也能使用QTextStream和QDataStream的流操作符。在試圖使用流操作符>>讀時,需要確保有足夠可用的數據。
04. QSerialPort類成員函數
//構造函數 QSerialPort::QSerialPort(QObject *parent = Q_NULLPTR) QSerialPort::QSerialPort(const QString &name, QObject *parent = Q_NULLPTR) QSerialPort::QSerialPort(const QSerialPortInfo &serialPortInfo, QObject *parent = Q_NULLPTR)//如果當前沒有數據可讀,返回true [virtual] bool QSerialPort::atEnd() const//波特率改變后,信號觸發 [signal] void QSerialPort::baudRateChanged(qint32 baudRate, QSerialPort::Directions directions)//返回可讀數據的字節數 [virtual] qint64 QSerialPort::bytesAvailable() const//返回可寫數據的字節數 [virtual] qint64 QSerialPort::bytesToWrite() const//關閉串口 [virtual] void QSerialPort::close()//設置串口端口信息為serialPortInfo void QSerialPort::setPort(const QSerialPortInfo &serialPortInfo)//設置串口名為name void QSerialPort::setPortName(const QString &name)05. 參考示例(簡單的串口示例)
main.cpp代碼
#include "mainwindow.h" #include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv);MainWindow w;w.show();return a.exec(); }mainwindows.h代碼參考如下:
#ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QtSerialPort/QSerialPort> #include <QtSerialPort/QSerialPortInfo> #include <QList> #include <QDebug>namespace Ui { class MainWindow; }class MainWindow : public QMainWindow {Q_OBJECTpublic:explicit MainWindow(QWidget *parent = 0);~MainWindow();private slots:void on_btn_openConsole_clicked();void on_btn_send_clicked();void on_btn_clearRecv_clicked();void on_btn_clearSend_clicked();void readData();private:Ui::MainWindow *ui;QSerialPort *serial; };#endif // MAINWINDOW_Hmainwindows.cpp代碼
#include "mainwindow.h" #include "ui_mainwindow.h"static const char blankString[] = QT_TRANSLATE_NOOP("SettingsDialog", "N/A");MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow) {ui->setupUi(this);serial = new QSerialPort;QString description;QString manufacturer;QString serialNumber;//獲取可以用的串口QList<QSerialPortInfo> serialPortInfos = QSerialPortInfo::availablePorts();//輸出當前系統可以使用的串口個數qDebug() << "Total numbers of ports: " << serialPortInfos.count();//將所有可以使用的串口設備添加到ComboBox中for (const QSerialPortInfo &serialPortInfo : serialPortInfos){QStringList list;description = serialPortInfo.description();manufacturer = serialPortInfo.manufacturer();serialNumber = serialPortInfo.serialNumber();list << serialPortInfo.portName()<< (!description.isEmpty() ? description : blankString)<< (!manufacturer.isEmpty() ? manufacturer : blankString)<< (!serialNumber.isEmpty() ? serialNumber : blankString)<< serialPortInfo.systemLocation()<< (serialPortInfo.vendorIdentifier() ? QString::number(serialPortInfo.vendorIdentifier(), 16) : blankString)<< (serialPortInfo.productIdentifier() ? QString::number(serialPortInfo.productIdentifier(), 16) : blankString);ui->comboBox_serialPort->addItem(list.first(), list);}ui->comboBox_serialPort->addItem(tr("custom"));//設置波特率ui->comboBox_baudRate->addItem(QStringLiteral("9600"), QSerialPort::Baud9600);ui->comboBox_baudRate->addItem(QStringLiteral("19200"), QSerialPort::Baud19200);ui->comboBox_baudRate->addItem(QStringLiteral("38400"), QSerialPort::Baud38400);ui->comboBox_baudRate->addItem(QStringLiteral("115200"), QSerialPort::Baud115200);ui->comboBox_baudRate->addItem(tr("Custom"));//設置數據位ui->comboBox_dataBits->addItem(QStringLiteral("5"), QSerialPort::Data5);ui->comboBox_dataBits->addItem(QStringLiteral("6"), QSerialPort::Data6);ui->comboBox_dataBits->addItem(QStringLiteral("7"), QSerialPort::Data7);ui->comboBox_dataBits->addItem(QStringLiteral("8"), QSerialPort::Data8);ui->comboBox_dataBits->setCurrentIndex(3);//設置奇偶校驗位ui->comboBox_parity->addItem(tr("None"), QSerialPort::NoParity);ui->comboBox_parity->addItem(tr("Even"), QSerialPort::EvenParity);ui->comboBox_parity->addItem(tr("Odd"), QSerialPort::OddParity);ui->comboBox_parity->addItem(tr("Mark"), QSerialPort::MarkParity);ui->comboBox_parity->addItem(tr("Space"), QSerialPort::SpaceParity);//設置停止位ui->comboBox_stopBit->addItem(QStringLiteral("1"), QSerialPort::OneStop);ui->comboBox_stopBit->addItem(QStringLiteral("2"), QSerialPort::TwoStop);//添加流控ui->comboBox_flowBit->addItem(tr("None"), QSerialPort::NoFlowControl);ui->comboBox_flowBit->addItem(tr("RTS/CTS"), QSerialPort::HardwareControl);ui->comboBox_flowBit->addItem(tr("XON/XOFF"), QSerialPort::SoftwareControl);//禁用發送按鈕ui->btn_send->setEnabled(false); }MainWindow::~MainWindow() {//delete serial;delete ui;}//打開串口按鈕槽函數 void MainWindow::on_btn_openConsole_clicked() {qDebug() << ui->btn_openConsole->text();if (ui->btn_openConsole->text() == tr("打開串口")){//設置串口名字serial->setPortName(ui->comboBox_serialPort->currentText());//設置波特率serial->setBaudRate(ui->comboBox_baudRate->currentText().toInt());//設置數據位serial->setDataBits(QSerialPort::Data8);//設置奇偶校驗位serial->setParity(QSerialPort::NoParity);//設置停止位serial->setStopBits(QSerialPort::OneStop);//設置流控serial->setFlowControl(QSerialPort::NoFlowControl);//打開串口if (serial->open(QIODevice::ReadWrite)){ui->comboBox_baudRate->setEnabled(false);ui->comboBox_dataBits->setEnabled(false);ui->comboBox_flowBit->setEnabled(false);ui->comboBox_parity->setEnabled(false);ui->comboBox_serialPort->setEnabled(false);ui->comboBox_stopBit->setEnabled(false);ui->btn_send->setEnabled(true);ui->btn_openConsole->setText(tr("關閉串口"));//信號與槽函數關聯connect(serial, &QSerialPort::readyRead, this, &MainWindow::readData);}}else{//關閉串口//serial->clear();serial->close();//serial->deleteLater();//恢復設置功能ui->comboBox_baudRate->setEnabled(true);ui->comboBox_dataBits->setEnabled(true);ui->comboBox_flowBit->setEnabled(true);ui->comboBox_parity->setEnabled(true);ui->comboBox_serialPort->setEnabled(true);ui->comboBox_stopBit->setEnabled(true);ui->btn_openConsole->setText(tr("打開串口"));ui->btn_send->setEnabled(false);}}//發送數據槽函數 void MainWindow::on_btn_send_clicked() {serial->write(ui->textEdit_send->toPlainText().toLatin1());}//清空接收數據槽函數 void MainWindow::on_btn_clearRecv_clicked() {ui->textEdit_recv->clear(); }//清空發送區槽函數 void MainWindow::on_btn_clearSend_clicked() {ui->textEdit_send->clear(); }void MainWindow::readData() {QByteArray buf;qDebug() << "readData: " << endl;buf = serial->readAll();if (!buf.isEmpty()){QString str = ui->textEdit_recv->toPlainText();str += tr(buf);ui->textEdit_recv->clear();ui->textEdit_recv->append(str);} }06. 圖形界面設計
圖形界面設計如圖所示:
圖形界面相關屬性設置:
07. 測試結果
前提條件是需要串口硬件的支持
程序下載:百度云盤
總結
以上是生活随笔為你收集整理的【Qt5.8】Qt5.8中串口类QSerialPort的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Qt5.8】Qt5.8中串口信息类QS
- 下一篇: 【Qt5.8】Qt5.8中QTableW