这两天捣鼓了一个简单的串口调试助手,参考QT例程terminal,可能是因为新手的缘故,发现字符发送和字符显示比较容易实现,而十六进制相对难实现一些。在这里记录一下我的实现方法。
///
/// \brief Widget::writeData
///向串口写数据
void Widget::writeData()
{
if(!m_pSerialPort->isOpen())return;//串口未打开则返回
QString str = ui->textEdit_Send->toPlainText(); //获取发送数据
QByteArray ba = str.toLatin1(); //转换成字节数组类型
if(ui->radioButton_SendAscii->isChecked())//字符发送
{
m_pSerialPort->write(ba);
}
else //十六进制发送
{
ba=ba.replace("0x","");//将字符串中的0x字符替换成空字符
ba=ba.replace("0X","");//将字符串中的0X字符替换成空字符
ba=ba.replace(" ",""); //将字符串中的空格字符替换成空字符
for(int i =0;i < ( ba.length() - ba.length()%2 )/2;i++) //循环写字节,两个数组成一个字节,循环次数为数据长度的一半,奇数时最后一位先不写
{
char ch= ba.mid(i*2,2).toUShort(nullptr,16);//2个数字组成一个字节,转换成十六进制
m_pSerialPort->putChar(ch);//发送一个字节
}
if(ba.length()%2 != 0)//数字个数是奇数 单独处理最后一个数
{
char ch= ba.right(1).toUShort(nullptr,16);//获取最后一个数
m_pSerialPort->putChar(ch);//发送最后一个字节
}
}
}
void Widget::read()
{
if(ui->radioButton_DisplayAscii->isChecked()) //字符显示
{ QByteArray data = m_pSerialPort->readAll();
ui->textEdit_Receive->append(data);
}
else //十六进制显示
{ QByteArray data = m_pSerialPort->readAll().toHex().toUpper(); //转换成十六进制大写
QByteArray newBA;
for(int i = 0; i<data.length()/2;i++) //两个数字组成一个字节,每个字节后加空格
{ newBA.append(data.mid(i*2,2));
newBA.append(" ");
}
ui->textEdit_Receive->append(newBA); //接收区显示 -- 追加方式
}
}
与串口调试助手连接通讯效果:
完整代码:
//widget.h
//widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QSerialPort>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private:
Ui::Widget *ui;
private:
QSerialPort *m_pSerialPort = nullptr;
private:
bool openSerialPort();
void fillPortsInfo();
void fillPortsParameters();
private slots:
void on_openSerialPortBtn_clicked();
void writeData();
void read();
};
#endif // WIDGET_H
//widget.cpp
//widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QSerialPortInfo>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
m_pSerialPort = new QSerialPort(this);
fillPortsInfo(); //端口号填充
fillPortsParameters();//串口参数填充
connect(ui->sendBtn,&QPushButton::clicked,this,&Widget::writeData);//发送按钮连接writeData
connect(m_pSerialPort,&QSerialPort::readyRead,this,&Widget::read); //串口接收连接read
}
Widget::~Widget()
{
delete ui;
}
///
/// \brief Widget::openSerialPort
/// \return
///打开串口
bool Widget::openSerialPort()
{
m_pSerialPort->setPortName(ui->comboBox_PortNO->currentText());//设置端口号
m_pSerialPort->setBaudRate(ui->comboBox_BaudRate->currentText().toInt());//设置波特率 其他设置默认
//打开串口
if (m_pSerialPort->open(QIODevice::ReadWrite)) {
qDebug()<<"open success";
return true;
}
else {
qDebug()<<"open err";
return false;
}
}
///
/// \brief Widget::fillPortsInfo
///端口号填充
void Widget::fillPortsInfo()
{
ui->comboBox_PortNO->clear(); //清空端口号
const auto infos = QSerialPortInfo::availablePorts();//获得可用端口号
QList<QString> list; //接收端口号链表
for (const QSerialPortInfo &info : infos) {
list<<info.portName();//端口号填入链表
}
list.sort(); //从小到大排序
ui->comboBox_PortNO->addItems(list);//端口号加入下拉框
}
///
/// \brief Widget::fillPortsParameters
///填充串口参数
void Widget::fillPortsParameters()
{ /*波特率填充*/
ui->comboBox_BaudRate->addItem(QStringLiteral("9600"), QSerialPort::Baud9600);
ui->comboBox_BaudRate->addItem(QStringLiteral("19200"), QSerialPort::Baud19200);
ui->comboBox_BaudRate->addItem(QStringLiteral("38400"), QSerialPort::Baud38400);
ui->comboBox_BaudRate->addItem(QStringLiteral("115200"), QSerialPort::Baud115200);
}
///
/// \brief Widget::on_openSerialPortBtn_clicked
///openSerialPortBtn 打开串口按钮响应槽函数
void Widget::on_openSerialPortBtn_clicked()
{
if(m_pSerialPort->isOpen())
{
m_pSerialPort->close();
ui->openSerialPortBtn->setText(u8"打开串口");
}
else
{
if(openSerialPort())
ui->openSerialPortBtn->setText(u8"关闭串口");
}
}
///
/// \brief Widget::writeData
///向串口写数据
void Widget::writeData()
{
if(!m_pSerialPort->isOpen())return;//串口未打开则返回
QString str = ui->textEdit_Send->toPlainText(); //获取发送数据
QByteArray ba = str.toLatin1(); //转换成字节数组类型
if(ui->radioButton_SendAscii->isChecked())//字符发送
{
m_pSerialPort->write(ba);
}
else //十六进制发送
{
ba=ba.replace("0x","");//将字符串中的0x字符替换成空字符
ba=ba.replace("0X","");//将字符串中的0X字符替换成空字符
ba=ba.replace(" ",""); //将字符串中的空格字符替换成空字符
for(int i =0;i < ( ba.length() - ba.length()%2 )/2;i++) //循环写字节,两个数组成一个字节,循环次数为数据长度的一半,奇数时最后一位先不写
{
char ch= ba.mid(i*2,2).toUShort(nullptr,16);//2个数字组成一个字节,转换成十六进制
m_pSerialPort->putChar(ch);//发送一个字节
}
if(ba.length()%2 != 0)//数字个数是奇数 单独处理最后一个数
{
char ch= ba.right(1).toUShort(nullptr,16);//获取最后一个数
m_pSerialPort->putChar(ch);//发送最后一个字节
}
}
}
void Widget::read()
{
if(ui->radioButton_DisplayAscii->isChecked()) //字符显示
{ QByteArray data = m_pSerialPort->readAll();
ui->textEdit_Receive->append(data);
}
else //十六进制显示
{ QByteArray data = m_pSerialPort->readAll().toHex().toUpper(); //转换成十六进制大写
QByteArray newBA;
for(int i = 0; i<data.length()/2;i++) //两个数字组成一个字节,每个字节后加空格
{ newBA.append(data.mid(i*2,2));
newBA.append(" ");
}
ui->textEdit_Receive->append(newBA); //接收区显示 -- 追加方式
}
}