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

浙公网安备 33010602011771号