Qt5串口助手(QSerialPort)

1 篇文章 0 订阅

一.易模糊点

1.1 下位机回数据

可能分隔多次传输,需字符串拼接。
可能累计多次传输,需取最后一次完整命令。

1.2 发送数据格式

A.hex或ascii。
B.QByteData结尾是否加"\r\n"。

sendData.append("\r\n");/*是否加回车换行*/
//sendData = sendData.fromHex(sendData);/*获取hex格式的数据*/
//char *temp=sendData.data();
m_serialPort->write(sendData);//直接发送ascii

1.3 循环冗余检验

Qt:计算CRC校验值(CRC16和CRC32

二.代码

2.1 串口类

#ifndef SERIAL_H
#define SERIAL_H

#include <QObject>
#include <QSerialPort>

class Serial:public QObject //要继承QObject,才能使用 connect() 函数
{
    Q_OBJECT

public:
    Serial();
    QStringList scanSerial();                    //扫描可用串口
    bool open(QString serialName, int baudRate); //打开串口
    void close();                                //关闭串口
    void sendData(QByteArray &sendData);         //发送数据给下位机
    QByteArray getReadBuf();                     //获得读取数据缓冲区
    void clearReadBuf();                         //清除读取数据缓冲区
    QByteArray hexStringToByteArray(QString HexString); //将16进制字符串转换为对应的字节序列

signals:
    void readSignal(); // 当下位机中有数据发送过来时就会触发这个信号,以提示其它类对象

public slots:
    void readData(); // 读取下位机发来数据
//public slots:
//    void readSerialData(); // 读取从自定义串口类获得的数据

private:
    QSerialPort *m_serialPort; // 实例化一个指向串口的指针,可以用于访问串口
    QByteArray m_readBuf; // 存储下位机发来数据的缓冲区
};
#include "Serial.h"
#include <QMessageBox>
#include <QSerialPortInfo>
#include <QDebug>
#pragma execution_character_set("utf-8")

Serial::Serial()
{
    // 初始化串口
    m_serialPort = new QSerialPort;
}

// 扫描可用串口
QStringList Serial::scanSerial()//会有先打开串口过程
{
    QStringList serialStrList;

    // 读取串口信息 static QList<QSerialPortInfo> availablePorts();
    foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
    {
        m_serialPort->setPort(info);
        // 判断端口能否以读写方式打开
        if(m_serialPort->open(QIODevice::ReadWrite))
        {
            serialStrList.append(m_serialPort->portName());
            m_serialPort->close(); // 然后自动关闭等待人为开启(通过"打开串口按钮")
        }
    }

    return serialStrList;
}

// 打开串口
bool Serial::open(QString serialName, int baudRate)
{   //COM4,115200
    //设置串口名
    m_serialPort->setPortName(serialName);
    //打开串口(以读写方式)
    if(m_serialPort->open(QIODevice::ReadWrite))
    {
        m_serialPort->setBaudRate(baudRate); // 设置波特率(默认为115200)
        m_serialPort->setStopBits( QSerialPort::OneStop ); //设置停止位(停止位为1)
        m_serialPort->setDataBits( QSerialPort::Data8 );   //设置数据位(数据位为8位)
        m_serialPort->setParity( QSerialPort::NoParity );  //设置校验位(无校验位)
        m_serialPort->setFlowControl( QSerialPort::NoFlowControl ); //设置流控制(无数据流控制)

        // 当下位机中有数据发送过来时就会响应这个槽函数
        connect(m_serialPort, SIGNAL(readyRead()), this, SLOT(readData()));
        // 当下位机中有数据发送过来时就会触发这个信号,以提示其它类对象
        connect(m_serialPort, SIGNAL(readyRead()), this, SIGNAL(readSignal()));//信号可直接连接信号
        return true;
    }
    return false;
}

// 关闭串口
void Serial::close()
{
    m_serialPort->clear();
    m_serialPort->close();
}

// 发送数据给下位机
void Serial::sendData(QByteArray &sendData)
{
    // 发送数据帧
    m_serialPort->write(sendData);
}

// 读取下位机发来数据
void Serial::readData()// 与硬件有关,可能需要拼接,可能不要
{
    // 将下位机发来数据存储在数据缓冲区
    QByteArray data = m_serialPort->readAll();

    //QByteArray 转 16进制字符串
    QString ret(data.toHex().toUpper());
    int len = ret.length()/2;
    for(int i=1;i<len;i++)
    {
        ret.insert(2*i+i-1," ");
    }

    //m_readBuf.clear();
    m_readBuf.append(ret);//1串返回指令可能分多段,故需拼接
}

// 获得读取数据缓冲区
QByteArray Serial::getReadBuf()
{
    return m_readBuf;
}

// 清除读取数据缓冲区
void Serial::clearReadBuf()
{
    m_readBuf.clear();
}

// 将16进制字符串转换为对应的字节序列
QByteArray Serial::hexStringToByteArray(QString HexString)
{
    //QMessageBox::information(nullptr,QString("提示"),QString("触发断点"));//this,
    bool ok;//默认false
    QByteArray ret;
    HexString = HexString.trimmed();//01050007ff003DFB
    HexString = HexString.simplified();
    QStringList sl = HexString.split(" ");

    foreach (QString s, sl)
    {
        if(!s.isEmpty())
        {
            char c = static_cast<char>(s.toInt(&ok, 16) & 0xFF);
            if(ok)
            {
                ret.append(c);
            }
            else
            {
                qDebug()<<QString("非法的16进制字符 ")<<s;
                QMessageBox::warning(nullptr, tr("错误:"), QString("非法的16进制字符: \"%1\"").arg(s));
            }
        }
    }

    return ret;
}

2.2 MainWindow调用

m_Serial = new Serial();
connect(m_Serial,&Serial::readSignal,this,&MainWindow::readSerialData);
void MainWindow::readSerialData()
{
    ui->TextEdit_Recv->clear();//m_readBuf未清空,故在此清空
    QByteArray readBuf=m_Serial->getReadBuf();
    QTextCodec *tc = QTextCodec::codecForName("GBK");
    QString tmpQStr = tc->toUnicode(readBuf);

    ui->TextEdit_Recv->insertPlainText(tmpQStr);
    ui->TextEdit_Recv->moveCursor(QTextCursor::End); // 在末尾移动光标一格
    ui->TextEdit_Recv->insertPlainText(" ");
    //
    tmpQStr.remove(QRegExp("\\s"));
}

2.3 进制转换

dec1 = hex1.toInt(0,16);//十六进制转十进制
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值