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); } } }