QT串口通信
前言:如果用qt写程序作为上位机,然后通过和usb和下位机通信的时候,就需要用到qt中的串口通信了。
使用qt中的串口通信的时候需要用到的两个头文件分别为:
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
除了加上面两个头文件之外,还需要在工程文件中加下面一行代码:
QT += serialport
我们一般都需要先定义一个全局的串口对象,记得在自己的头文件中添加上:
QSerialPort *serial;
到这里我们就可以调用qt串口通信中的函数了,一般来讲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);//设置波特率为115200
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());
主要使用的函数就这些了,我们来看看代码:
1、工程文件SerialPortTool.pro
1 #------------------------------------------------- 2 # 3 # Project created by QtCreator 2017-11-17T15:43:04 4 # 5 #------------------------------------------------- 6 7 QT += core gui 8 QT += serialport 9 10 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 11 12 TARGET = SerialPortTool 13 TEMPLATE = app 14 15 # The following define makes your compiler emit warnings if you use 16 # any feature of Qt which as been marked as deprecated (the exact warnings 17 # depend on your compiler). Please consult the documentation of the 18 # deprecated API in order to know how to port your code away from it. 19 DEFINES += QT_DEPRECATED_WARNINGS 20 21 # You can also make your code fail to compile if you use deprecated APIs. 22 # In order to do so, uncomment the following line. 23 # You can also select to disable deprecated APIs only up to a certain version of Qt. 24 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 25 26 27 SOURCES += \ 28 main.cpp \ 29 mainwindow.cpp 30 31 HEADERS += \ 32 mainwindow.h 33 34 FORMS += \ 35 mainwindow.ui
2、头文件mainwindow.h
1 #ifndef MAINWINDOW_H 2 #define MAINWINDOW_H 3 4 #include <QMainWindow> 5 #include <QDebug> 6 #include <QtSerialPort/QSerialPort> 7 #include <QtSerialPort/QSerialPortInfo> 8 9 namespace Ui { 10 class MainWindow; 11 } 12 13 class MainWindow : public QMainWindow 14 { 15 Q_OBJECT 16 17 public: 18 explicit MainWindow(QWidget *parent = 0); 19 ~MainWindow(); 20 21 private slots: 22 void on_OpenSerialButton_clicked(); 23 24 void ReadData(); 25 26 void on_SendButton_clicked(); 27 28 private: 29 Ui::MainWindow *ui; 30 QSerialPort *serial; 31 }; 32 33 #endif // MAINWINDOW_H
3、源文件mainwindow.cpp
1 #include "mainwindow.h" 2 #include "ui_mainwindow.h" 3 4 5 MainWindow::MainWindow(QWidget *parent) : 6 QMainWindow(parent), 7 ui(new Ui::MainWindow) 8 { 9 ui->setupUi(this); 10 11 //查找可用的串口 12 foreach (const QSerialPortInfo &info,QSerialPortInfo::availablePorts()) 13 { 14 QSerialPort serial; 15 serial.setPort(info); 16 if(serial.open(QIODevice::ReadWrite)) 17 { 18 ui->PortBox->addItem(serial.portName()); 19 serial.close(); 20 } 21 } 22 //设置波特率下拉菜单默认显示第0项 23 ui->BaudBox->setCurrentIndex(0); 24 25 } 26 27 MainWindow::~MainWindow() 28 { 29 delete ui; 30 } 31 32 void MainWindow::on_OpenSerialButton_clicked() 33 { 34 if(ui->OpenSerialButton->text() == tr("打开串口")) 35 { 36 serial = new QSerialPort; 37 //设置串口名 38 serial->setPortName(ui->PortBox->currentText()); 39 //打开串口 40 serial->open(QIODevice::ReadWrite); 41 //设置波特率 42 serial->setBaudRate(QSerialPort::Baud115200);//设置波特率为115200 43 //设置数据位数 44 switch (ui->BitBox->currentIndex()) 45 { 46 case 8: 47 serial->setDataBits(QSerialPort::Data8);//设置数据位8 48 break; 49 default: 50 break; 51 } 52 //设置校验位 53 switch (ui->ParityBox->currentIndex()) 54 { 55 case 0: 56 serial->setParity(QSerialPort::NoParity); 57 break; 58 default: 59 break; 60 } 61 //设置停止位 62 switch (ui->BitBox->currentIndex()) 63 { 64 case 1: 65 serial->setStopBits(QSerialPort::OneStop);//停止位设置为1 66 break; 67 case 2: 68 serial->setStopBits(QSerialPort::TwoStop); 69 default: 70 break; 71 } 72 //设置流控制 73 serial->setFlowControl(QSerialPort::NoFlowControl);//设置为无流控制 74 75 //关闭设置菜单使能 76 ui->PortBox->setEnabled(false); 77 ui->BaudBox->setEnabled(false); 78 ui->BitBox->setEnabled(false); 79 ui->ParityBox->setEnabled(false); 80 ui->StopBox->setEnabled(false); 81 ui->OpenSerialButton->setText(tr("关闭串口")); 82 83 //连接信号槽 84 QObject::connect(serial,&QSerialPort::readyRead,this,&MainWindow::ReadData); 85 } 86 else 87 { 88 //关闭串口 89 serial->clear(); 90 serial->close(); 91 serial->deleteLater(); 92 93 //恢复设置使能 94 ui->PortBox->setEnabled(true); 95 ui->BaudBox->setEnabled(true); 96 ui->BitBox->setEnabled(true); 97 ui->ParityBox->setEnabled(true); 98 ui->StopBox->setEnabled(true); 99 ui->OpenSerialButton->setText(tr("打开串口")); 100 101 } 102 103 104 105 106 } 107 //读取接收到的信息 108 void MainWindow::ReadData() 109 { 110 QByteArray buf; 111 buf = serial->readAll(); 112 if(!buf.isEmpty()) 113 { 114 QString str = ui->textEdit->toPlainText(); 115 str+=tr(buf); 116 ui->textEdit->clear(); 117 ui->textEdit->append(str); 118 119 } 120 buf.clear(); 121 } 122 123 //发送按钮槽函数 124 void MainWindow::on_SendButton_clicked() 125 { 126 serial->write(ui->textEdit_2->toPlainText().toLatin1()); 127 }
4、界面文件mainwindow.ui
1 <?xml version="1.0" encoding="UTF-8"?> 2 <ui version="4.0"> 3 <class>MainWindow</class> 4 <widget class="QMainWindow" name="MainWindow"> 5 <property name="geometry"> 6 <rect> 7 <x>0</x> 8 <y>0</y> 9 <width>547</width> 10 <height>470</height> 11 </rect> 12 </property> 13 <property name="windowTitle"> 14 <string>MainWindow</string> 15 </property> 16 <widget class="QWidget" name="centralWidget"> 17 <widget class="QLabel" name="label"> 18 <property name="geometry"> 19 <rect> 20 <x>10</x> 21 <y>50</y> 22 <width>54</width> 23 <height>12</height> 24 </rect> 25 </property> 26 <property name="text"> 27 <string>串口</string> 28 </property> 29 </widget> 30 <widget class="QLabel" name="label_2"> 31 <property name="geometry"> 32 <rect> 33 <x>10</x> 34 <y>90</y> 35 <width>54</width> 36 <height>12</height> 37 </rect> 38 </property> 39 <property name="text"> 40 <string>波特率</string> 41 </property> 42 </widget> 43 <widget class="QLabel" name="label_3"> 44 <property name="geometry"> 45 <rect> 46 <x>10</x> 47 <y>130</y> 48 <width>54</width> 49 <height>12</height> 50 </rect> 51 </property> 52 <property name="text"> 53 <string>数据位</string> 54 </property> 55 </widget> 56 <widget class="QComboBox" name="PortBox"> 57 <property name="geometry"> 58 <rect> 59 <x>100</x> 60 <y>50</y> 61 <width>69</width> 62 <height>22</height> 63 </rect> 64 </property> 65 </widget> 66 <widget class="QComboBox" name="BaudBox"> 67 <property name="geometry"> 68 <rect> 69 <x>100</x> 70 <y>90</y> 71 <width>69</width> 72 <height>22</height> 73 </rect> 74 </property> 75 <property name="currentIndex"> 76 <number>0</number> 77 </property> 78 <item> 79 <property name="text"> 80 <string>9600</string> 81 </property> 82 </item> 83 <item> 84 <property name="text"> 85 <string>19200</string> 86 </property> 87 </item> 88 <item> 89 <property name="text"> 90 <string>38400</string> 91 </property> 92 </item> 93 <item> 94 <property name="text"> 95 <string>57600</string> 96 </property> 97 </item> 98 <item> 99 <property name="text"> 100 <string>115200</string> 101 </property> 102 </item> 103 </widget> 104 <widget class="QComboBox" name="BitBox"> 105 <property name="geometry"> 106 <rect> 107 <x>100</x> 108 <y>120</y> 109 <width>69</width> 110 <height>22</height> 111 </rect> 112 </property> 113 <property name="currentIndex"> 114 <number>0</number> 115 </property> 116 <item> 117 <property name="text"> 118 <string>8</string> 119 </property> 120 </item> 121 </widget> 122 <widget class="QComboBox" name="ParityBox"> 123 <property name="geometry"> 124 <rect> 125 <x>100</x> 126 <y>160</y> 127 <width>69</width> 128 <height>22</height> 129 </rect> 130 </property> 131 <item> 132 <property name="text"> 133 <string>0</string> 134 </property> 135 </item> 136 </widget> 137 <widget class="QLabel" name="label_4"> 138 <property name="geometry"> 139 <rect> 140 <x>10</x> 141 <y>160</y> 142 <width>61</width> 143 <height>16</height> 144 </rect> 145 </property> 146 <property name="text"> 147 <string>校验位</string> 148 </property> 149 </widget> 150 <widget class="QLabel" name="label_6"> 151 <property name="geometry"> 152 <rect> 153 <x>10</x> 154 <y>200</y> 155 <width>54</width> 156 <height>12</height> 157 </rect> 158 </property> 159 <property name="text"> 160 <string>停止位</string> 161 </property> 162 </widget> 163 <widget class="QComboBox" name="StopBox"> 164 <property name="geometry"> 165 <rect> 166 <x>100</x> 167 <y>200</y> 168 <width>69</width> 169 <height>22</height> 170 </rect> 171 </property> 172 <item> 173 <property name="text"> 174 <string>1</string> 175 </property> 176 </item> 177 </widget> 178 <widget class="QPushButton" name="OpenSerialButton"> 179 <property name="geometry"> 180 <rect> 181 <x>100</x> 182 <y>240</y> 183 <width>71</width> 184 <height>23</height> 185 </rect> 186 </property> 187 <property name="text"> 188 <string>打开串口</string> 189 </property> 190 </widget> 191 <widget class="QTextEdit" name="textEdit"> 192 <property name="geometry"> 193 <rect> 194 <x>200</x> 195 <y>30</y> 196 <width>221</width> 197 <height>291</height> 198 </rect> 199 </property> 200 </widget> 201 <widget class="QTextEdit" name="textEdit_2"> 202 <property name="geometry"> 203 <rect> 204 <x>200</x> 205 <y>330</y> 206 <width>221</width> 207 <height>31</height> 208 </rect> 209 </property> 210 </widget> 211 <widget class="QPushButton" name="SendButton"> 212 <property name="geometry"> 213 <rect> 214 <x>430</x> 215 <y>330</y> 216 <width>75</width> 217 <height>31</height> 218 </rect> 219 </property> 220 <property name="text"> 221 <string>发送</string> 222 </property> 223 </widget> 224 </widget> 225 <widget class="QMenuBar" name="menuBar"> 226 <property name="geometry"> 227 <rect> 228 <x>0</x> 229 <y>0</y> 230 <width>547</width> 231 <height>23</height> 232 </rect> 233 </property> 234 </widget> 235 <widget class="QToolBar" name="mainToolBar"> 236 <attribute name="toolBarArea"> 237 <enum>TopToolBarArea</enum> 238 </attribute> 239 <attribute name="toolBarBreak"> 240 <bool>false</bool> 241 </attribute> 242 </widget> 243 <widget class="QStatusBar" name="statusBar"/> 244 </widget> 245 <layoutdefault spacing="6" margin="11"/> 246 <resources/> 247 <connections/> 248 </ui>
效果图如下,自己设置对应下位机的波特率就可以实现数据收发了
这里注意一下,使用串口通信的时候是按字节发送的,所以如果你定义一个char buff[10],而且你想这样定义buff[0] = '255'发送255这个字符给下位机的时候,下位机是接收不完整的,经过测试发现发送大于或等于10的字符是会被截断的,只会留下最后一个字符,比如说发送10字符的时候,下位机很有可能只能接收到0这个字符,当然如果想要完整的发送过去的话可以定义成字符串形式。比如char buff[] ="255",这样就可以发送一个完整的255过去了,但是需要注意的是这是一个字符串不是一个字符,所以如果你在下位机如果要根据上位机发送的数据来处理一些事情的时候一定要清楚你发送的是字符还是字符串。