QT 串口通信 CRC-16校验 日志输出

QT 串口通信,接收下位机消息,发送消息给下位机。

如果你是用 CLion 需要在CMakeLists.txt 中添加 : SerialPort   Qt5::SerialPort

set(REQUIRED_LIBS Core Gui Widgets SerialPort)
set(REQUIRED_LIBS_QUALIFIED Qt5::Core Qt5::Gui Qt5::Widgets Qt5::SerialPort)

QT 串口通信 CRC-16校验 日志输出_第1张图片

 如果你是QT Creator 

在.pro 在工程文件中添加以下代码   QT += serialport  

CRC-16校验

github地址

校验方式很多大家可下载大佬源码,分析一下取出自己需要的部分,比如我需要 

CRC-16/XMODEM , 参数对照表对着填写即可。


#include          // 提供访问串口的功能
#include      // 提供系统中存在的串口信息
#include 
#include 
typedef unsigned short uint_16;
typedef unsigned char uint_8;
class SerialCom : public QMainWindow {
Q_OBJECT

public:
    explicit SerialCom(QWidget *parent = nullptr) : QMainWindow(parent) {
        mSerialPort->setBaudRate(QSerialPort::Baud115200, QSerialPort::AllDirections);//设置波特率和读写方向
        mSerialPort->setDataBits(QSerialPort::Data8);        //数据位为8位
        mSerialPort->setFlowControl(QSerialPort::NoFlowControl);//无流控制
        mSerialPort->setParity(QSerialPort::NoParity);    //无校验位
        mSerialPort->setStopBits(QSerialPort::OneStop); //一位停止位
        // 查找可用串口
        QStringList pSerialPortName;
                foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
                pSerialPortName << info.portName();
            }
        if (pSerialPortName.empty()) {
            qInfo() << "未找到串口";
            return;
        }
        qInfo() << "串口名:" << pSerialPortName;
        // 打开串口
        QString &pSerialName = pSerialPortName[0]; // 获取第0个串口
        auto mPortArduino = new QSerialPortInfo(pSerialName);
        if (mPortArduino->isBusy()) {
            qCritical() << QString("%1-串口被占用").arg(pSerialName);
            return;
        }
        mSerialPort->setPortName(pSerialName);
        if (!mSerialPort->open(QIODevice::ReadWrite))//用ReadWrite 的模式尝试打开串口
        {
            qCritical() << QString("%1-打开失败!").arg(pSerialName);
            return;
        }
        qInfo() << "串口已打开:";
        // 向串口发送OK 消息
        QByteArray OK = QByteArray::fromHex(QString("4F 4B 21").toLocal8Bit());
        // 写入发送消息给串口
        mSerialPort->write(OK);
        // 读取串口消息,有消息时会触发这个信号
        connect(mSerialPort, &QSerialPort::readyRead, this, &SerialCom::receiveInfo);

        // 校验
        const QString &mCheckData = QString("3E 01 7B 00 00 00 00 00 43 00 01 00 00 00 00 00 00 00 00 00 00 0B");

        QStringList dataList = mCheckData.split(" ");
        unsigned char buf8[1028] = {0};
        QString temp;
        for (int i = 0; i < dataList.length(); i++) {
            temp = dataList.at(i);
            buf8[i] = temp.toInt(nullptr, 16);
        }

        QByteArray validation = QByteArray::fromHex(
                QString(mCheckData + CRC16(buf8, dataList.length()) + "3E").toUpper().toLocal8Bit());
        mSerialPort->write(validation);
        
        // 关闭串口
        mSerialPort->clear();// 清除缓存
        mSerialPort->close();// 关闭串口


    }


private:
    QSerialPort *mSerialPort = new QSerialPort();//串口对象

    void receiveInfo() {// 用于读取接收串口消息的函数
        QByteArray data = mSerialPort->readAll();      // 读取数据
        if (!data.isEmpty()) {  // 接收到数据
            QString text = data.toHex().toUpper(); //将16进制字节码转字符串
            qDebug() << text;
        }
    }

    static QString CRC16(unsigned char *data, int data_len) {
        //                         数值           长度

        uint_16 crc16 = QString("0000").toUInt(nullptr, 16);
        uint_8 temp1;

        for (; data_len > 0; data_len--) {
            temp1 = *data++;
            crc16 = crc16 ^ (temp1 << 8);
            for (int i = 0; i < 8; i++) {
                if (crc16 & 0x8000)
                    crc16 = (crc16 << 1) ^ QString("1021").toUInt(nullptr, 16);
                else
                    crc16 = crc16 << 1;
            }
        }
        crc16 = crc16 ^ QString("0000").toUInt(nullptr, 16);
        QString crc = QString::number(crc16, 16);
        return crc;
    }
};


QT 日志输出 

QT 串口通信 CRC-16校验 日志输出_第2张图片

 Log.h


#ifndef UNTITLED_LOG_H
#define UNTITLED_LOG_H

#include 
#include 
#include 

class Log : public QMainWindow {
Q_OBJECT
public:
    static Log *mStaticSelf;// 静态方法访问成员变量
    static void outputMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg);

    QTextEdit *mStatus;

    explicit Log(QWidget *parent = nullptr);
};


#endif //UNTITLED_LOG_H

Log.cpp

#include 
#include 
#include 
#include "Log.h"

Log *Log::mStaticSelf;

Log::Log(QWidget *parent) : QMainWindow(parent) {
    mStaticSelf = this;
    qInstallMessageHandler(outputMessage);//注册日志

    mStatus = new QTextEdit(this);
    mStatus->resize(400, 300);
    qDebug() << "Debug";
    qWarning() << "Warning";
    qCritical() << "Critical";
    qInfo() << "Info";
}

void Log::outputMessage(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
    //日志
    static QMutex mutex;
    mutex.lock(); // 加锁
    QString text;
    switch (type) {
        case QtDebugMsg:
            text = QString("Debug");
            break;
        case QtWarningMsg:
            text = QString("Warning");
            break;
        case QtCriticalMsg:
            text = QString("Critical");
            break;
        case QtInfoMsg:
            text = QString("Info");

        case QtFatalMsg:
            break;
    }
    QString current_date_time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss ddd");
    QString current_date = QString("%1:").arg(current_date_time);
    QString message = QString("%1 %2 >> %3").arg(current_date).arg(text).arg(msg);
    mStaticSelf->mStatus->append(message);
    mStaticSelf->mStatus->moveCursor(QTextCursor::End); // 光标末尾
    mStaticSelf->mStatus->moveCursor(QTextCursor::StartOfLine);  // 光标换行
    mutex.unlock();// 解锁
}

你可能感兴趣的:(QT,C++,python,qt,开发语言)