Qt:采用第三方串口类CSerialPort V4.0.3开发的串口助手,支持高波特率
程序员文章站
2022-07-13 13:34:36
...
首先感谢itas109大佬的开源代码,用起来真的简单方便,且经过多年修改完善代码整体框架比较健全,很多大公司都在使用这个串口类。
初次使用这个串口类是在MFC下开发串口通讯时使用的(代码链接:使用CSerialPort开源类在MFC下开发的串口助手),当时就感觉特别的简单方便,之后因为项目需要就在Qt下开始使用了,刚开始使用了Qt自带的串口类,但是感觉操作繁琐,且不支持高波特率,后来又还了Qt的第三方串口类qextserialport类,但是因为缺乏维护且问题较多,所以最后还是找了itas109大佬的开源串口类,结果显而易见,在Qt环境下的使用还是一如既往的方便简单,且本人实测,921600波特率下,20ms周期发送接收数据稳定!
重点来了:itas109大佬博客:http://blog.csdn.net/itas109
QQ群,平时遇到的问题或者串口使用想到的新需求都可以在群里提:129518033
Git:https://github.com/itas109/CSerialPort里边有最新版本的发布以及以往个版本的更新说明;
环境:QT5.6.3
效果图:
下面时代码的大体结构:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTimer>
#include "SerialPort.h"
using namespace std;
using namespace itas109;
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow, public has_slots<>
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
//转16进制
QByteArray QString2Hex(QString str);
char ConvertHexChar(char ch);
QTimer *m_time;
private slots:
void OnReceive();
void OnUpdateReceive(QString str);
void on_pushButtonOpen_clicked();
void on_pushButtonSend_clicked();
void on_pushButtonClear_clicked();
void on_checkBoxSync_stateChanged(int arg1);
void on_pushButtonReadSync_clicked();
void on_checkBoxSync_clicked(bool checked);
void time_send();
signals:
void emitUpdateReceive(QString str);
private:
Ui::MainWindow *ui;
CSerialPort m_SerialPort;
int tx;
int rx;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "SerialPortInfo.h"
#include <QDebug>
#include <QScrollBar>
#include <QMessageBox>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->spinBox->setMaximum(5000);
ui->spinBox->setMinimum(5);
connect(this,&MainWindow::emitUpdateReceive,this,&MainWindow::OnUpdateReceive,Qt::QueuedConnection);
//hide pushButtonReadSync
ui->pushButtonReadSync->hide();//隐藏这个控件
//ui
ui->pushButtonOpen->setText(tr("open"));
rx = 0;
tx = 0;
setWindowTitle(this->windowTitle() + "串口助手" +QString::fromStdString(m_SerialPort.getVersion()));
//自动获取端口
vector<SerialPortInfo> portNameList = CSerialPortInfo::availablePortInfos();
for (int i = 0; i < portNameList.size(); i++)
{
ui->comboBoxPortName->insertItem(i,QString::fromLocal8Bit(portNameList[i].portName.c_str()));
}
//初始化
m_SerialPort.readReady.connect(this, &MainWindow::OnReceive);
ui->comboBoxBaudrate->setCurrentText("115200");
ui->comboBoxDataBit->setCurrentText("8");
//qDebug() << QString::fromStdString(m_SerialPort.getVersion());
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::OnReceive()
{
int iRet = -1;
char * str = NULL;
str = new char[512];
iRet = m_SerialPort.readAllData(str);
//qDebug() << "read length : " << iRet;
if(iRet != -1)
{
// TODO: 中文需要由两个字符拼接,否则显示为空""
QString m_str = QString::fromLocal8Bit(str,iRet);
//qDebug() << "receive : " << m_str;
emit emitUpdateReceive(m_str);//发出信号
}
else
{
}
delete str;
str = NULL;
}
void MainWindow::OnUpdateReceive(QString str)//显示数据
{
rx += str.length();
ui->labelRXValue->setText(QString::number(rx));
//追加文本
if(ui->checkBox->checkState()==Qt::Checked)//十六进制显示
{
QByteArray temp=str.toLatin1();
QString str3 = temp.toHex().data();//以十六进制显示
QString strDis;
for(int i = 0;i<str3.length();i+=2)//填加空格
{
QString st = str3.mid (i,2);
strDis += st;
strDis += " ";
}
ui->plainTextEditReceive->moveCursor (QTextCursor::End);
ui->plainTextEditReceive->insertPlainText(strDis);
}
else
{
ui->plainTextEditReceive->moveCursor (QTextCursor::End);
ui->plainTextEditReceive->insertPlainText(str);
}
}
void MainWindow::on_pushButtonOpen_clicked()//打开串口
{
if(ui->pushButtonOpen->text() == tr("open"))
{
if(ui->comboBoxPortName->count() > 0)//检测到端口
{
//初始化串口
m_SerialPort.init(ui->comboBoxPortName->currentText().toStdString(),
ui->comboBoxBaudrate->currentText().toInt(),
itas109::Parity(ui->comboBoxParity->currentIndex()),
itas109::DataBits(ui->comboBoxDataBit->currentText().toInt()),
itas109::StopBits(ui->comboBoxStopBit->currentIndex()));
//打开串口
if(m_SerialPort.open())
{
ui->pushButtonOpen->setText(tr("close"));
}
else
{
QMessageBox::information(NULL,tr("information"),tr("open port error"));
ui->pushButtonOpen->setText(tr("open"));
//qDebug()<< m_SerialPort.getLastError();
}
}
else
{
QMessageBox::information(NULL,tr("information"),tr("This Computer no avaiable port"));
//qDebug()<< "This Computer no avaiable port";
}
}
else
{
m_SerialPort.close();
ui->pushButtonOpen->setText(tr("open"));
}
}
void MainWindow::on_pushButtonSend_clicked()//发送数据
{
if(m_SerialPort.isOpened())
{
if(ui->checkBox_3->checkState()==Qt::Checked)//定时发送
{
int timecount=ui->spinBox->value();//定时器发送的周期
m_time=new QTimer(this);
connect(m_time,&QTimer::timeout,this,&MainWindow::time_send);
m_time->start(timecount);
}
else
{
if(ui->checkBox_2->checkState()==Qt::Checked)//十六进制发
{
QByteArray m_senddata=QString2Hex(ui->plainTextEditSend->toPlainText());
const char *s = m_senddata.constData();
//支持中文并获取正确的长度
m_SerialPort.writeData(s,m_senddata.length());
tx+=m_senddata.length();
ui->labelTXValue->setText(QString::number(tx));
}
else
{
QString sendStr = ui->plainTextEditSend->toPlainText();
QByteArray ba = sendStr.toLocal8Bit();
const char *s = ba.constData();
//支持中文并获取正确的长度
m_SerialPort.writeData(s,ba.length());
tx += sendStr.length();
ui->labelTXValue->setText(QString::number(tx));
}
}
}
else
{
QMessageBox::information(NULL,tr("information"),tr("please open serial port first"));
//qDebug() << tr("please open serial port first");
}
}
void MainWindow::time_send()//定时发送
{
if(ui->checkBox_3->checkState()==Qt::Checked)//定时发送
{
if(ui->checkBox_2->checkState()==Qt::Checked)//十六进制发
{
QByteArray m_senddata=QString2Hex(ui->plainTextEditSend->toPlainText());
const char *s = m_senddata.constData();
//支持中文并获取正确的长度
m_SerialPort.writeData(s,m_senddata.length());
tx+=m_senddata.length();
ui->labelTXValue->setText(QString::number(tx));
}
else
{
QString sendStr = ui->plainTextEditSend->toPlainText();
QByteArray ba = sendStr.toLocal8Bit();
const char *s = ba.constData();
//支持中文并获取正确的长度
m_SerialPort.writeData(s,ba.length());
tx += sendStr.length();
ui->labelTXValue->setText(QString::number(tx));
}
}
else
{
m_time->stop();
}
}
QByteArray MainWindow::QString2Hex(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; )
{
hstr=str[i].toLatin1();
if(hstr == ' ')
{
i++;
continue;
}
i++;
if(i >= len)
break;
lstr = str[i].toLatin1();
hexdata = ConvertHexChar(hstr);
lowhexdata = ConvertHexChar(lstr);
if((hexdata == 16) || (lowhexdata == 16))
break;
else
hexdata = hexdata*16+lowhexdata;
i++;
senddata[hexdatalen] = (char)hexdata;
hexdatalen++;
}
senddata.resize(hexdatalen);
return senddata;
}
char MainWindow::ConvertHexChar(char ch)
{
if((ch >= '0') && (ch <= '9'))
return ch-0x30;
else if((ch >= 'A') && (ch <= 'F'))
return ch-'A'+10;
else if((ch >= 'a') && (ch <= 'f'))
return ch-'a'+10;
else return (-1);
}
void MainWindow::on_pushButtonClear_clicked()//清空
{
tx = 0;
rx = 0;
ui->labelTXValue->setText(QString::number(tx));
ui->labelRXValue->setText(QString::number(rx));
}
void MainWindow::on_checkBoxSync_stateChanged(int arg1)//状态改变选择框
{
if(arg1 == 0)
{
m_SerialPort.close();
}
else
{
m_SerialPort.close();
}
}
void MainWindow::on_pushButtonReadSync_clicked()//SYNC按键
{
OnReceive();
}
void MainWindow::on_checkBoxSync_clicked(bool checked)//选择框选择
{
//AsynchronousOperate
if(checked)
{
m_SerialPort.setOperateMode(itas109::SynchronousOperate);
ui->pushButtonReadSync->show();
}
else
{
m_SerialPort.setOperateMode(itas109::AsynchronousOperate);
ui->pushButtonReadSync->hide();
}
}
基本上整个项目的代码都在这里了,图片里的源码部分大家可以在我文章开头处的Git链接出进行下载,再次感谢itas109
大佬的开源代码,非常实用,倾力推荐!
需要项目源码请点击此处
有问题联系:aaa@qq.com
上一篇: 字符串反转
下一篇: STM32之串口通信