QT串口通信的實(shí)現(xiàn)方法
前言:如果用qt寫(xiě)程序作為上位機(jī),然后通過(guò)和usb和下位機(jī)通信的時(shí)候,就需要用到qt中的串口通信了。
使用qt中的串口通信的時(shí)候需要用到的兩個(gè)頭文件分別為:
#include <QtSerialPort/QSerialPort> #include <QtSerialPort/QSerialPortInfo>
除了加上面兩個(gè)頭文件之外,還需要在工程文件中加下面一行代碼:
QT += serialport
我們一般都需要先定義一個(gè)全局的串口對(duì)象,記得在自己的頭文件中添加上:
QSerialPort *serial;
到這里我們就可以調(diào)用qt串口通信中的函數(shù)了,一般來(lái)講qt串口通信需要經(jīng)過(guò)7步:
1、設(shè)置串口名(如COM1)
serial = new QSerialPort; serial->setPortName(ui->PortBox->currentText());
這里我使用自動(dòng)尋找可用串口的方法,直接自動(dòng)設(shè)置了
foreach (const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
{
QSerialPort serial;
serial.setPort(info);
if(serial.open(QIODevice::ReadWrite))
{
ui->PortBox->addItem(serial.portName());
serial.close();
}
}
2、打開(kāi)串口
serial->open(QIODevice::ReadWrite);
3、設(shè)置波特率(如115200)
serial->setBaudRate(QSerialPort::Baud115200);//設(shè)置波特率為115200
4、設(shè)置數(shù)據(jù)位(如8)
serial->setDataBits(QSerialPort::Data8);//設(shè)置數(shù)據(jù)位8
5、設(shè)置校驗(yàn)位(如0)
serial->setParity(QSerialPort::NoParity); //校驗(yàn)位設(shè)置為0
6、設(shè)置停止位(如1)
serial->setStopBits(QSerialPort::OneStop);//停止位設(shè)置為1
7、設(shè)置流控制
serial->setFlowControl(QSerialPort::NoFlowControl);//設(shè)置為無(wú)流控制
到這里串口通信的設(shè)置就完成了,下面我們需要實(shí)現(xiàn)對(duì)數(shù)據(jù)的發(fā)送和接收
1、連接數(shù)據(jù)接收槽函數(shù),下位機(jī)中一有數(shù)據(jù)發(fā)送過(guò)來(lái)的時(shí)候就會(huì)響應(yīng)這個(gè)槽函數(shù)
QObject::connect(serial,&QSerialPort::readyRead,this,&MainWindow::ReadData);
2、從上位機(jī)發(fā)送數(shù)據(jù)到下位機(jī)
serial->write(ui->textEdit_2->toPlainText().toLatin1());
主要使用的函數(shù)就這些了,我們來(lái)看看代碼:
1、工程文件SerialPortTool.pro
#-------------------------------------------------
#
# Project created by QtCreator 2017-11-17T15:43:04
#
#-------------------------------------------------
QT += core gui
QT += serialport
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = SerialPortTool
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as 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
2、頭文件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();
private:
Ui::MainWindow *ui;
QSerialPort *serial;
};
#endif // MAINWINDOW_H
3、源文件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();
}
}
//設(shè)置波特率下拉菜單默認(rèn)顯示第0項(xiàng)
ui->BaudBox->setCurrentIndex(0);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_OpenSerialButton_clicked()
{
if(ui->OpenSerialButton->text() == tr("打開(kāi)串口"))
{
serial = new QSerialPort;
//設(shè)置串口名
serial->setPortName(ui->PortBox->currentText());
//打開(kāi)串口
serial->open(QIODevice::ReadWrite);
//設(shè)置波特率
serial->setBaudRate(QSerialPort::Baud115200);//設(shè)置波特率為115200
//設(shè)置數(shù)據(jù)位數(shù)
switch (ui->BitBox->currentIndex())
{
case 8:
serial->setDataBits(QSerialPort::Data8);//設(shè)置數(shù)據(jù)位8
break;
default:
break;
}
//設(shè)置校驗(yàn)位
switch (ui->ParityBox->currentIndex())
{
case 0:
serial->setParity(QSerialPort::NoParity);
break;
default:
break;
}
//設(shè)置停止位
switch (ui->BitBox->currentIndex())
{
case 1:
serial->setStopBits(QSerialPort::OneStop);//停止位設(shè)置為1
break;
case 2:
serial->setStopBits(QSerialPort::TwoStop);
default:
break;
}
//設(shè)置流控制
serial->setFlowControl(QSerialPort::NoFlowControl);//設(shè)置為無(wú)流控制
//關(guān)閉設(shè)置菜單使能
ui->PortBox->setEnabled(false);
ui->BaudBox->setEnabled(false);
ui->BitBox->setEnabled(false);
ui->ParityBox->setEnabled(false);
ui->StopBox->setEnabled(false);
ui->OpenSerialButton->setText(tr("關(guān)閉串口"));
//連接信號(hào)槽
QObject::connect(serial,&QSerialPort::readyRead,this,&MainWindow::ReadData);
}
else
{
//關(guān)閉串口
serial->clear();
serial->close();
serial->deleteLater();
//恢復(fù)設(shè)置使能
ui->PortBox->setEnabled(true);
ui->BaudBox->setEnabled(true);
ui->BitBox->setEnabled(true);
ui->ParityBox->setEnabled(true);
ui->StopBox->setEnabled(true);
ui->OpenSerialButton->setText(tr("打開(kāi)串口"));
}
}
//讀取接收到的信息
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();
}
//發(fā)送按鈕槽函數(shù)
void MainWindow::on_SendButton_clicked()
{
serial->write(ui->textEdit_2->toPlainText().toLatin1());
}
4、界面文件mainwindow.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>547</width>
<height>470</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>10</x>
<y>50</y>
<width>54</width>
<height>12</height>
</rect>
</property>
<property name="text">
<string>串口</string>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>10</x>
<y>90</y>
<width>54</width>
<height>12</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>54</width>
<height>12</height>
</rect>
</property>
<property name="text">
<string>數(shù)據(jù)位</string>
</property>
</widget>
<widget class="QComboBox" name="PortBox">
<property name="geometry">
<rect>
<x>100</x>
<y>50</y>
<width>69</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QComboBox" name="BaudBox">
<property name="geometry">
<rect>
<x>100</x>
<y>90</y>
<width>69</width>
<height>22</height>
</rect>
</property>
<property name="currentIndex">
<number>0</number>
</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>100</x>
<y>120</y>
<width>69</width>
<height>22</height>
</rect>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<item>
<property name="text">
<string>8</string>
</property>
</item>
</widget>
<widget class="QComboBox" name="ParityBox">
<property name="geometry">
<rect>
<x>100</x>
<y>160</y>
<width>69</width>
<height>22</height>
</rect>
</property>
<item>
<property name="text">
<string>0</string>
</property>
</item>
</widget>
<widget class="QLabel" name="label_4">
<property name="geometry">
<rect>
<x>10</x>
<y>160</y>
<width>61</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>校驗(yàn)位</string>
</property>
</widget>
<widget class="QLabel" name="label_6">
<property name="geometry">
<rect>
<x>10</x>
<y>200</y>
<width>54</width>
<height>12</height>
</rect>
</property>
<property name="text">
<string>停止位</string>
</property>
</widget>
<widget class="QComboBox" name="StopBox">
<property name="geometry">
<rect>
<x>100</x>
<y>200</y>
<width>69</width>
<height>22</height>
</rect>
</property>
<item>
<property name="text">
<string>1</string>
</property>
</item>
</widget>
<widget class="QPushButton" name="OpenSerialButton">
<property name="geometry">
<rect>
<x>100</x>
<y>240</y>
<width>71</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>打開(kāi)串口</string>
</property>
</widget>
<widget class="QTextEdit" name="textEdit">
<property name="geometry">
<rect>
<x>200</x>
<y>30</y>
<width>221</width>
<height>291</height>
</rect>
</property>
</widget>
<widget class="QTextEdit" name="textEdit_2">
<property name="geometry">
<rect>
<x>200</x>
<y>330</y>
<width>221</width>
<height>31</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="SendButton">
<property name="geometry">
<rect>
<x>430</x>
<y>330</y>
<width>75</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>發(fā)送</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>547</width>
<height>23</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>
效果圖如下,自己設(shè)置對(duì)應(yīng)下位機(jī)的波特率就可以實(shí)現(xiàn)數(shù)據(jù)收發(fā)了

