概述
由于前段时间有个项目用需要一个上位机与单片机进行实现串口通讯,所以参考网上的教程用qt5完成了上位机的设计,目前实现了基本的功能,其他的功能还在完善中,文末有完整工程下载链接
首先要注意的是:因为应用到了qt5自带的串口通信模块,所以在项目的.pro文件中加入一句 QT += serialport,并在头文件中加入包含文件
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
以下是mainwindow.h的内容
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QLabel>
#include <QTimer>
#include <windows.h>
#include <QString>
#include <dbt.h>
#include <QDebug>
#include<devguid.h>
#include<SetupAPI.h>
#include<InitGuid.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
void initPort();
~MainWindow();
private slots:
void ReadData();//读取数据
void timeTosend();//定时发送
void on_openButton_clicked();
void on_r_clearButton_clicked();
void on_s_clearButton_clicked();
void on_sendButton_clicked();
void StringToHex(QString str, QByteArray & senddata);//用于发送时进制转换
char ConvertHexChart(char ch);//十六进制转换
void readToHex();//将读取的数据以十六进制显示
void Mdisplay();
private:
Ui::MainWindow *ui;
QSerialPort *serialPort;
QTimer *time; //用于定时发送
};
#endif // MAINWINDOW_H
还有就是.cpp的内容,其中各个功能都有对应的函数
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QMessageBox>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
time = new QTimer(this);
initPort();
//设置默认值
ui->BaudBox->setCurrentIndex(7);
ui->PortBox->setCurrentIndex(1);
ui->StopBox->setCurrentIndex(0);
ui->DataBox->setCurrentIndex(3);
ui->ParityBox->setCurrentIndex(0);
ui->sendButton->setEnabled(false);
ui->sHexRadio->setEnabled(false);
ui->sTextRadio->setChecked(true);
ui->sTextRadio->setEnabled(false);
ui->rTextRadio->setChecked(true);
connect(ui->reSendCheck, &QCheckBox::stateChanged,
this, &MainWindow::timeTosend);
connect(time, &QTimer::timeout, this, &MainWindow::on_sendButton_clicked);
connect(ui->rHexRadio, &QRadioButton::toggled, this, &MainWindow::Mdisplay);
}
void MainWindow::initPort()
{
//获取可用串口
const auto infos = QSerialPortInfo::availablePorts();
for(const QSerialPortInfo &info : infos)
{
QSerialPort serial;
serial.setPort(info);
if(serial.open(QIODevice::ReadWrite))
{
ui->PortBox->addItem(info.portName());
qDebug()<<info.portName();
serial.close();
}
}
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::ReadData()
{
static int reNum = 0;
QByteArray buf;
buf = serialPort->readAll();
if (!buf.isEmpty())
{
reNum += buf.size();
QString myStrTemp = QString::fromLocal8Bit(buf); //支持中文显示
QString str = ui->textBrowser->toPlainText();
str +=myStrTemp;
ui->textBrowser->clear();
ui->textBrowser->append(str);
}
buf.clear();
}
void MainWindow::timeTosend()
{
if(ui->reSendCheck->isChecked())
{
if(time->isActive())
{
return;
}
else
{
int ms = ui->spinBox->value();
time->start(ms);
}
}
else
{
if(time->isActive())
{
time->stop();
}
else
{
return;
}
}
}
void MainWindow::on_openButton_clicked()
{
if (ui->openButton->text() == tr("打开串口"))
{
serialPort = new QSerialPort;
serialPort->setPortName(ui->PortBox->currentText());
if(serialPort->open(QIODevice::ReadWrite))
{
switch (ui->BaudBox->currentIndex()) {
case 7:
serialPort->setBaudRate(QSerialPort::Baud115200);
break;
default:
break;
}
switch (ui->StopBox->currentIndex()) {
case 0:
serialPort->setStopBits(QSerialPort::OneStop);
break;
default:
break;
}
switch (ui->DataBox->currentIndex()) {
case 3:
serialPort->setDataBits(QSerialPort::Data8);
break;
default:
break;
}
switch (ui->ParityBox->currentIndex()) {
case 0:
serialPort->setParity(QSerialPort::NoParity);
break;
default:
break;
}
ui->openButton->setText(tr("关闭串口"));
ui->PortBox->setEnabled(false);
ui->BaudBox->setEnabled(false);
ui->StopBox->setEnabled(false);
ui->DataBox->setEnabled(false);
ui->ParityBox->setEnabled(false);
ui->sendButton->setEnabled(true);
ui->sTextRadio->setEnabled(true);
ui->sHexRadio->setEnabled(true);
connect(serialPort, &QSerialPort::readyRead, this, &MainWindow::ReadData);
// connect(serialPort, &QSerialPort::readyRead, this, &MainWindow::readToHex);
}
else
{
QMessageBox::critical(this, tr("Error"), serialPort->errorString());
}
}
else
{
serialPort->clear();
serialPort->close();
serialPort->deleteLater();
ui->sendButton->setEnabled(false);
ui->openButton->setText(tr("打开串口"));
ui->PortBox->setEnabled(true);
ui->BaudBox->setEnabled(true);
ui->StopBox->setEnabled(true);
ui->DataBox->setEnabled(true);
ui->ParityBox->setEnabled(true);
ui->sHexRadio->setEnabled(false);
ui->sTextRadio->setEnabled(false);
}
}
void MainWindow::on_r_clearButton_clicked()
{
ui->textBrowser->clear();
}
void MainWindow::on_s_clearButton_clicked()
{
ui->lineEdit->clear();
}
void MainWindow::on_sendButton_clicked()
{
//Latin1是ISO-8859-1的别名,有些环境下写作Latin-1。ISO-8859-1编码是单字节编码,向下兼容ASCII
//其编码范围是0x00-0xFF,0x00-0x7F之间完全和ASCII一致,0x80-0x9F之间是控制字符,0xA0-0xFF之间是文字符号。
// QString test = ui->textEdit->toPlainText();
// qDebug()<<test<<endl;
// serialPort->write(test.toLocal8Bit());
QString str = ui->lineEdit->text();
if(!str.isEmpty())
{
auto isHexSend = ui->sHexRadio->isChecked();
int len = str.length();
if(len%2 == 1)
{
str = str.insert(len-1,'0');
}
QByteArray senddata;
if(isHexSend)
{
StringToHex(str,senddata);
if(serialPort->write(senddata)<0)
{
QMessageBox::critical(this, tr("Error"), serialPort->errorString());
}
}
else
{
if(serialPort->write(ui->lineEdit->text().toLocal8Bit())<0)
{
QMessageBox::critical(this, tr("Error"), serialPort->errorString());
}
}
auto isredisplay = ui->reDisplay->isChecked();
if(isredisplay)
{
ui->textBrowser->append(str);
}
}
}
void MainWindow::StringToHex(QString str, QByteArray &senddata)
{
int hexdata,lowhexdata;
int hexdatalen = 0;
int len = str.length();
senddata.resize(len/2);
char lstr,hstr;
for(int i=0; i<len; )
{
//char lstr,
hstr=str[i].toLatin1();
if(hstr == ' ')
{
i++;
continue;
}
i++;
if(i >= len)
break;
lstr = str[i].toLatin1();
hexdata = ConvertHexChart(hstr);
lowhexdata = ConvertHexChart(lstr);
if((hexdata == 16) || (lowhexdata == 16))
break;
else
hexdata = hexdata*16+lowhexdata;
i++;
senddata[hexdatalen] = (char)hexdata;
hexdatalen++;
}
senddata.resize(hexdatalen);
}
char MainWindow::ConvertHexChart(char ch)
{
if((ch >= '0') && (ch <= '9'))
return ch-0x30; // 0x30 对应 ‘0’
else if((ch >= 'A') && (ch <= 'F'))
return ch-'A'+10;
else if((ch >= 'a') && (ch <= 'f'))
return ch-'a'+10;
// else return (-1);
else return ch-ch;//不在0-f范围内的会发送成0
}
void MainWindow::readToHex()
{
QByteArray temp = serialPort->readAll();
QDataStream out(&temp,QIODevice::ReadWrite); //将字节数组读入
while(!out.atEnd())
{
qint8 outChar = 0;
out>>outChar; //每字节填充一次,直到结束
//十六进制的转换
QString str = QString("%1").arg(outChar&0xFF,2,16,QLatin1Char('0'));
ui->textBrowser->insertPlainText(str.toUpper());//大写
ui->textBrowser->insertPlainText(" ");//每发送两个字符后添加一个空格
ui->textBrowser->moveCursor(QTextCursor::End);
}
}
void MainWindow::Mdisplay()
{
if(ui->rHexRadio->isChecked())
{
disconnect(serialPort, &QSerialPort::readyRead, this, &MainWindow::ReadData);
connect(serialPort, &QSerialPort::readyRead, this, &MainWindow::readToHex);
}
else
{
connect(serialPort, &QSerialPort::readyRead, this, &MainWindow::ReadData);
disconnect(serialPort, &QSerialPort::readyRead, this, &MainWindow::readToHex);
}
}
最后附上一张软件的运行图:
如有任何问题,欢迎留言交流
补充:QT5自带的串口通信模块不足之处在于其波特率最高是115200,所以若实际需要更高的波特率,可以选择qt的第三方库,还有一点需要注意QT5自带的串口模块没有提供热插拔功能,需要另外处理。还有就是为了方便测试,我们可以使用虚拟 串口助手辅助调试,具体的软件可百度自行搜索下载。
最后附上工程地址:https://github.com/fireflylr/Upper-computer
参考网址:https://blog.csdn.net/hellolru/article/details/80838824
其他可以参考的网址:https://blog.csdn.net/CSDNZSX/article/details/89335600
https://blog.csdn.net/imkelt/article/details/53000523?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param