1. 程式人生 > >Qt實踐(二)——實現串列埠通訊

Qt實踐(二)——實現串列埠通訊

如果用Qt寫程式作為上位機,然後通過和usb和下位機通訊的時候,就需要用到Qt中的串列埠通訊了。

使用Qt中的串列埠通訊的時候需要用到的兩個標頭檔案分別為:

#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>

除了加上面兩個標頭檔案之外,還需要在工程檔案中加下面一行程式碼:

QT       += serialport

一般都需要先定義一個全域性的串列埠物件,在標頭檔案中新增上:

QSerialPort *serial;

一般來講Qt串列埠通訊需要經過7步:

1、設定串列埠名(如COM1):

serial = new QSerialPort;
serial->setPortName(ui->PortBox->currentText());

也可以用自動尋找可用串列埠的方法進行自動設定:

foreach (const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
{
        QSerialPort serial;
        serial.setPort(info);
        if(serial.open(QIODevice::ReadWrite))
        {
            ui->PortBox->addItem(serial.portName());
            serial.close();
        }
}

2、開啟串列埠

serial->open(QIODevice::ReadWrite);

3、設定波特率(如115200)

serial->setBaudRate(QSerialPort::Baud115200);

4、設定資料位(如8)

 serial->setDataBits(QSerialPort::Data8);//設定資料位8

5、設定校驗位(如0)

serial->setParity(QSerialPort::NoParity); //校驗位設定為0

6、設定停止位(如1)

serial->setStopBits(QSerialPort::OneStop);//停止位設定為1

7、設定流控制

 serial->setFlowControl(QSerialPort::NoFlowControl);//設定為無流控制

下面是對資料的傳送和接收:

1、連線資料接收槽函式,下位機中一有資料傳送過來的時候就會響應這個槽函式

QObject::connect(serial,&QSerialPort::readyRead,this,&MainWindow::ReadData);

2、從上位機發送資料到下位機

serial->write(ui->textEdit_2->toPlainText().toLatin1());

下面是完整的工程檔案:

demo.pro:

#-------------------------------------------------
#
# Project created by QtCreator 2018-10-01T15:23:39
#
#-------------------------------------------------

QT       += core gui
QT       += serialport

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = demo
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0


SOURCES += \
        main.cpp \
        mainwindow.cpp

HEADERS += \
        mainwindow.h

FORMS += \
        mainwindow.ui

mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDebug>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void on_OpenSerialButton_clicked();

    void ReadData();

    void on_SendButton_clicked();

    void on_ClearButton_clicked();

private:
    Ui::MainWindow *ui;
    QSerialPort *serial;
};

#endif // MAINWINDOW_H

mainwindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //查詢可用的串列埠
    foreach (const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
    {
        QSerialPort serial;
        serial.setPort(info);
        if(serial.open(QIODevice::ReadWrite))
        {
            ui->PortBox->addItem(serial.portName());
            serial.close();
        }
    }
    //設定波特率下拉選單預設顯示第0項
    ui->BaudBox->setCurrentIndex(0);

}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_OpenSerialButton_clicked()
{
    if(ui->OpenSerialButton->text() == tr("開啟串列埠"))
    {
        serial = new QSerialPort;
        //設定串列埠名
        serial->setPortName(ui->PortBox->currentText());
        //開啟串列埠
        serial->open(QIODevice::ReadWrite);
        //設定波特率
        serial->setBaudRate(QSerialPort::Baud115200);//設定波特率為115200
        //設定資料位數
        switch (ui->BitBox->currentIndex())
        {
        case 8:
            serial->setDataBits(QSerialPort::Data8);//設定資料位8
            break;
        default:
            break;
        }
        //設定校驗位
        switch (ui->ParityBox->currentIndex())
        {
        case 0:
            serial->setParity(QSerialPort::NoParity);
            break;
        default:
            break;
        }
        //設定停止位
        switch (ui->BitBox->currentIndex())
        {
        case 1:
            serial->setStopBits(QSerialPort::OneStop);//停止位設定為1
            break;
        case 2:
            serial->setStopBits(QSerialPort::TwoStop);
        default:
            break;
        }
        //設定流控制
        serial->setFlowControl(QSerialPort::NoFlowControl);//設定為無流控制

        //關閉設定選單使能
        ui->PortBox->setEnabled(false);
        ui->BaudBox->setEnabled(false);
        ui->BitBox->setEnabled(false);
        ui->ParityBox->setEnabled(false);
        ui->StopBox->setEnabled(false);
        ui->OpenSerialButton->setText(tr("關閉串列埠"));

        //連線訊號槽
        QObject::connect(serial,&QSerialPort::readyRead,this,&MainWindow::ReadData);
    }
    else
    {
        //關閉串列埠
        serial->clear();
        serial->close();
        serial->deleteLater();

        //恢復設定使能
        ui->PortBox->setEnabled(true);
        ui->BaudBox->setEnabled(true);
        ui->BitBox->setEnabled(true);
        ui->ParityBox->setEnabled(true);
        ui->StopBox->setEnabled(true);
        ui->OpenSerialButton->setText(tr("開啟串列埠"));

    }




}
//讀取接收到的資訊
void MainWindow::ReadData()
{
    QByteArray buf;
    buf = serial->readAll();
    if(!buf.isEmpty())
    {
        QString str = ui->textEdit->toPlainText();
        str+=tr(buf);
        ui->textEdit->clear();
        ui->textEdit->append(str);

    }
    buf.clear();
}

