效果图
注:16进制显示没有用空格分开
1、在项目管理文件(.pro) 里面添加
QT += serialport //加入串口模块
2、引用头文件
#include <QSerialPort> //提供访问串口的功能
#include <QSerialPortInfo> //提供系统中存在的串口的信息
3、界面设计
4、定义一个 QSerialPort 类
QSerialPort Serial;
5、串口设置需要的函数
Serial.setPortName("COM6"); //设置端口号
Serial.setBaudRate(9600); //设置波特率
Serial.setDataBits(QSerialPort::Data8); //设置数据位
Serial.setStopBits(QSerialPort::OneStop); //设置停止位
Serial.setParity(QSerialPort:NoParity); //设置奇偶校验
Serial.setFlowControl(QSerialPort::NoFlowControl);//设置流控制模式
6、串口开关控制
void subwidget::on_open_Button_clicked()
{
if(ui->open_Button->text() == QString("打开串口")) //串口未打开
{
//设置端口号
Serial.setPortName(ui->comBox->currentText());
//设置波特率
Serial.setBaudRate(ui->bandRateBox->currentText().toInt());
//设置数据位
switch (ui->dataBitBox->currentText().toInt())
{
case 8: Serial.setDataBits(QSerialPort::Data8); break;
case 7: Serial.setDataBits(QSerialPort::Data7); break;
case 6: Serial.setDataBits(QSerialPort::Data6); break;
case 5: Serial.setDataBits(QSerialPort::Data5); break;
default: break;
}
//设置停止位
switch (ui->stopBitBox->currentText().toInt())
{
case 1: Serial.setStopBits(QSerialPort::OneStop);break;
case 2: Serial.setStopBits(QSerialPort::TwoStop);break;
default:break;
}
//设置校验方式
switch (ui->checkoutBox->currentIndex())
{
case 0: Serial.setParity(QSerialPort::NoParity);break;
default:break;
}
//设置流控制模式
Serial.setFlowControl(QSerialPort::NoFlowControl);
//打开串口
if(Serial.open(QIODevice::ReadWrite)==false)
{
QMessageBox::warning(NULL , "提示", "串口打开失败!");
return;
}
// 失能串口设置控件
ui->comBox->setEnabled(false);
ui->checkoutBox->setEnabled(false);
ui->bandRateBox->setEnabled(false);
ui->dataBitBox->setEnabled(false);
ui->stopBitBox->setEnabled(false);
ui->search_Button->setEnabled(false);
//调整串口控制按钮的文字提示
ui->open_Button->setText(QString("关闭串口"));
}
else //串口已经打开
{
Serial.close();
// 使能串口设置控件
ui->comBox->setEnabled(true);
ui->checkoutBox->setEnabled(true);
ui->bandRateBox->setEnabled(true);
ui->dataBitBox->setEnabled(true);
ui->stopBitBox->setEnabled(true);
ui->search_Button->setEnabled(true);
//调整串口控制按钮的文字提示
ui->open_Button->setText(QString("打开串口"));
}
}
7、检测可用端口
void subwidget::on_search_Button_clicked()
{
// 清除当前显示的端口号
ui->comBox->clear();
//检索端口号
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
ui->comBox->addItem(info.portName());
}
}
8、串口发送
void subwidget::on_send_Button_clicked()
{
if(Serial.isOpen()==false) //判断串口是否正常打开
{
QMessageBox::warning(NULL , "提示", "请打开串口!");
return;
}
//toPlainText() 转换为纯文本格式
//toUtf8() 转换为UTF-8 编码
QByteArray senddata = ui->SendEdit->toPlainText().toUtf8();
//判断是否有非16进制字符
if(ui->send16Box->isChecked()==true) //勾选了16进制发送
{
int cnt = senddata.size(); //要发送数据的长度
char *data = senddata.data();
for(int i=0;i<cnt;i++)//判断是否有非16进制字符
{
if(data[i]>='0' && (data[i]<='9'))
continue;
else if(data[i]>='a' && (data[i]<='f'))
continue;
else if(data[i]>='A' && (data[i]<='F'))
continue;
else if(data[i] == ' ') //输入为空格
continue;
else
{
QMessageBox::warning(NULL , "提示", "输入非16进制字符!");
return;
}
}
//字符串转化为16进制数 "1234" --> 0X1234
//转换时会自动除去非16进制字符
senddata = senddata.fromHex(senddata);
}
//勾选了发送新行
if(ui->newlineBox->isChecked()==true)
{
int cnt = senddata.size();
senddata = senddata.insert(cnt,"\r\n"); //插入回车换行符
}
Serial.write(senddata); //通过串口发送数据
}
9、在接收窗口显示收到的数据
注:测试时不是一次性全部接收串口发送的数据,没有实现16进制字符用空格分开。
void subwidget::Serial_read()
{
//读取串口收到的数据
QByteArray buffer = Serial.readAll();
//判断是否需要16进制显示
if(ui->show16Box->isChecked()==true)
{
buffer = buffer.toHex() ;//转换为16进制 例:"1234" -->“31323334”
}
QString receive = QString(buffer);
//在接受窗口显示收到的数据
ui->receiveEdit->insertPlainText(receive);
}
注:需要使用connect()关联
connect(&Serial, &QSerialPort::readyRead , this , &subwidget::Serial_read);
完整程序
.H 文件
#ifndef SUBWIDGET_H
#define SUBWIDGET_H
#include <QWidget>
#include <QSerialPort> //提供访问串口的功能
#include <QSerialPortInfo> //提供系统中存在的串口的信息
namespace Ui {
class subwidget;
}
class subwidget : public QWidget
{
Q_OBJECT
public:
explicit subwidget(QWidget *parent = nullptr);
~subwidget();
private:
Ui::subwidget *ui;
public:
QSerialPort Serial;
private slots:
void on_open_Button_clicked();
void on_send_Button_clicked();
void on_search_Button_clicked();
void Serial_read();
void on_clear_r_Button_clicked();
};
#endif // SUBWIDGET_H
cpp文件
#include "subwidget.h"
#include "ui_subwidget.h"
#include <QMessageBox>
#include <QDataStream>
subwidget::subwidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::subwidget)
{
ui->setupUi(this);
this->setWindowTitle("TEST子窗口"); //设置子窗口标题
connect(&Serial, &QSerialPort::readyRead , this , &subwidget::Serial_read);
ui->bandRateBox->setCurrentIndex(0); //波特率默认9600
}
subwidget::~subwidget()
{
delete ui;
}
//串口控制 槽函数
void subwidget::on_open_Button_clicked()
{
if(ui->open_Button->text() == QString("打开串口")) //串口未打开
{
//设置端口号
Serial.setPortName(ui->comBox->currentText());
//设置波特率
Serial.setBaudRate(ui->bandRateBox->currentText().toInt());
//设置数据位
switch (ui->dataBitBox->currentText().toInt())
{
case 8: Serial.setDataBits(QSerialPort::Data8); break;
case 7: Serial.setDataBits(QSerialPort::Data7); break;
case 6: Serial.setDataBits(QSerialPort::Data6); break;
case 5: Serial.setDataBits(QSerialPort::Data5); break;
default: break;
}
//设置停止位
switch (ui->stopBitBox->currentText().toInt())
{
case 1: Serial.setStopBits(QSerialPort::OneStop);break;
case 2: Serial.setStopBits(QSerialPort::TwoStop);break;
default:break;
}
//设置校验方式
switch (ui->checkoutBox->currentIndex())
{
case 0: Serial.setParity(QSerialPort::NoParity);break;
default:break;
}
//设置流控制模式
Serial.setFlowControl(QSerialPort::NoFlowControl);
//打开串口
if(Serial.open(QIODevice::ReadWrite)==false)
{
QMessageBox::warning(NULL , "提示", "串口打开失败!");
return;
}
// 失能串口设置控件
ui->comBox->setEnabled(false);
ui->checkoutBox->setEnabled(false);
ui->bandRateBox->setEnabled(false);
ui->dataBitBox->setEnabled(false);
ui->stopBitBox->setEnabled(false);
ui->search_Button->setEnabled(false);
//调整串口控制按钮的文字提示
ui->open_Button->setText(QString("关闭串口"));
}
else //串口已经打开
{
Serial.close();
// 使能串口设置控件
ui->comBox->setEnabled(true);
ui->checkoutBox->setEnabled(true);
ui->bandRateBox->setEnabled(true);
ui->dataBitBox->setEnabled(true);
ui->stopBitBox->setEnabled(true);
ui->search_Button->setEnabled(true);
//调整串口控制按钮的文字提示
ui->open_Button->setText(QString("打开串口"));
}
}
void subwidget::on_search_Button_clicked()
{
// 清除当前显示的端口号
ui->comBox->clear();
//检索端口号
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
ui->comBox->addItem(info.portName());
}
}
void subwidget::on_clear_r_Button_clicked()
{
ui->receiveEdit->clear();
}
void subwidget::on_send_Button_clicked()
{
if(Serial.isOpen()==false) //判断串口是否正常打开
{
QMessageBox::warning(NULL , "提示", "请打开串口!");
return;
}
//toPlainText() 转换为纯文本格式
//toUtf8() 转换为UTF-8 编码
QByteArray senddata = ui->SendEdit->toPlainText().toUtf8();
//判断是否有非16进制字符
if(ui->send16Box->isChecked()==true) //勾选了16进制发送
{
int cnt = senddata.size(); //要发送数据的长度
char *data = senddata.data();
for(int i=0;i<cnt;i++)//判断是否有非16进制字符
{
if(data[i]>='0' && (data[i]<='9'))
continue;
else if(data[i]>='a' && (data[i]<='f'))
continue;
else if(data[i]>='A' && (data[i]<='F'))
continue;
else if(data[i] == ' ') //输入为空格
continue;
else
{
QMessageBox::warning(NULL , "提示", "输入非16进制字符!");
return;
}
}
//字符串转化为16进制数 "1234" --> 0X1234
//转换时会自动除去非16进制字符
senddata = senddata.fromHex(senddata);
}
//勾选了发送新行
if(ui->newlineBox->isChecked()==true)
{
int cnt = senddata.size();
senddata = senddata.insert(cnt,"\r\n"); //插入回车换行符
}
Serial.write(senddata); //通过串口发送数据
}
//显示收到的数据
void subwidget::Serial_read()
{
//读取串口收到的数据
QByteArray buffer = Serial.readAll();
//判断是否需要16进制显示
if(ui->show16Box->isChecked()==true)
{
buffer = buffer.toHex() ;//转换为16进制 例:"1234" -->“31323334”
}
QString receive = QString(buffer);
//在接受窗口显示收到的数据
ui->receiveEdit->insertPlainText(receive);
}