目录
前言
前段时间在做一个毕业设计需要一个上位机与单片机进行通讯,为了让毕业设计论文更好写一些,想着自己设计一个串口工具。花费一天时间,在网上找了大量模板,终于设计出来了,程序都是网上复制修改的,超级缝合怪,第一次使用qt开发希望我的学习心得对想要学习的同学能有所帮助。本人纯小白,还有不足地方还请大佬指点一二。
一、最终效果图
二、操作方法
1、创建一个新的Widgets Appliaction工程
2、用Qt Designer 设计上位机的界面
界面用到的控件还是挺多的,我直接贴出来:
3、代码部分
1、mainwindow.h文件内容:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QSerialPort> //提供访问串口的功能
#include <QSerialPortInfo> //提供系统中存在的串口的信息
#include <QDebug>
#include <QMessageBox>
#include <QFileDialog>
#include <QPushButton>
#include <QTimer>
#include <QPainter>
#include <qinputdialog.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_2_clicked();
void on_pushButton_clicked();
void on_pushButton_3_clicked();
void on_pushButton_4_clicked();
void serialPort_readyRead();
char ConvertHexChar(char ch);
void StringToHex(QString str, QByteArray &senddata); //字符串转换为十六进制数据0-F
void on_checkBox_clicked();
void on_checkBox_1_clicked();
void on_pushButton_6_clicked();
void on_pushButton_5_clicked();
void on_checkBox_3_stateChanged(int arg1);
void on_pushButton_7_clicked();
void on_pushButton_8_clicked();
void on_pushButton_9_clicked();
void on_pushButton_10_clicked();
void on_pushButton_11_clicked();
void on_pushButton_12_clicked();
void on_pushButton_13_clicked();
void on_pushButton_14_clicked();
void on_pushButton_15_clicked();
void on_pushButton_16_clicked();
void on_pushButton_17_clicked();
void on_pushButton_18_clicked();
void on_pushButton_19_clicked();
void on_pushButton_20_clicked();
void on_pushButton_21_clicked();
void Baud_rate_custom();
void on_comboBox_2_activated(const QString &arg1);
private:
Ui::MainWindow *ui;
QSerialPort serial;
// 定时发送-定时器
QTimer *timSend;
};
#endif // MAINWINDOW_H
2、mainwindow.cpp文件内容:
#include "mainwindow.h"
#include "ui_mainwindow.h"
bool Hex_Input=0;
bool Hex_Output=0;
bool Out_put_1=0;
bool Baud_rate_1=0;
QString Baud_rate="9600";
long int recvNum=0;
long int sendNum=0;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->comboBox->clear();
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
ui->comboBox->addItem(info.portName() + ": " + info.description());
}
this->setWindowTitle("串口助手");
this->setMaximumSize(660,457);
this->setMinimumSize(660,457);
ui->pushButton->setEnabled(false);
QPalette pl = ui->textEdit->palette(); // 获取textEdit的调色板
pl.setColor(QPalette::Base, Qt::black); // 设置背景色为黑色
pl.setColor(QPalette::Text, Qt::yellow); // 设置文本颜色为绿色
ui->textEdit->setPalette(pl); // 设置回调色板
ui->textEdit->setReadOnly(true);
ui->label_9->setText(QString::number(sendNum));
ui->label_11->setText(QString::number(recvNum));
timSend = new QTimer;
timSend->setInterval(1000);// 设置默认定时时长1000ms
connect(timSend, &QTimer::timeout, this, [=](){
on_pushButton_clicked();
});
QObject::connect(&serial, &QSerialPort::readyRead, this, &MainWindow::serialPort_readyRead);
}
MainWindow::~MainWindow()
{
delete ui;
}
//打开串口
void MainWindow::on_pushButton_2_clicked()
{
if(ui->pushButton_2->text()==QString("打开串口"))
{
//设置串口名
QString spTxt = ui->comboBox->currentText();
spTxt = spTxt.section(':', 0, 0);//spTxt.mid(0, spTxt.indexOf(":"));
qDebug() << spTxt;
serial.setPortName(spTxt);
//设置波特率
serial.setBaudRate(ui->comboBox_2->currentText().toInt());
// 获取串口数据位
if(ui->comboBox_5->currentText() == "5")
{
serial.setDataBits(QSerialPort::Data5);
}
else if(ui->comboBox_5->currentText() == "6")
{
serial.setDataBits(QSerialPort::Data6);
}
else if(ui->comboBox_5->currentText() == "7")
{
serial.setDataBits(QSerialPort::Data7);
}
else if(ui->comboBox_5->currentText() == "8")
{
serial.setDataBits(QSerialPort::Data8);
}
// 获取串口奇偶校验位
if(ui->comboBox_3->currentText() == "None")
{
serial.setParity(QSerialPort::NoParity);
}
else if(ui->comboBox_3->currentText() == "Odd")
{
serial.setParity(QSerialPort::OddParity);
}
else if(ui->comboBox_3->currentText() == "Even")
{
serial.setParity(QSerialPort::EvenParity);
}
// 获取串口停止位
if(ui->comboBox_4->currentText() == "1")
{
serial.setStopBits(QSerialPort::OneStop);
}
else if(ui->comboBox_4->currentText() == "1.5")
{
serial.setStopBits(QSerialPort::OneAndHalfStop);
}
else if(ui->comboBox_4->currentText() == "2")
{
serial.setStopBits(QSerialPort::TwoStop);
}
//设置流控制
serial.setFlowControl(QSerialPort::NoFlowControl);
//打开串口
if(!serial.open(QIODevice::ReadWrite))
{
QMessageBox::about(NULL,"提示","无法打开串口!");
return;
}
//下拉菜单控件失能
ui->comboBox->setEnabled(false);
ui->comboBox_2->setEnabled(false);
ui->comboBox_3->setEnabled(false);
ui->comboBox_4->setEnabled(false);
ui->comboBox_5->setEnabled(false);
ui->pushButton_2->setText(QString("关闭串口"));
//发送按键使能
ui->pushButton->setEnabled(true);
ui->pushButton_3->setEnabled(false);
}
else
{
//关闭串口
serial.close();
//下拉菜单控件使能
ui->comboBox->setEnabled(true);
ui->comboBox_2->setEnabled(true);
ui->comboBox_3->setEnabled(true);
ui->comboBox_4->setEnabled(true);
ui->comboBox_5->setEnabled(true);
ui->pushButton_2->setText(QString("打开串口"));
//发送按键失能
ui->pushButton->setEnabled(false);
ui->pushButton_3->setEnabled(true);
}
}
//串口发送字符串和16进制切换
void MainWindow::on_checkBox_1_clicked()
{
bool status =ui->checkBox_1->isChecked();
if(status == true)
{
Hex_Output=1;//16进制
}
else if(status == false)
{
Hex_Output=0;//字符串
}
}
//发送数据
void MainWindow::on_pushButton_clicked()
{
int a;
QByteArray str = ui->textEdit_2->toPlainText().toUtf8();//从LineEdit得到字符串
if(Hex_Output==0)
{
a= serial.write(str);
}
else if(Hex_Output==1)
{
int len = str.length();
if(len%2 == 1) //如果发送的数据个数为奇数的,则在前面最后落单的字符前添加一个字符0
{
str = str.insert(len-1,'0'); //insert(int position, const QString & str)
}
QByteArray senddata;
StringToHex(str,senddata);//将str字符串转换为16进制的形式
a= serial.write(senddata);//发送到串口
}
if(a > 0)
{
// 发送字节计数
sendNum += a;
// 状态栏显示计数值
ui->label_9->setText(QString::number(sendNum));
}
}
//串口接收字符串和16进制切换
void MainWindow::on_checkBox_clicked()
{
bool status =ui->checkBox->isChecked();
if(status == true)
{
Hex_Input=1;//16进制
}
else if(status == false)
{
Hex_Input=0;//字符串
}
}
//串口接收
void MainWindow::serialPort_readyRead()
{
if(Hex_Input==1)
{
QByteArray temp = serial.readAll();
recvNum += temp.size();
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->textEdit->insertPlainText(str.toUpper());//大写
ui->textEdit->insertPlainText(" ");//每发送两个字符后添加一个空格
ui->textEdit->moveCursor(QTextCursor::End);
}
}
if(Hex_Input==0)
{
//从接收缓冲区中读取数据
QByteArray buffer = serial.readAll();
recvNum += buffer.size();
//从界面中读取以前收到的数据
QString recv = ui->textEdit->toPlainText();
recv += QString(buffer);
//清空以前的显示
ui->textEdit->clear();
//重新显示
ui->textEdit->append(recv);
}
ui->label_11->setText(QString::number(recvNum));
}
//监测串口
void MainWindow::on_pushButton_3_clicked()
{
ui->comboBox->clear();
//通过QSerialPortInfo查找可用串口
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
// QString serialPortInfo = info.portName() + ": " + info.description();// 串口设备信息,芯片/驱动名称
ui->comboBox->addItem(info.portName() + ": " + info.description());
}
}
//清空接收
void MainWindow::on_pushButton_4_clicked()
{
ui->textEdit->clear();
recvNum=0;
ui->label_11->setText(QString::number(recvNum));
}
//清空发送
void MainWindow::on_pushButton_6_clicked()
{
ui->textEdit_2->clear();
sendNum=0;
ui->label_9->setText(QString::number(sendNum));
}
void MainWindow::StringToHex(QString str, QByteArray &senddata) //字符串转换为十六进制数据0-F
{
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 = 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);
}
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 ch-ch;//不在0-f范围内的会发送成0
}
//保存接收文件
void MainWindow::on_pushButton_5_clicked()
{
if(ui->textEdit->toPlainText()==NULL)
{
QMessageBox::information(this,tr("注意"),tr("当前文本没有内容"),QMessageBox::Ok);
}
else {
QString fileName = QFileDialog::getSaveFileName(
this, tr("save txt file"),
"/", tr("Txt files(*.txt)"));
QFile f1(fileName);
f1.open(QIODevice::WriteOnly|QIODevice::Text);
QTextStream str(&f1);
str<<ui->textEdit->toPlainText();
f1.close();
}
}
//定时发送 选择复选框
void MainWindow::on_checkBox_3_stateChanged(int arg1)
{
// 获取复选框状态,未选为0,选中为2
if(arg1 == 0){
timSend->stop();
// 时间输入框恢复可选
ui->txtSendMs->setEnabled(true);
}else{
// 对输入的值做限幅,小于1ms会弹出对话框提示
if(ui->txtSendMs->text().toInt() >= 1){
timSend->start(ui->txtSendMs->text().toInt());// 设置定时时长,重新计数
// 让时间输入框不可选,避免误操作(输入功能不可用,控件背景为灰色)
ui->txtSendMs->setEnabled(false);
}else{
ui->checkBox_3->setCheckState(Qt::Unchecked);
QMessageBox::critical(this, "错误提示", "定时发送的最小间隔为 1ms\r\n请确保输入的值 >=1");
}
}
}
void MainWindow::on_pushButton_7_clicked()
{
int a;
QByteArray str = ui->txtSendMs_1->text().toUtf8();//从LineEdit得到字符串
if(Hex_Output==0)
{
a= serial.write(str);
}
else if(Hex_Output==1)
{
int len = str.length();
if(len%2 == 1) //如果发送的数据个数为奇数的,则在前面最后落单的字符前添加一个字符0
{
str = str.insert(len-1,'0'); //insert(int position, const QString & str)
}
QByteArray senddata;
StringToHex(str,senddata);//将str字符串转换为16进制的形式
a= serial.write(senddata);//发送到串口
}
if(a > 0)
{
// 发送字节计数
sendNum += a;
// 状态栏显示计数值
ui->label_9->setText(QString::number(sendNum));
}
}
void MainWindow::on_pushButton_8_clicked()
{
int a;
QByteArray str = ui->txtSendMs_2->text().toUtf8();//从LineEdit得到字符串
if(Hex_Output==0)
{
a= serial.write(str);
}
else if(Hex_Output==1)
{
int len = str.length();
if(len%2 == 1) //如果发送的数据个数为奇数的,则在前面最后落单的字符前添加一个字符0
{
str = str.insert(len-1,'0'); //insert(int position, const QString & str)
}
QByteArray senddata;
StringToHex(str,senddata);//将str字符串转换为16进制的形式
a= serial.write(senddata);//发送到串口
}
if(a > 0)
{
// 发送字节计数
sendNum += a;
// 状态栏显示计数值
ui->label_9->setText(QString::number(sendNum));
}
}
void MainWindow::on_pushButton_9_clicked()
{
int a;
QByteArray str = ui->txtSendMs_3->text().toUtf8();//从LineEdit得到字符串
if(Hex_Output==0)
{
a= serial.write(str);
}
else if(Hex_Output==1)
{
int len = str.length();
if(len%2 == 1) //如果发送的数据个数为奇数的,则在前面最后落单的字符前添加一个字符0
{
str = str.insert(len-1,'0'); //insert(int position, const QString & str)
}
QByteArray senddata;
StringToHex(str,senddata);//将str字符串转换为16进制的形式
a= serial.write(senddata);//发送到串口
}
if(a > 0)
{
// 发送字节计数
sendNum += a;
// 状态栏显示计数值
ui->label_9->setText(QString::number(sendNum));
}
}
void MainWindow::on_pushButton_10_clicked()
{
int a;
QByteArray str = ui->txtSendMs_4->text().toUtf8();//从LineEdit得到字符串
if(Hex_Output==0)
{
a= serial.write(str);
}
else if(Hex_Output==1)
{
int len = str.length();
if(len%2 == 1) //如果发送的数据个数为奇数的,则在前面最后落单的字符前添加一个字符0
{
str = str.insert(len-1,'0'); //insert(int position, const QString & str)
}
QByteArray senddata;
StringToHex(str,senddata);//将str字符串转换为16进制的形式
a= serial.write(senddata);//发送到串口
}
if(a > 0)
{
// 发送字节计数
sendNum += a;
// 状态栏显示计数值
ui->label_9->setText(QString::number(sendNum));
}
}
void MainWindow::on_pushButton_11_clicked()
{
int a;
QByteArray str = ui->txtSendMs_5->text().toUtf8();//从LineEdit得到字符串
if(Hex_Output==0)
{
a= serial.write(str);
}
else if(Hex_Output==1)
{
int len = str.length();
if(len%2 == 1) //如果发送的数据个数为奇数的,则在前面最后落单的字符前添加一个字符0
{
str = str.insert(len-1,'0'); //insert(int position, const QString & str)
}
QByteArray senddata;
StringToHex(str,senddata);//将str字符串转换为16进制的形式
a= serial.write(senddata);//发送到串口
}
if(a > 0)
{
// 发送字节计数
sendNum += a;
// 状态栏显示计数值
ui->label_9->setText(QString::number(sendNum));
}
}
void MainWindow::on_pushButton_12_clicked()
{
int a;
QByteArray str = ui->txtSendMs_6->text().toUtf8();//从LineEdit得到字符串
if(Hex_Output==0)
{
a= serial.write(str);
}
else if(Hex_Output==1)
{
int len = str.length();
if(len%2 == 1) //如果发送的数据个数为奇数的,则在前面最后落单的字符前添加一个字符0
{
str = str.insert(len-1,'0'); //insert(int position, const QString & str)
}
QByteArray senddata;
StringToHex(str,senddata);//将str字符串转换为16进制的形式
a= serial.write(senddata);//发送到串口
}
if(a > 0)
{
// 发送字节计数
sendNum += a;
// 状态栏显示计数值
ui->label_9->setText(QString::number(sendNum));
}
}
void MainWindow::on_pushButton_13_clicked()
{
int a;
QByteArray str = ui->txtSendMs_7->text().toUtf8();//从LineEdit得到字符串
if(Hex_Output==0)
{
a= serial.write(str);
}
else if(Hex_Output==1)
{
int len = str.length();
if(len%2 == 1) //如果发送的数据个数为奇数的,则在前面最后落单的字符前添加一个字符0
{
str = str.insert(len-1,'0'); //insert(int position, const QString & str)
}
QByteArray senddata;
StringToHex(str,senddata);//将str字符串转换为16进制的形式
a= serial.write(senddata);//发送到串口
}
if(a > 0)
{
// 发送字节计数
sendNum += a;
// 状态栏显示计数值
ui->label_9->setText(QString::number(sendNum));
}
}
void MainWindow::on_pushButton_14_clicked()
{
int a;
QByteArray str = ui->txtSendMs_8->text().toUtf8();//从LineEdit得到字符串
if(Hex_Output==0)
{
a= serial.write(str);
}
else if(Hex_Output==1)
{
int len = str.length();
if(len%2 == 1) //如果发送的数据个数为奇数的,则在前面最后落单的字符前添加一个字符0
{
str = str.insert(len-1,'0'); //insert(int position, const QString & str)
}
QByteArray senddata;
StringToHex(str,senddata);//将str字符串转换为16进制的形式
a= serial.write(senddata);//发送到串口
}
if(a > 0)
{
// 发送字节计数
sendNum += a;
// 状态栏显示计数值
ui->label_9->setText(QString::number(sendNum));
}
}
void MainWindow::on_pushButton_15_clicked()
{
int a;
QByteArray str = ui->txtSendMs_9->text().toUtf8();//从LineEdit得到字符串
if(Hex_Output==0)
{
a= serial.write(str);
}
else if(Hex_Output==1)
{
int len = str.length();
if(len%2 == 1) //如果发送的数据个数为奇数的,则在前面最后落单的字符前添加一个字符0
{
str = str.insert(len-1,'0'); //insert(int position, const QString & str)
}
QByteArray senddata;
StringToHex(str,senddata);//将str字符串转换为16进制的形式
a= serial.write(senddata);//发送到串口
}
if(a > 0)
{
// 发送字节计数
sendNum += a;
// 状态栏显示计数值
ui->label_9->setText(QString::number(sendNum));
}
}
void MainWindow::on_pushButton_16_clicked()
{
int a;
QByteArray str = ui->txtSendMs_10->text().toUtf8();//从LineEdit得到字符串
if(Hex_Output==0)
{
a= serial.write(str);
}
else if(Hex_Output==1)
{
int len = str.length();
if(len%2 == 1) //如果发送的数据个数为奇数的,则在前面最后落单的字符前添加一个字符0
{
str = str.insert(len-1,'0'); //insert(int position, const QString & str)
}
QByteArray senddata;
StringToHex(str,senddata);//将str字符串转换为16进制的形式
a= serial.write(senddata);//发送到串口
}
if(a > 0)
{
// 发送字节计数
sendNum += a;
// 状态栏显示计数值
ui->label_9->setText(QString::number(sendNum));
}
}
void MainWindow::on_pushButton_17_clicked()
{
int a;
QByteArray str = ui->txtSendMs_11->text().toUtf8();//从LineEdit得到字符串
if(Hex_Output==0)
{
a= serial.write(str);
}
else if(Hex_Output==1)
{
int len = str.length();
if(len%2 == 1) //如果发送的数据个数为奇数的,则在前面最后落单的字符前添加一个字符0
{
str = str.insert(len-1,'0'); //insert(int position, const QString & str)
}
QByteArray senddata;
StringToHex(str,senddata);//将str字符串转换为16进制的形式
a= serial.write(senddata);//发送到串口
}
if(a > 0)
{
// 发送字节计数
sendNum += a;
// 状态栏显示计数值
ui->label_9->setText(QString::number(sendNum));
}
}
void MainWindow::on_pushButton_18_clicked()
{
int a;
QByteArray str = ui->txtSendMs_12->text().toUtf8();//从LineEdit得到字符串
if(Hex_Output==0)
{
a= serial.write(str);
}
else if(Hex_Output==1)
{
int len = str.length();
if(len%2 == 1) //如果发送的数据个数为奇数的,则在前面最后落单的字符前添加一个字符0
{
str = str.insert(len-1,'0'); //insert(int position, const QString & str)
}
QByteArray senddata;
StringToHex(str,senddata);//将str字符串转换为16进制的形式
a= serial.write(senddata);//发送到串口
}
if(a > 0)
{
// 发送字节计数
sendNum += a;
// 状态栏显示计数值
ui->label_9->setText(QString::number(sendNum));
}
}
void MainWindow::on_pushButton_19_clicked()
{
int a;
QByteArray str = ui->txtSendMs_13->text().toUtf8();//从LineEdit得到字符串
if(Hex_Output==0)
{
a= serial.write(str);
}
else if(Hex_Output==1)
{
int len = str.length();
if(len%2 == 1) //如果发送的数据个数为奇数的,则在前面最后落单的字符前添加一个字符0
{
str = str.insert(len-1,'0'); //insert(int position, const QString & str)
}
QByteArray senddata;
StringToHex(str,senddata);//将str字符串转换为16进制的形式
a= serial.write(senddata);//发送到串口
}
if(a > 0)
{
// 发送字节计数
sendNum += a;
// 状态栏显示计数值
ui->label_9->setText(QString::number(sendNum));
}
}
void MainWindow::on_pushButton_20_clicked()
{
int a;
QByteArray str = ui->txtSendMs_14->text().toUtf8();//从LineEdit得到字符串
if(Hex_Output==0)
{
a= serial.write(str);
}
else if(Hex_Output==1)
{
int len = str.length();
if(len%2 == 1) //如果发送的数据个数为奇数的,则在前面最后落单的字符前添加一个字符0
{
str = str.insert(len-1,'0'); //insert(int position, const QString & str)
}
QByteArray senddata;
StringToHex(str,senddata);//将str字符串转换为16进制的形式
a= serial.write(senddata);//发送到串口
}
if(a > 0)
{
// 发送字节计数
sendNum += a;
// 状态栏显示计数值
ui->label_9->setText(QString::number(sendNum));
}
}
void MainWindow::on_pushButton_21_clicked()
{
int a;
QByteArray str = ui->txtSendMs_15->text().toUtf8();//从LineEdit得到字符串
if(Hex_Output==0)
{
a= serial.write(str);
}
else if(Hex_Output==1)
{
int len = str.length();
if(len%2 == 1) //如果发送的数据个数为奇数的,则在前面最后落单的字符前添加一个字符0
{
str = str.insert(len-1,'0'); //insert(int position, const QString & str)
}
QByteArray senddata;
StringToHex(str,senddata);//将str字符串转换为16进制的形式
a= serial.write(senddata);//发送到串口
}
if(a > 0)
{
// 发送字节计数
sendNum += a;
// 状态栏显示计数值
ui->label_9->setText(QString::number(sendNum));
}
}
void MainWindow::Baud_rate_custom()
{
bool ok;
int text = QInputDialog::getInt(this, tr("自定义波特率"),tr("请输入波特率"),9600,1,9999999,0, &ok);
if (ok && text >= 1)
{
Baud_rate = QString::number(text);
}
}
void MainWindow::on_comboBox_2_activated(const QString &arg1)
{
if(arg1=="custom")
{
Baud_rate_custom();
ui->comboBox_2->addItem(Baud_rate);
}
}
作者也是小白,代码还有很多问题,希望大家指正,代码太长,完整工程我会上传资源。
3、main.cpp文件内容:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
4、pro文件:
#-------------------------------------------------
#
# Project created by QtCreator 2022-03-04T17:01:41
#
#-------------------------------------------------
QT += core gui
QT += serialport
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = demo_3
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
RC_ICONS = demo_22.ico
4、代码介绍
博主也不是废话很多的人,也不喜欢直接看一些原理,喜欢直接上手去做一个项目,通过做项目的过程中去学习和了解,所以直接上源码,希望大家在程序能有效果的同时去慢慢了解,废话不多说现在介绍下代码。
1、添加库
QT5是自带QSerialPor这个类,使用时需要在pro文件里面添加:
QT += serialport
其次需要在mainwindow.cpp文件夹中加入以下两个头文件:
#include <QSerialPort> //提供访问串口的功能
#include <QSerialPortInfo> //提供系统中存在的串口的信息
2、串口配置程序
//创建串口对象
QSerialPort serial;
//设置串口名为COM5
serial.setPortName("COM5");
//设置波特率为115200
serial.setBaudRate(QSerialPort::Baud115200);
//设置数据位数为8位
serial.setDataBits(QSerialPort::Data8);
//设置奇偶校验无
serial.setParity(QSerialPort::NoParity);
//设置停止位为一位
serial.setStopBits(QSerialPort::OneStop);
//设置流控制为无
serial.setFlowControl(QSerialPort::NoFlowControl);
//打开串口
serial.open(QIODevice::ReadWrite);
以上程序在mainwindow.cpp文件中,主要配置串口工作模式。
3、串口发送数据
//发送数据
void MainWindow::on_pushButton_clicked()
{
int a;
QByteArray str = ui->textEdit_2->toPlainText().toUtf8();//从LineEdit得到字符串
if(Hex_Output==0)
{
a= serial.write(str);//发送完毕后返回发送的字节数
}
else if(Hex_Output==1)
{
int len = str.length();
if(len%2 == 1) //如果发送的数据个数为奇数的,则在前面最后落单的字符前添加一个字符0
{
str = str.insert(len-1,'0'); //insert(int position, const QString & str)
}
QByteArray senddata;
StringToHex(str,senddata);//将str字符串转换为16进制的形式
a= serial.write(senddata);//发送完毕后返回发送的字节数
}
if(a > 0)
{
// 发送字节计数
sendNum += a;
// 状态栏显示计数值
ui->label_9->setText(QString::number(sendNum));
}
}
上段函数是发送数据,最终使用write函数便可以把字节数组中的字节发送出去。上段程序Hex_Output是判断以16进制发送还是以字符串发送。a是用来统计发送的数据字节数,最后统计到sendNum 。
4、串口接收数据
//连接信号和槽
QObject::connect(&serial, &QSerialPort::readyRead, this, &MainWindow::serialPort_readyRead);
//串口接收
void MainWindow::serialPort_readyRead()
{
if(Hex_Input==1)
{
//从接收缓冲区中读取数据
QByteArray temp = serial.readAll();
recvNum += temp.size();//记录接收数据字节数
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->textEdit->insertPlainText(str.toUpper());//大写
ui->textEdit->insertPlainText(" ");//每发送两个字符后添加一个空格
ui->textEdit->moveCursor(QTextCursor::End);
}
}
if(Hex_Input==0)
{
//从接收缓冲区中读取数据
QByteArray buffer = serial.readAll();
recvNum += buffer.size();
//从界面中读取以前收到的数据
QString recv = ui->textEdit->toPlainText();
recv += QString(buffer);
//清空以前的显示
ui->textEdit->clear();
//重新显示
ui->textEdit->append(recv);
}
ui->label_11->setText(QString::number(recvNum));
}
串口在收到数据后,会将数据存入接收缓冲区。通过readAll()函数读取缓存区数据,在这里为了实时读取数据,编写一个槽函数来读取数据。
5、关闭串口
serial->close();
串口不使用的时候可以使用serial->close();关闭串口。
总结
博主也是刚学习qt编程,串口功能实现很多是借鉴github上开源项目,有很多代码都是拼凑的,有不对的希望大家指正,再次也很希望这个教程能让刚学习qt的朋友们快速上手。
完整工程