QT学习笔记:简单的串口调试助手--实现 字符与十六进制发送接收

这两天捣鼓了一个简单的串口调试助手,参考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); //接收区显示 -- 追加方式
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值