updateapp.h
#ifndef UPDATEAPP_H#define UPDATEAPP_H#include <QWidget>#include <QDialog>#include <QFile>#include <QTimer>#include <QList>namespace Ui {class UpdateApp;}class UpdateApp : public QDialog{ Q_OBJECTpublic: explicit UpdateApp(QWidget *parent = 0); ~UpdateApp(); qint16 Xmodem = 128; QString tempData = NULL; // 临时存储 QFile file; // 文件对象 QString fileName; // 文件名字 qint64 fileSize; // 文件大小 qint64 sendSize; // 已发送文件大小 qint32 sendCount; // 要发送几次 qint32 num = 0; // 累计发送的次数 qint64 len = 0; // 每次发送的长度 //QTimer timer4; // 更新程序定时器 //void sendUpdateAppData(); // 发送数据函数 void sliceData(); // 接收返回的数据 void recevedData(char); // 定义变量枚举 enum ID_Enum { ID_C = 'C', ID_ACK = 1, ID_NAK = 2 };signals: void sendCloseSig(void); void sendUpdateData(QString);private slots: void on_selectFile_clicked(); void on_sendData_clicked(); void on_cancle_clicked();private: Ui::UpdateApp *ui; void closeEvent(QCloseEvent*event);};#endif // UPDATEAPP_H
updateapp.c
#include "updateapp.h"#include "ui_updateapp.h"#include <QFileDialog>#include <QDebug>UpdateApp::UpdateApp(QWidget *parent) : QDialog(parent), ui(new Ui::UpdateApp){ ui->setupUi(this); this->setWindowTitle("更新程序"); ui->sendData->setEnabled(false); // 禁用发送数据按钮}UpdateApp::~UpdateApp(){ delete ui;}void UpdateApp::on_selectFile_clicked(){ ui->progressBar->setValue(0); // 当前值 ui->sendData->setEnabled(false); ui->fileName->setText("..."); // 文件路径 QString filePath = QFileDialog::getOpenFileName(this, "open", "../"); // 如果选择文件路径有效 if(filePath.isEmpty() == false) { // 先清空前面的内容 fileName.clear(); fileSize = 0; // 获取文件信息 QFileInfo info(filePath); fileName = info.fileName(); // 文件名 fileSize = info.size(); // 文件大小 sendCount = fileSize/Xmodem + (fileSize%Xmodem ? 1 : 0); // 要发送几次 ui->fileName->setText(fileName); // 设置文件名 qDebug() << "文件大小" << fileSize; qDebug() << "总数" << sendCount; sendSize = 0; // 初始化发送文件的大小 // 只读方式打开, 指定文件的名字 file.setFileName(filePath); // 打开文件 bool isOk = file.open(QIODevice::ReadOnly); if(isOk == false) { qDebug() << "只读方式打开文件失败"; ui->sendData->setEnabled(false); }else { qDebug() << "文件打开成功"; ui->sendData->setEnabled(true); } }}void UpdateApp::on_sendData_clicked(){ // 先发送固件升级请求 emit sendUpdateData("11 00 4D 00 01"); // 设置进度条当前值为0 ui->progressBar->setValue(0); ui->sendData->setEnabled(false); // 确定按钮禁用 // 设置进度条 ui->progressBar->setMinimum(0); // 最小值 ui->progressBar->setMaximum(sendCount); ui->progressBar->setValue(0); // 当前值 //timer4.start(100); num = 0;}void UpdateApp::recevedData(char sig){ switch (sig) { case ID_C: sliceData(); // 文件发送 break; case ID_ACK: sliceData(); // 文件发送 break; case ID_NAK: emit sendUpdateData(tempData); // 重发文件 break; } // 是否发送文件完毕 if(sendSize == fileSize) { qDebug() << "文件发送完毕"; file.close(); // timer4.stop(); // 停止定时器 }}void UpdateApp::sliceData(){ // 每次发送数据的大小 char buf[Xmodem] = {0}; len = 0; // 往文件中读数据 len = file.read(buf, sizeof(buf)); if(len == 0) { //timer4.stop(); // 停止定时器 return; } // 发送数据, 读多少发多少 QString sendCounts = QString("%1").arg(sendCount, 4, 16, QLatin1Char('0')); QString numst = QString("%1").arg(num, 4, 16, QLatin1Char('0')); // 更新进度条 ui->progressBar->setValue(num +1); qDebug() << numst; QByteArray bit_arr; int size = sizeof(buf); int i = 0; do { bit_arr.append(buf[i]); // 将二进制文件添加到数组中 i++; }while(i<size); QString str_Data = QString("55 %1 %2 %3").arg(sendCounts) .arg(numst) .arg(QString(bit_arr.toHex())); // 将数组的数据转hex发送 num++; tempData = str_Data; emit sendUpdateData(str_Data); // 发送的数据累加 sendSize += len;}void UpdateApp::on_cancle_clicked(){ // qDebug() << "点击取消"; this->close();}void UpdateApp::closeEvent(QCloseEvent* event){ // 初始化文件 ui->fileName->setText("..."); fileName.clear(); file.close(); ui->sendData->setEnabled(false); ui->progressBar->setValue(0); // qDebug() << "点击关闭" << event; emit sendCloseSig(); // 发送取消信号}
主程序.h
#include "updateapp.h"public: // 更新程序窗口 UpdateApp *updateapp;signals: void receveData(char);
主程序.c
... // 读取串口返回的数据 QObject::connect(&mSerialPort, &QSerialPort::readyRead, this, &Dx1000_dialogSP::on_SerialPort_readyRead); // 当updateapp弹框关闭时,就重启定时器 connect(updateapp, &UpdateApp::sendCloseSig, this, [=](){ int time = ui->setTime->text().toInt(); timer->start(time); // 重启定时器 }); connect(updateapp, &UpdateApp::sendUpdateData, this, [=](QString str){ QString sendData = merge(str); isSendData = QString2Hex(sendData).toHex(); mSerialPort.write(QString2Hex(sendData)); qDebug() << "sendUpdateData"; qDebug() << isSendData; qDebug() << "read" << mSerialPort.readAll(); }); // 将接收到的指令返回到updateapp提示框中 connect(this, &Dx1000_dialogSP::receveData, updateapp, &UpdateApp::recevedData);// 接收数据槽函数void Dx1000_dialogSP::on_SerialPort_readyRead(){ // 判断返回的是否是要的数据 QByteArray recvData = mSerialPort.readAll(); qDebug() << "recvData" << recvData; qint8 reD = recvData[2]; qDebug() << "reD" << reD; if( 67 == reD) { emit receveData(updateapp->ID_C); // 数据接收成功 qDebug() << "接收C指令成功"; return; }else if( 6 == reD) { emit receveData(updateapp->ID_ACK); // 数据接收成功 qDebug() << "接收ACK指令成功"; return; }else if( 21 == reD) { emit receveData(updateapp->ID_NAK); // 数据接收成功 qDebug() << "接收NAK指令成功"; return; } ...}