QT5实现串口收发数据(上位机与下位机通信)

it2022-05-05  128

最近帮老师做一个应用程序,通过上位机与下位机进行串口通信,最后实现实时绘图,通过几天努力,成功实现蓝牙串口通信。 参考博客1

注意:代码中一些与串口无关代码,可以忽略掉

一、QT5串口基础知识

1. pro文件与cpp文件

QT5自带QSerialPort这个类的,需要在pro文件中添加(不添加会报错):

QT += serialport

其他CPP需要引用该类

#include <QSerialPort> //提供访问串口的功能 #include <QSerialPortInfo> //提供系统中存在的串口的信息

2. 基本串口设置

//创建串口对象 QSerialPort serial; //设置串口名称 serial.setPortName("COM3"); //设置波特率 serial.setBaudRate(QSerialPort::Baud9600); //设置数据位 serial.setDataBits(QSerialPort::Data8); //设置是否奇偶校验 serial.setParity(QSerialPort::NoParity); //设置停止位 serial.setStopBits(QSerialPort::OneStop); //设置是否流控制 serial.setFlowControl(QSerialPort::NoFlowControl); //打开串口—可读可写地打开 serial.open(QIODevice::ReadWrite); //关闭串口 serial->close();

如果对一些类或者成员不懂可以鼠标移上去按F1查看手册,按两次直接全屏。

3. 收发数据

读取数据:

QByteArray buffer = serial.readAll();//读取数据到缓冲数组中

发送数据:

serial->write(data);//将数据发送到串口

二、QT5串口实例

1. h文件

#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QImage> #include <QLabel> #include <QMenu> #include <QMenuBar> #include <QAction> #include <QComboBox> #include <QSpinBox> #include <QToolBar> #include <QFontComboBox> #include <QToolButton> #include <QStatusBar> #include <QTextCharFormat> #include <QDockWidget> #include <QStackedWidget> #include <QPushButton> #include <QVBoxLayout> #include <QButtonGroup> #include <QGraphicsScene> #include <QGraphicsView> #include <QGraphicsEllipseItem> #include <QTableWidget> #include <QtSerialPort/QSerialPort> //#include <QtCharts/QXYSeries> #include "showwidget.h" class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = 0); ~MainWindow(); void createActions(); //创建动作 void createMenus(); //创建菜单 void createToolBars(); //创建工具栏 void createStatusBars(); //创建状态栏 void loadFile(QString filename); //?? void mergeFormat(QTextCharFormat); //?? void setvariables(); //设置调试参数 void startDeviceDiscovery(); void deviceDiscovered(); void bluetooth(); void statusOfAll(); private: //基本布局 QGraphicsScene *scene; QStackedWidget *Stack1; QMenu *fileMenu; QMenu *zoomMenu; QImage img; QString filename; ShowWidget *showWidget; //文件菜单栏 QAction *OpenFileAction; QAction *NewFileAction; QAction *ExitAction; //编辑菜单栏 QAction *CopyAction; QAction *CutAction; QAction *PasteAction; QAction *AboutAction; QAction *ZoomInAction; QAction *ZoomOutAction; QAction *UndoAction; QAction *RedoAction; //工具栏 QToolBar *Tool; QToolBar *DoToolBar; //状态栏 QStatusBar *Status; //停靠窗口1,显示蓝牙连接状态 QLabel *BlueToothLabel; QComboBox *BlueToothPortComboBox; QPushButton *ConnectBtn; QPushButton *BreakBtn; QPushButton *Stop1Btn; QSerialPort *CurrentPort; QLabel *BaudRateLabel; QComboBox *BaudRateComBox; QLabel *DateRateLabel; QComboBox *DateRateComBox; QLabel *ParityLabel; QComboBox *ParityComBox; QLabel *StopBitsLabel; QComboBox *StopBitsComBox; //停靠窗口2,各种参数调整模块 QLabel *InitELabel; QLabel *FinalELabel; QLabel *ScanRateLabel; QLabel *ScanningDirectionLabel; QLabel *GainLabel; QLabel *SampleIntervalLabel; QLabel *QuietTimeLabel; QLineEdit *InitELineEdit; QLineEdit *FinalELineEdit; QLineEdit *ScanRateLineEdit; QComboBox *ScanningDirectionComboBox; QLineEdit *GainLineEdit; QLineEdit *SampleIntervalLineEdit; QLineEdit *QuietTimeLineEdit; QPushButton *SendBtn; QPushButton *StartBtn; QPushButton *PauseBtn; QPushButton *Stop2Btn; QButtonGroup *Dock2Group; QTextEdit *StatusOfBT; //停靠窗口3,3个显示窗口,状态/接受/发送 QTextEdit *StatusOfDock3; QTextEdit *SendInfo; QTextEdit *ReceiveInfo; protected slots: void showNewFile(); void showZoomIn(); void showZoomOut(); void startPainting(); void stopPainting(); private slots: void on_clearButton_clicked(); void on_sendButtton_clicked(); void on_connectButton_clicked(); void on_breakButton_clicked(); void Read_Data(); }; #endif // MAINWINDOW_H

