QT 绿米QTA协议 (一)QtCreator

 

一.QtCreator 第一个 EmptyProject

emptyProject.pro

#TARGET = emptyProject
QT+= core gui widgets

HEADERS =

SOURCES = \
   $$PWD/main.cpp

INCLUDEPATH =

#DEFINES = 

 main.cpp

#include<QApplication>
#include<QtWidgets>
#include<QtDebug>
#include<QByteArray>
int main(int argc,char* argv[]){

    QApplication a(argc,argv);
    QWidget w;
    w.show();

    uint16_t CrcReg = 0xFFFF;
    qDebug()<<"Btn_Open_File----------> CrcReg -> " << (CrcReg << 1)  ;
    CrcReg = (CrcReg << 1) ;
    qDebug()<<"Btn_Open_File----------> CrcReg -> " << (CrcReg << 1)  ;
    qDebug()<<"Btn_Open_File----------> CrcReg -> "<< (CrcReg <<= 1) ;

    qDebug()<<"hello";
    return  a.exec();
} 

 控制台

10:11:16: Starting E:\GatsbyDevelop\QT\QTDemo\QTCodeHellow\build-emptyProject-Desktop_Qt_5_14_2_MinGW_64_bit-Debug\debug\emptyProject.exe ...
Btn_Open_File----------> CrcReg ->  131070
Btn_Open_File----------> CrcReg ->  131068
Btn_Open_File----------> CrcReg ->  65532
hello

 二.WeiText Demo建立

新建项目   其他项目  选择 Empty  qmake  Project  平台选32位

二.新建 UI

ui 会新建关联文件

WeiText 

 

三.WeiTexDemo

3.1.QTA 协议

 3.2.WeiText.pro

#TARGET = WeiText
# 加载基础模块
QT+= core gui 
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
QT+= serialport

HEADERS = \
    mainwindow.h \
    usart.h

SOURCES = \
    main.cpp \
    mainwindow.cpp \
    usart.cpp

FORMS += \
    mainwindow.ui  

3.3.mainWindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    Usart_Refresh();
    Dev_init();
}

MainWindow::~MainWindow()
{
    delete ui;
}

/*---------------------User---------------------*/
// 延时中断
void MainWindow::time_run()
{
    Updata_time->stop();
}

// 扫描串口
void MainWindow::Usart_Refresh()
{
    if (ui->Btn_Dev_Connect->text() == "连接")
    {
        // 清除串口ID
        ui->CBox_Dev_Name->clear();
        // 通过QSerialPortInfo查找可用串口
        foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
        {
            // 在portBox中显示可用串口
            ui->CBox_Dev_Name->addItem(info.portName());
        }
    }
}

// 设备初始化
void MainWindow::Dev_init()
{
    //构造函数中
    local_serial = new Usart();
    Updata_time = new QTimer();
    local_serial->Dev_Run = 1;

    connect(Updata_time, SIGNAL(timeout()), this, SLOT(time_run()));        // 中断槽函数
    connect(ui->Btn_Dev_Refresh, &QPushButton::clicked, this, &MainWindow::Usart_Refresh);          // 刷新串口按键
    connect(ui->Btn_Dev_Connect, &QPushButton::clicked, this, &MainWindow::Btn_Usart_conmect);      // 连接串口按键

    connect(this, SIGNAL(Dev_State(QString, bool)), local_serial, SLOT(Com_State(QString, bool)), Qt::QueuedConnection);        // 连接串口信号
    connect(local_serial, SIGNAL(Dev_State_data(bool)), this, SLOT(Dev_Btn_conmect(bool)), Qt::QueuedConnection);               // 连接串口反馈
    connect(this, SIGNAL(Dev_Sand_Data(QByteArray)), local_serial, SLOT(write_data(QByteArray)), Qt::QueuedConnection);         // 设备发送数据
    connect(local_serial, SIGNAL(receive_data(QByteArray)), this, SLOT(Data_deal(QByteArray)), Qt::QueuedConnection);           // 接收数据

    connect(ui->Sand_Data, &QPushButton::clicked, this, &MainWindow::Btn_Sand_Data);                // 编程数据
    connect(ui->Open_File, &QPushButton::clicked, this, &MainWindow::Btn_Open_File);                // 打开文件
}

