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_OBJECT
public:
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;
}
...
}