2. cpp文件

#include "mainwindow.h" #include <QTextEdit> #include <QDockWidget> #include <QLineEdit> #include <QPushButton> #include <QLabel> #include <QLayout> #include <QGridLayout> #include <QtGui> #include <QLabel> #include <QFileDialog> #include <QAction> #include <QDebug> #include <QtSerialPort/QSerialPort> #include <QtSerialPort/QSerialPortInfo> #include <QMessageBox> #include <QTimer> void MainWindow::createActions() { OpenFileAction = new QAction(QIcon("Open.png"),tr("Open"),this); OpenFileAction->setShortcut(tr("Ctrl+O")); OpenFileAction->setStatusTip(tr("Open one file")); connect(OpenFileAction,&QAction::triggered,[=] () { QString path = QFileDialog::getOpenFileName( this,"open","../", "souce(*.cpp *.h);;Text(*.txt);;All(*.*)"); } ); NewFileAction = new QAction(QIcon("Open.png"),tr("New"),this); NewFileAction->setShortcut(tr("Ctrl+N")); NewFileAction->setStatusTip(tr("Build one new file")); connect(NewFileAction,SIGNAL(triggered()),this,SLOT(showNewFile())); ExitAction = new QAction(QIcon("Open.png"),tr("Exit"),this); ExitAction->setShortcut(tr("Ctrl+N")); ExitAction->setStatusTip(tr("Exit")); CopyAction = new QAction(QIcon("Open.png"),tr("Copy"),this); CopyAction->setShortcut(tr("Ctrl+Q")); CopyAction->setStatusTip(tr("Exit")); //connect(CopyAction,SIGNAL(triggered()),showWidget->text,SLOT(copy())); CutAction = new QAction(QIcon("Open.png"),tr("Cut"),this); CutAction->setShortcut(tr("Crtl+C")); //connect(CutAction,SIGNAL(triggered()),showWidget->text,SLOT(cut())); PasteAction = new QAction(QIcon("Open.png"),tr("Paste"),this); PasteAction->setShortcut(tr("Ctrl+V")); //connect(PasteAction,SIGNAL(triggered()),showWidget->text,SLOT(paste())); ZoomInAction = new QAction(QIcon("Open.png"),tr("ZoomIn"),this); connect(ZoomInAction,SIGNAL(triggered()),this,SLOT(showZoomIn())); ZoomOutAction = new QAction(QIcon("Open.png"),tr("ZoomOut"),this); connect(ZoomOutAction,SIGNAL(triggered()),this,SLOT(showZoomOut()));//图标未设置,均采用open.png } void MainWindow::createMenus() { fileMenu = menuBar()->addMenu(tr("File")); fileMenu->addAction(OpenFileAction); fileMenu->addAction(NewFileAction); fileMenu->addSeparator(); fileMenu->addAction(ExitAction); } void MainWindow::createToolBars() { Tool = addToolBar("Tool"); Tool->addAction(CopyAction); Tool->addAction(CutAction); Tool->addAction(PasteAction); Tool->addAction(ZoomInAction); Tool->addAction(ZoomOutAction); Tool->setAllowedAreas(Qt::TopToolBarArea); } void MainWindow::createStatusBars()//状态栏,最下面一行,显示状态 { Status = statusBar(); Status->addWidget(new QLabel("2",this)); } void MainWindow::showNewFile()//新建文件,这里需要修改 { MainWindow *newFile = new MainWindow; newFile->show(); } void MainWindow::showZoomIn()//下面这两个要修改,能够将实时图像放大或者缩小 { } void MainWindow::showZoomOut()// { } void MainWindow::bluetooth()//蓝牙模块 { QDockWidget *dock1 = new QDockWidget(tr("DockWindow1")); dock1->setFeatures(QDockWidget::DockWidgetMovable|QDockWidget::DockWidgetFloatable); //窗口可移动 dock1->setAllowedAreas(Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea); addDockWidget(Qt::RightDockWidgetArea,dock1); dock1->setStyleSheet("QPushButton{color:white;background-color:black}");//按钮样式设置 BlueToothLabel = new QLabel(tr("Port name: ")); ConnectBtn = new QPushButton("Connect"); BreakBtn = new QPushButton(tr("Break")); Stop1Btn = new QPushButton(tr("Stop")); BlueToothPortComboBox = new QComboBox; BaudRateLabel = new QLabel(tr("BaudRate: ")); BaudRateComBox = new QComboBox; BaudRateComBox->addItem(tr("11520")); BaudRateComBox->addItem(tr("9600")); DateRateLabel = new QLabel(tr("DateRate: ")); DateRateComBox = new QComboBox; DateRateComBox->addItem("5"); DateRateComBox->addItem("6"); DateRateComBox->addItem("7"); DateRateComBox->addItem("8"); DateRateComBox->setCurrentIndex(3);//设置下拉选择默认为第4个 ParityLabel = new QLabel("Parity"); ParityComBox = new QComboBox; ParityComBox->addItem("On"); ParityComBox->addItem("Off"); ParityComBox->setCurrentIndex(1); StopBitsLabel = new QLabel("StopBits: "); StopBitsComBox = new QComboBox; StopBitsComBox->addItem("1"); StopBitsComBox->addItem("2"); // QTextEdit *StatusOfBT = new QTextEdit; //进行布局,先横向再纵向 QHBoxLayout *Dock1Layout1 = new QHBoxLayout(); Dock1Layout1->addWidget(BlueToothLabel); Dock1Layout1->addWidget(BlueToothPortComboBox); QHBoxLayout *Dock1Layout2 = new QHBoxLayout(); Dock1Layout2->addWidget(BaudRateLabel); Dock1Layout2->addWidget(BaudRateComBox); QHBoxLayout *Dock1Layout3 = new QHBoxLayout(); Dock1Layout3->addWidget(DateRateLabel); Dock1Layout3->addWidget(DateRateComBox); QHBoxLayout *Dock1Layout4 = new QHBoxLayout(); Dock1Layout4->addWidget(ParityLabel); Dock1Layout4->addWidget(ParityComBox); QHBoxLayout *Dock1Layout5 = new QHBoxLayout(); Dock1Layout5->addWidget(StopBitsLabel); Dock1Layout5->addWidget(StopBitsComBox); QHBoxLayout *Dock1Layout6 = new QHBoxLayout(); Dock1Layout6->addWidget(ConnectBtn);//点击后就开始寻找设备进行连接 Dock1Layout6->addWidget(BreakBtn);//点击后断开串口连接 // Dock1Layout6->addWidget(Stop1Btn);//暂时未用到 QVBoxLayout *Dock1Layout = new QVBoxLayout(); Dock1Layout->setAlignment(Qt::AlignCenter); Dock1Layout->addLayout(Dock1Layout1); Dock1Layout->addLayout(Dock1Layout2); Dock1Layout->addLayout(Dock1Layout3); Dock1Layout->addLayout(Dock1Layout4); Dock1Layout->addLayout(Dock1Layout5); Dock1Layout->addLayout(Dock1Layout6); QWidget *Dock1Widget = new QWidget(); Dock1Widget->setLayout(Dock1Layout); dock1->setWidget(Dock1Widget); ConnectBtn->setMinimumWidth(70); BreakBtn->setMaximumWidth(50); Stop1Btn ->setMaximumWidth(50); //搜索串口,并添加到选项上供使用者选择 foreach(const QSerialPortInfo &Info,QSerialPortInfo ::availablePorts()) { QSerialPort CurrentPort; CurrentPort.setPort(Info); if(CurrentPort.open(QIODevice::ReadWrite)) { BlueToothPortComboBox->addItem(CurrentPort.portName());//插入串口的名字 CurrentPort.close(); //先开再关,把串口名称先导入 } } connect(ConnectBtn, SIGNAL(clicked()),this,SLOT(on_connectButton_clicked())); connect(BreakBtn, SIGNAL(clicked()),this,SLOT(on_breakButton_clicked())); } void MainWindow::on_clearButton_clicked()//清空发送与接收窗口信息 { SendInfo->clear(); ReceiveInfo->clear(); } void MainWindow::on_sendButtton_clicked()//发送数据 { QByteArray SendBytes = SendInfo->toPlainText().toLatin1();//toPlainText(将文本编辑的文本转换为纯文本) if(SendBytes.isEmpty())//判断发送数据是否为空 { StatusOfDock3->append("No message can be sent, Please write something"); } CurrentPort->write(SendBytes); } void MainWindow::Read_Data()//读取接收到的数据 { QByteArray buf; buf = CurrentPort->readAll();//Qbytearray类提供一个字节数组,buf这里应该是缓冲数据的功能 if(!buf.isEmpty()) { QString str = this->ReceiveInfo->toPlainText().toUtf8(); str += tr(buf);//??? ReceiveInfo->clear(); ReceiveInfo->append(str); } buf.clear(); } void MainWindow::on_connectButton_clicked() { CurrentPort = new QSerialPort; CurrentPort->setPortName(BlueToothPortComboBox->currentText());//设置串口名 //设置波特率 switch (BaudRateComBox->currentIndex()) { case 0: StatusOfDock3->append("Baud:115200"); CurrentPort->setBaudRate(QSerialPort::Baud115200,QSerialPort::AllDirections); break; case 1: StatusOfDock3->append("Baud:9600"); CurrentPort->setBaudRate(QSerialPort::Baud9600,QSerialPort::AllDirections); break; default: break; } //设置数据位数 switch(DateRateComBox->currentIndex()) { case 0: StatusOfDock3->append("Data:5"); CurrentPort->setDataBits(QSerialPort::Data5); break; case 1: StatusOfDock3->append("Data:6"); CurrentPort->setDataBits(QSerialPort::Data6); break; case 2: StatusOfDock3->append("Data:7"); CurrentPort->setDataBits(QSerialPort::Data7); break; case 3: StatusOfDock3->append("Data:8"); CurrentPort->setDataBits(QSerialPort::Data8); break; default: break; } //设置奇偶校验 switch(ParityComBox->currentIndex()) { case 1:StatusOfDock3->append("Parity: off"); CurrentPort->setParity(QSerialPort::NoParity); break; default: break; } switch(StopBitsComBox->currentIndex()) //设置停止位 { case 0: StatusOfDock3->append("StopBits:1"); CurrentPort->setStopBits(QSerialPort::OneStop); break; case 1: StatusOfDock3->append("StopBits:2"); CurrentPort->setStopBits(QSerialPort::TwoStop); break; default: break; } CurrentPort->setFlowControl(QSerialPort::NoFlowControl); //设置流控制 CurrentPort->open(QIODevice::ReadWrite);//打开串口 if(CurrentPort->isOpen()) { StatusOfDock3->append("Succeesfully open the Port "); //关闭设置菜单使能 BlueToothPortComboBox->setEnabled(false); BaudRateComBox->setEnabled(false); DateRateComBox->setEnabled(false); ParityComBox->setEnabled(false); StopBitsComBox->setEnabled(false); ConnectBtn->setEnabled(false); BreakBtn->setEnabled(true); SendBtn->setEnabled(true); } else { StatusOfDock3->append("Defeatly open the port"); } //连接信号槽 QObject::connect(CurrentPort, &QSerialPort::readyRead, this, &MainWindow::Read_Data); } void MainWindow::on_breakButton_clicked() { //关闭串口 CurrentPort->clear(); CurrentPort->close(); CurrentPort->deleteLater(); StatusOfDock3->append("Serial connection has been disconnected"); //恢复设置使能 BlueToothPortComboBox->setEnabled(true); BaudRateComBox->setEnabled(true); DateRateComBox->setEnabled(true); ParityComBox->setEnabled(true); StopBitsComBox->setEnabled(true); ConnectBtn->setEnabled(true); BreakBtn->setEnabled(false); SendBtn->setEnabled(false); } void MainWindow::startPainting() { } void MainWindow::stopPainting() { } void MainWindow::setvariables() { //停靠窗口2,调整各种变量 QDockWidget *dock2 = new QDockWidget(tr("DockWindow2")); dock2->setFeatures(QDockWidget::DockWidgetMovable|QDockWidget::DockWidgetFloatable); //窗口可移动 dock2->setAllowedAreas(Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea); //dock2->setStyleSheet("QPushButtonl{color:white;background-color:black}");//设置按钮/标签等颜色 color\background-color //空白margain/边框border/填充padding/内容content addDockWidget(Qt::RightDockWidgetArea,dock2); //设置各个Widget,进行填充 InitELabel = new QLabel(tr("Init E(V): ")); InitELineEdit = new QLineEdit; FinalELabel = new QLabel(tr("Final E(V): ")); FinalELineEdit = new QLineEdit; ScanRateLabel = new QLabel(tr("Scan Rate (mV/s): ")); ScanRateLineEdit = new QLineEdit; ScanningDirectionLabel = new QLabel(tr("Scanning direction: ")); ScanningDirectionComboBox = new QComboBox; ScanningDirectionComboBox->addItem(tr("Positive")); ScanningDirectionComboBox->addItem(tr("Negative")); GainLabel = new QLabel(tr("Gain : ")); GainLineEdit = new QLineEdit; SampleIntervalLabel = new QLabel(tr("Sample Interval (mv): ")); SampleIntervalLineEdit = new QLineEdit; QuietTimeLabel = new QLabel(tr("Quiet Time: ")); QuietTimeLineEdit = new QLineEdit; SendBtn = new QPushButton(tr("Send")); StartBtn = new QPushButton(tr("Start")); PauseBtn = new QPushButton(tr("Pause")); Stop2Btn = new QPushButton(tr("Stop")); dock2->setStyleSheet("QPushButton{color:white;background-color:black}");//设置按钮样式 StartBtn->setMaximumWidth(50); PauseBtn->setMaximumWidth(50); Stop2Btn ->setMaximumWidth(50); //设置完各个控件进行布局,先水平布局再垂直布局 QHBoxLayout *Dock2Layout1 = new QHBoxLayout(); Dock2Layout1->addWidget(InitELabel); Dock2Layout1->addWidget(InitELineEdit); QHBoxLayout *Dock2Layout2 = new QHBoxLayout(); Dock2Layout2->addWidget(FinalELabel); Dock2Layout2->addWidget(FinalELineEdit); QHBoxLayout *Dock2Layout3 = new QHBoxLayout(); Dock2Layout3->addWidget(ScanRateLabel); Dock2Layout3->addWidget(ScanRateLineEdit); QHBoxLayout *Dock2Layout4 = new QHBoxLayout(); Dock2Layout4->addWidget(ScanningDirectionLabel); Dock2Layout4->addWidget(ScanningDirectionComboBox); QHBoxLayout *Dock2Layout5 = new QHBoxLayout(); Dock2Layout5->addWidget(GainLabel); Dock2Layout5->addWidget(GainLineEdit); QHBoxLayout *Dock2Layout6 = new QHBoxLayout(); Dock2Layout6->addWidget(SampleIntervalLabel); Dock2Layout6->addWidget(SampleIntervalLineEdit); QHBoxLayout *Dock2Layout7 = new QHBoxLayout(); Dock2Layout7->addWidget(QuietTimeLabel); Dock2Layout7->addWidget(QuietTimeLineEdit); QHBoxLayout *Dock2Layout8 = new QHBoxLayout(); Dock2Layout8->addWidget(SendBtn); Dock2Layout8->addWidget(StartBtn); Dock2Layout8->addWidget(PauseBtn); Dock2Layout8->addWidget(Stop2Btn); QVBoxLayout *Dock2Layout = new QVBoxLayout; Dock2Layout->setAlignment(Qt::AlignCenter); Dock2Layout->addLayout(Dock2Layout1); Dock2Layout->addLayout(Dock2Layout2); Dock2Layout->addLayout(Dock2Layout3); Dock2Layout->addLayout(Dock2Layout4); Dock2Layout->addLayout(Dock2Layout5); Dock2Layout->addLayout(Dock2Layout6); Dock2Layout->addLayout(Dock2Layout7); Dock2Layout->addLayout(Dock2Layout8); Dock2Layout->setSpacing(20);//设置间隙 QWidget *Dock2Widget = new QWidget(); Dock2Widget->setLayout(Dock2Layout); dock2->setWidget(Dock2Widget); connect(SendBtn,SIGNAL(clicked()),this,SLOT(on_sendButtton_clicked())); } void MainWindow::statusOfAll()//最下面的窗口,显示图像的各个数据;暂时让收发数据显示在这里,到后面可隐藏掉 { //停靠窗口3,显示图像各种参数 QDockWidget *dock3 = new QDockWidget(tr("DockWindow3")); dock3->setFeatures(QDockWidget::DockWidgetMovable|QDockWidget::DockWidgetFloatable); //窗口可移动 dock3->setAllowedAreas(Qt::BottomDockWidgetArea); addDockWidget(Qt::BottomDockWidgetArea,dock3); dock3->setMinimumSize(1500,100); QHBoxLayout *Dock3Layout = new QHBoxLayout; StatusOfDock3 = new QTextEdit; StatusOfDock3->setMinimumSize(300,200); SendInfo = new QTextEdit; ReceiveInfo = new QTextEdit; Dock3Layout->addWidget(StatusOfDock3); Dock3Layout->addWidget(SendInfo); Dock3Layout->addWidget(ReceiveInfo); QWidget *Dock3Widget = new QWidget(); Dock3Widget->setLayout(Dock3Layout); dock3->setWidget(Dock3Widget); } MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { setWindowTitle(tr("V1.0"));//窗体标题 //主窗口设计 scene = new QGraphicsScene; scene->setSceneRect(-200,-200,400,400); //initScene(); QGraphicsView *view = new QGraphicsView; view->setScene(scene); view->setMinimumSize(800,600); setCentralWidget(view); resize(1000,800); //创建动作、菜单、工具栏的函数 createActions(); createMenus(); createToolBars(); createStatusBars(); //蓝牙、参数设置、状态显示 bluetooth(); setvariables(); statusOfAll(); //创建坐标轴 } MainWindow::~MainWindow() { }

3. 实例结果

三、QT5串口注意点

虚拟串口下载:https://download.csdn.net/download/qq_41429220/11383961 串口助手下载:https://download.csdn.net/download/qq_41429220/11383925 本实例源文件下载:https://download.csdn.net/download/qq_41429220/11383958

运行程序后实现收发数据,电脑端可以直接进行模拟,虚拟串口出来。用COM1实现发送,再用串口助手将COM2打开,两者之间可以成功实现通信。

最新回复(0)