// 连接串口
void MainWindow::Btn_Usart_conmect()
{
    // 获取文本端口
    QString str = ui->CBox_Dev_Name->currentText();
    local_serial->Dev_BaudRate = ui->CBox_BaudRate->currentIndex();
    local_serial->Dev_DataBits = ui->CBox_DataBits->currentIndex();
    local_serial->Dev_Parity = ui->CBox_Parity->currentIndex();
    local_serial->Dev_StopBits = ui->CBox_StopBits->currentIndex();
    

    // 连接串口
    if (ui->Btn_Dev_Connect->text() == "连接")
    {
        emit Dev_State(str, true);
    }
    // 端口串口
    else if (ui->Btn_Dev_Connect->text() == "断开")
    {
        emit Dev_State(str, false);
        ui->Btn_Dev_Connect->setText("连接");
    }
}

// 处理连接反馈状态
void MainWindow::Dev_Btn_conmect(bool cmd)
{
    if (cmd)
    {
        ui->Btn_Dev_Connect->setText("断开");
    }
    else
    {
        QMessageBox::information(this,tr("错误"),QStringLiteral("连接设备失败!"),QMessageBox::Ok);
    }
}

// CRC校验
uint16_t CRC16(const uint8_t * u8pArray, uint8_t u8Size) 
{
    uint16_t i, j;
    uint16_t CrcReg = 0xFFFF;
    uint16_t CurVal;

    for (i = 0; i < u8Size; i++) 
    {
        CurVal = u8pArray[i] << 8;

        for (j = 0; j < 8; j++) 
        { 
            if ((short)(CrcReg ^ CurVal) < 0)
            {
                CrcReg = (CrcReg << 1) ^ 0x1021;
            }
            else 
            {
                CrcReg <<= 1;
            }
            CurVal <<= 1;
        }
    }

    return CrcReg;
}

// CRC校验
uint16_t Dev_CRC16(QByteArray ba)
{
    uint8_t val;
    uint16_t i, j;
    uint16_t CurVal;
    uint16_t CrcReg = 0xFFFF;

    for (i = 0; i < ba.size(); i++)
    {
        val = (uint8_t)ba.at(i);
        CurVal = val << 8;

        for (j = 0; j < 8; j++)
        {
            if ((short)(CrcReg ^ CurVal) < 0)
            {
                CrcReg = (CrcReg << 1) ^ 0x1021;
            }
            else 
            {
                CrcReg <<= 1;
            }
            CurVal <<= 1;
        }
    }

    return CrcReg;
}


// 发送数据
void MainWindow::Sand_Data(unsigned char cmd)
{
    QByteArray ba;
    QString st;
    uint16_t ChkData;
    uint8_t val;

    if (cmd == 0x01)
    {
        uint8_t data[200] = {0};

        ba.append(1, (char)cmd);
        val = ~Data_Number;
        ba.append(1, (char)Data_Number);
        ba.append(1, (char)val);
        ba.append(Send_Data);
        memcpy(&data, Send_Data.data(), Send_Data.size());

        // 数据校验
        ChkData = CRC16(&data[0],128);

        val = (uint8_t)ChkData;
        ba.append(1, (char)val);

        val = (uint8_t)(ChkData>>8);
        ba.append(1, (char)val);

        emit Dev_Sand_Data(ba);

        if (flag_EOT == 0)
        {
            st = "Sand Packet";
            st += QString::number(Data_Number, 10);
        }
        // 发送校验
        else if (flag_EOT == 1)
        {
            st = "Sand Check";
        }
        ui->text_Data_W->append(st);
    }
    else
    {
        ba.append(1, (char)cmd);
        emit Dev_Sand_Data(ba);
        switch (cmd)
        {
            case    0x93:
                ui->text_Data_W->clear();
                st = "进入编程环境...";
                ui->text_Data_W->append(st);
            break;

            case    0x04:
                st = "EOT 结束命令";
                local_serial->Dev_Run = 1;
                ui->text_Data_W->append(st);
            break;

            default:
            break;
        }
    }
}

// 发送字符串
void MainWindow::Sand_Data_QString(QString st)
{
    QByteArray ba;
    ui->text_Data_W->append(st);
    st += "\r\n";
    ba = st.toLatin1();
    emit Dev_Sand_Data(ba);
}