這里注意一下,使用串口通信的時(shí)候是按字節(jié)發(fā)送的,所以如果你定義一個(gè)char buff[10],而且你想這樣定義buff[0] = '255'發(fā)送255這個(gè)字符給下位機(jī)的時(shí)候,下位機(jī)是接收不完整的,經(jīng)過(guò)測(cè)試發(fā)現(xiàn)發(fā)送大于或等于10的字符是會(huì)被截?cái)嗟?,只?huì)留下最后一個(gè)字符,比如說(shuō)發(fā)送10字符的時(shí)候,下位機(jī)很有可能只能接收到0這個(gè)字符,當(dāng)然如果想要完整的發(fā)送過(guò)去的話可以定義成字符串形式。比如char buff[] ="255",這樣就可以發(fā)送一個(gè)完整的255過(guò)去了,但是需要注意的是這是一個(gè)字符串不是一個(gè)字符,所以如果你在下位機(jī)如果要根據(jù)上位機(jī)發(fā)送的數(shù)據(jù)來(lái)處理一些事情的時(shí)候一定要清楚你發(fā)送的是字符還是字符串。
到此這篇關(guān)于QT串口通信的實(shí)現(xiàn)方法的文章就介紹到這了,更多相關(guān)QT串口通信內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
介紹C語(yǔ)言中tolower函數(shù)的實(shí)例
這篇文章主要介紹了介紹C語(yǔ)言中tolower函數(shù)的實(shí)例,本文列出了該函數(shù)的頭文件,功能說(shuō)明等,以及如何使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
C++中vector的實(shí)現(xiàn)方法示例詳解
這篇文章主要介紹了C++中vector實(shí)現(xiàn)的相關(guān)資料,vector是C++中重要的容器之一,底層通過(guò)三個(gè)迭代器實(shí)現(xiàn),分別是_start,?_finish,?和_end_of_storage,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-10-10
C語(yǔ)言內(nèi)存函數(shù) memcpy,memmove ,memcmp
這篇文章主要介紹了C語(yǔ)言內(nèi)存函數(shù) memcpy,memmove ,memcmp,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-09-09
C語(yǔ)言實(shí)現(xiàn)學(xué)生檔案管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)學(xué)生檔案管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
C++計(jì)算任意權(quán)值的單源最短路徑(Bellman-Ford)
這篇文章主要為大家詳細(xì)介紹了C++計(jì)算任意權(quán)值的單源最短路徑,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-04-04