//傳送按鈕槽函式
void MainWindow::on_SendButton_clicked()
{
    serial->write(ui->textEdit_2->toPlainText().toLatin1());
}

void MainWindow::on_ClearButton_clicked()
{
    ui->textEdit->clear();
}

main.cpp:

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

mainwindow.ui(程式碼不能直接編輯,需要通過Ui介面來進行編輯):

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>568</width>
    <height>526</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralWidget">
   <widget class="QPushButton" name="OpenSerialButton">
    <property name="geometry">
     <rect>
      <x>90</x>
      <y>400</y>
      <width>111</width>
      <height>61</height>
     </rect>
    </property>
    <property name="text">
     <string>開啟串列埠</string>
    </property>
   </widget>
   <widget class="QTextEdit" name="textEdit">
    <property name="geometry">
     <rect>
      <x>220</x>
      <y>10</y>
      <width>191</width>
      <height>301</height>
     </rect>
    </property>
   </widget>
   <widget class="QPushButton" name="SendButton">
    <property name="geometry">
     <rect>
      <x>430</x>
      <y>340</y>
      <width>131</width>
      <height>61</height>
     </rect>
    </property>
    <property name="text">
     <string>傳送</string>
    </property>
   </widget>
   <widget class="QLabel" name="label">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>10</y>
      <width>61</width>
      <height>51</height>
     </rect>
    </property>
    <property name="text">
     <string>串列埠</string>
    </property>
   </widget>
   <widget class="QLabel" name="label_3">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>130</y>
      <width>71</width>
      <height>41</height>
     </rect>
    </property>
    <property name="text">
     <string>資料位</string>
    </property>
   </widget>
   <widget class="QLabel" name="label_4">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>190</y>
      <width>71</width>
      <height>31</height>
     </rect>
    </property>
    <property name="text">
     <string>校驗位</string>
    </property>
   </widget>
   <widget class="QLabel" name="label_5">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>260</y>
      <width>71</width>
      <height>41</height>
     </rect>
    </property>
    <property name="text">
     <string>停止位</string>
    </property>
   </widget>
   <widget class="QLabel" name="label_2">
    <property name="geometry">
     <rect>
      <x>10</x>
      <y>70</y>
      <width>61</width>
      <height>41</height>
     </rect>
    </property>
    <property name="text">
     <string>波特率</string>
    </property>
   </widget>
   <widget class="QComboBox" name="PortBox">
    <property name="geometry">
     <rect>
      <x>90</x>
      <y>10</y>
      <width>111</width>
      <height>41</height>
     </rect>
    </property>
   </widget>
   <widget class="QComboBox" name="BaudBox">
    <property name="geometry">
     <rect>
      <x>90</x>
      <y>70</y>
      <width>111</width>
      <height>41</height>
     </rect>
    </property>
    <item>
     <property name="text">
      <string>9600</string>
     </property>
    </item>
    <item>
     <property name="text">
      <string>19200</string>
     </property>
    </item>
    <item>
     <property name="text">
      <string>38400</string>
     </property>
    </item>
    <item>
     <property name="text">
      <string>57600</string>
     </property>
    </item>
    <item>
     <property name="text">
      <string>115200</string>
     </property>
    </item>
   </widget>
   <widget class="QComboBox" name="BitBox">
    <property name="geometry">
     <rect>
      <x>90</x>
      <y>130</y>
      <width>111</width>
      <height>41</height>
     </rect>
    </property>
    <item>
     <property name="text">
      <string>8</string>
     </property>
    </item>
   </widget>
   <widget class="QComboBox" name="ParityBox">
    <property name="geometry">
     <rect>
      <x>90</x>
      <y>190</y>
      <width>111</width>
      <height>41</height>
     </rect>
    </property>
    <item>
     <property name="text">
      <string>0</string>
     </property>
    </item>
   </widget>
   <widget class="QComboBox" name="StopBox">
    <property name="geometry">
     <rect>
      <x>90</x>
      <y>260</y>
      <width>111</width>
      <height>41</height>
     </rect>
    </property>
    <item>
     <property name="text">
      <string>1</string>
     </property>
    </item>
   </widget>
   <widget class="QTextEdit" name="textEdit_2">
    <property name="geometry">
     <rect>
      <x>220</x>
      <y>340</y>
      <width>191</width>
      <height>61</height>
     </rect>
    </property>
   </widget>
   <widget class="QPushButton" name="ClearButton">
    <property name="geometry">
     <rect>
      <x>90</x>
      <y>320</y>
      <width>111</width>
      <height>61</height>
     </rect>
    </property>
    <property name="text">
     <string>清空接收區</string>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menuBar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>568</width>
     <height>17</height>
    </rect>
   </property>
  </widget>
  <widget class="QToolBar" name="mainToolBar">
   <attribute name="toolBarArea">
    <enum>TopToolBarArea</enum>
   </attribute>
   <attribute name="toolBarBreak">
    <bool>false</bool>
   </attribute>
  </widget>
  <widget class="QStatusBar" name="statusBar"/>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources/>
 <connections/>
</ui>

上面就是執行的結果。