// 启动
void MainWindow::Btn_Sand_Data()
{
    QString st;
    uint8_t val;

    if (ui->Btn_Dev_Connect->text() == "断开")
    {
        QString file_Name = ui->OpenFileName->text();

        if (file_Name.isEmpty())           // 如果未选择文件便确认,即返回
        {
            QMessageBox::information(this,tr("错误"),QStringLiteral("未导入文件!"),QMessageBox::Ok);
            return;
        }

        // 打开文件
        QFile file(file_Name);
        if(!file.open(QIODevice::ReadOnly))
        {
            QMessageBox::information(this,tr("错误"),QStringLiteral("文件打开错误!"),QMessageBox::Ok);
            return;
        }
        file_arry = file.readAll();                             // 读取文件
        file.close();

        // 文件求整
        val = file_arry.size()%128;
        if (val)
        {
            val = 128 - val;
            file_arry.append(val, (char)0);
        }

        file_ChkData = Dev_CRC16(file_arry);
        st = QString::number(file_ChkData, 16).toUpper();
        ui->text_ChkData->setText(st);

        // 清除计数 接收文本 保存数据
        NAck_Cnt = 0;
        Ack_Cnt = 0;
        ui->text_Data_W->clear();
        ui->text_Data_R->clear();
        Save_Data.clear();

        // 开始接收数据
        local_serial->Dev_Run = 0;

        // 开始发送进入编译环境
        Data_Number = 0;        // 重新发送计数
        flag_EOT = 0;           // 发送结束标记位重置
        Sand_Data(0x93);        // 发送
    }
    
}

// 打开文件
void MainWindow::Btn_Open_File()
{
    QString st;
    uint8_t val;

    QString docName = QFileDialog::getOpenFileName(this, tr("打开"), QString(),tr("二进制文件 (*.bin)"));
    ui->OpenFileName->setText(docName);

    if (docName.isEmpty())           // 如果未选择文件便确认,即返回
    {
        QMessageBox::information(this,tr("错误"),QStringLiteral("未导入文件!"),QMessageBox::Ok);
        return;
    }

    // 打开文件
    QFile file(docName);
    if(!file.open(QIODevice::ReadOnly))
    {
        QMessageBox::information(this,tr("错误"),QStringLiteral("文件打开错误!"),QMessageBox::Ok);
        return;
    }
    file_arry = file.readAll();                             // 读取文件
    file.close();

    // 文件求整
    val = file_arry.size()%128;
    if (val)
    {
        val = 128 - val;
        file_arry.append(val, (char)0);
    }

    file_ChkData = Dev_CRC16(file_arry);
    st = QString::number(file_ChkData, 16).toUpper();
    ui->text_ChkData->setText(st);
}

/*-----Receive data-----*/
void MainWindow::Data_deal(QByteArray ba)
{
    QString st;
    uint8_t val;

    // 载入保存数据
    Save_Data.append(ba);
    Send_Data.clear();

    if (Save_Data == "Apply OTA\r\n")
    {
        st = "Apply OTA";
        ui->text_Data_R->append(st);
        Sand_Data_QString("OTA");
        Save_Data.clear();
    }
    else if (Save_Data == "Ready\r\n")
    {
        st = "Ready";
        ui->text_Data_R->append(st);
        Sand_Data_QString("Start");
        NAck_Cnt = 0;
        Ack_Cnt = 0;
        Temp_file_Data = file_arry;
        Data_Number = 0;        // 重新发送计数
        flag_EOT = 0;           // 发送结束标记位重置
        Save_Data.clear();
    }
    // NACK
    else if (Save_Data.at(0) == (char)0x15)
    {
        NAck_Cnt++;
        ui->sBox_NAck->setValue(NAck_Cnt);
        if (Data_Number == 0)
        {
            Data_Number = 1;

            // 首次发送 
            st = "(NAck) Ready Receive";
            ui->text_Data_R->append(st);

            // 发送数据
            Send_Data = Temp_file_Data.left(128);
            Sand_Data(0x01);
        }
        else if (Data_Number)
        {
            st = "(NAck) Receive Packet";
            st += QString::number(Data_Number, 10);
            st += " Error";
            ui->text_Data_R->append(st);
            // 发送数据
            Send_Data = Temp_file_Data.left(128);
            Sand_Data(0x01);
        }
        Save_Data.clear();
    }
    // ACK
    else if (Save_Data.at(0) == (char)0x06)
    {
        Ack_Cnt++;
        ui->sBox_Ack->setValue(Ack_Cnt);

        Data_Number++;
        if (Temp_file_Data.size() > 128)
        {
            Temp_file_Data.remove(0, 128);

            // 发送数据
            Send_Data = Temp_file_Data.left(128);
            if (Temp_file_Data.size() == 128)
            {
                Temp_file_Data.remove(0, 128);
            }
            Sand_Data(0x01);
            st = "(Ack) Receive Packet";
            st += QString::number(Data_Number-1, 10);
            st += " Success";
        }
        else 
        {
            // 发送校验
            if (flag_EOT == 0)
            {
                flag_EOT = 1;
                val = (uint8_t)file_ChkData;
                Send_Data.append(1, (char)val);
                val = (uint8_t)(file_ChkData>>8);
                Send_Data.append(1, (char)val);
                Send_Data.append(128-2, (char)0);
                Sand_Data(0x01);
                st = "(Ack) Receive Packet";
                st += QString::number(Data_Number-1, 10);
                st += " Success";
            }
            // 发送EOT 完成
            else if (flag_EOT == 1)
            {
                flag_EOT = 2;
                Sand_Data(0x04);
                st = "(Ack) Receive Check";
                ui->text_Data_R->append(st);
                st = " ";
            }
        }
        ui->text_Data_R->append(st);
        Save_Data.clear();
    }
    
}

3.3.usart.cpp

#include "usart.h"
#include <QMessageBox>

Usart::Usart(QObject *parent) : QObject(parent)
{
    my_thread = new QThread();
    port = new QSerialPort();

    this->moveToThread(my_thread);
    Usart_init();
    my_thread->start();     // 启动线程
}

Usart::~Usart()
{
    port->close();
    port->deleteLater();
    my_thread->quit();
    my_thread->wait();
    my_thread->deleteLater();
}

// 串口初始化
void Usart::Usart_init()
{
    connect(port, SIGNAL(readyRead()), this, SLOT(handle_data()), Qt::QueuedConnection);                // 接收数据
}

// 连接设备状态
void Usart::Com_State(QString str, bool cmd)
{
    // 设置串口号
    port->setPortName(str);

    // 设置波特率
    switch (Dev_BaudRate)
    {
        case    0:
            port->setBaudRate(QSerialPort::Baud9600);
        break;

        case    1:
            port->setBaudRate(QSerialPort::Baud19200);
        break;

        case    2:
            port->setBaudRate(QSerialPort::Baud38400);
        break;

        case    3:
            port->setBaudRate(QSerialPort::Baud57600);
        break;

        case    4:
            port->setBaudRate(QSerialPort::Baud115200);
        break;

        default:
            port->setBaudRate(QSerialPort::Baud9600);
        break;
    }
    
    // 设置数据位
    switch (Dev_DataBits)
    {
        case    0:
            port->setDataBits(QSerialPort::Data5);
        break;

        case    1:
            port->setDataBits(QSerialPort::Data6);
        break;

        case    2:
            port->setDataBits(QSerialPort::Data7);
        break;

        case    3:
            port->setDataBits(QSerialPort::Data8);
        break;

        default:
            port->setDataBits(QSerialPort::Data8);
        break;
    }

    // 设置奇偶效验位
    switch (Dev_Parity)
    {
        case    0:
            port->setParity(QSerialPort::NoParity);
        break;

        case    1:
            port->setParity(QSerialPort::OddParity);
        break;

        case    2:
            port->setParity(QSerialPort::EvenParity);
        break;

        default:
            port->setParity(QSerialPort::NoParity);
        break;
    }

    // 设置停止位
    switch (Dev_StopBits)
    {
        case    0:
            port->setStopBits(QSerialPort::OneStop);
        break;

        case    1:
            port->setStopBits(QSerialPort::OneAndHalfStop);
        break;

        case    2:
            port->setStopBits(QSerialPort::TwoStop);
        break;

        default:
            port->setStopBits(QSerialPort::OneStop);
        break;
    }

    // 设置流模流
    port->setFlowControl(QSerialPort::NoFlowControl);

    if (cmd)
    {
        bool opt = port->open(QIODevice::ReadWrite);
        emit Dev_State_data(opt);
    }
    else
    {
        port->close();
    }
}

// 发送数据
void Usart::write_data(QByteArray ba)
{
    port->write(ba);
}

// 接收数据
void Usart::handle_data()
{
    QByteArray ba;

    if (port->bytesAvailable() >= 1)
    {
        ba = port->readAll();
        if (Dev_Run == 0)
        {
            emit receive_data(ba);
        }
    }
}

  

  

  

  

  

 

posted @ 2022-01-08 10:39  CrushGirl  阅读(151)  评论(0编辑  收藏  举报