Files
VX5_KRO_GearPump/oldProject/Serial/serial.cpp
T
2026-06-29 14:54:30 +08:00

1005 lines
29 KiB
C++

#include "serial.h"
#include <QDebug>
#include <iostream>
#include <string.h>
#include <QThread>
#include <QFile>
#include "DevOp.h"
#include <QElapsedTimer>
#include <QEventLoop>
#include <QCoreApplication>
#define MAX_LEN1 1024
#define MAX_LEN2 224
Serial::Serial(const QString comport)
{
com = comport;
queue.clear();
flagOfReadFinished = true;
timerRead = new QTimer(this);
connect(timerRead,SIGNAL(timeout()),this,SLOT(readTimeOut()));
STM32ReadCnt = 0;
STM32WriteCnt = 0;
FPGAReadCnt = 0;
FPGAWriteCnt = 0;
RecFlag=true;
isCommunication = true;
STM32CRCErrorCNt = 0;
FPGACRCErrorCNt = 0;
flagOfUpgradeSTM32 = 0;
}
Serial::~Serial(){
if (serial) serial->close();
}
int baudRateValue = 0;
void Serial::initSerialPort(const QString comport){
// 设置串口名称
if(com == "/dev/ttyAS5")
updateSet();
qDebug()<<"init comport: "<<comport;
if(comport == "/dev/ttyAS5" || comport == "/dev/ttyAS2"){
serial->setPortName(comport); // Windows 下的串口名称
baudRateValue = 115200;
switch(baudRateValue){
case 115200:waitTime = 10;break;
case 256000:waitTime = 3;break;
case 1500000:waitTime = 2;break;
}
serial->setBaudRate(baudRateValue);
if(comport == "/dev/ttyAS5")
serial->setBaudRate(1500000);
serial->setDataBits(QSerialPort::Data8);
serial->setParity(QSerialPort::NoParity);
if(comport == "/dev/ttyAS2") //硬件上VX5的第二版(FPGA芯片BGA封装),STM32使用UART1跟ARM通信,STM32的串口参数使用奇校验
serial->setParity(QSerialPort::EvenParity);
serial->setStopBits(QSerialPort::OneStop);
serial->setFlowControl(QSerialPort::NoFlowControl);
if (serial->open(QIODevice::ReadWrite)) {
if(comport == "/dev/ttyAS5")
qDebug() << "FPGA串口打开成功";
else
qDebug() << "STM32串口打开成功";
} else {
if(comport == "/dev/ttyAS5")
qDebug() << "FPGA串口打开失败:" << serial->errorString();
else
qDebug() << "STM32串口打开失败:" << serial->errorString();
}
this->FPGARecDataSavePtr=NULL;
this->FPGARecDataLen=0;
}
else{
qDebug() << "无效的串口号";
return;
}
}
void Serial::startInitSlot()
{
if(!serial)
{
serial = new QSerialPort(this);
initSerialPort(com);
connect(serial,&QSerialPort::readyRead,this,&Serial::readData);
qDebug()<<"startInitSlot thread id:"<< QString("0x%1").arg(reinterpret_cast<quintptr>(QThread::currentThreadId()), 0, 16);
}
}
void Serial::updateSet(){
int addr,size;
int len=0;
int num=0;
QFile file(":/conf/addrset.txt");
QString str = "";
if(file.open(QIODevice::ReadOnly)){
while(!file.atEnd()){
QByteArray line = file.readLine();
qDebug()<<QString(line);
QList<QString> lineList = QString(line).split(',');
addr = lineList.at(0).toInt(0,16);
len =MAX_LEN1;
if(lineList.size() > 1)
size = lineList.at(1).toInt();
num = size/len;
if(num == 0 || size == len){
set.insert(addr);
QString hexStr1 = QString::number(addr, 16).toUpper();
str = str + hexStr1 + ",";
}
else
for(int i=0;i<=num;i++){
set.insert(addr + i*len);
QString hexStr1 = QString::number(addr + i*len, 16).toUpper();
str = str + hexStr1 + ",";
}
len=MAX_LEN2;
if(lineList.size() > 1)
size = lineList.at(1).toInt();
num = size/len;
if(num == 0 || size == len){
set.insert(addr);
QString hexStr1 = QString::number(addr, 16).toUpper();
str = str + hexStr1 + ",";
}
else
for(int i=0;i<=num;i++){
set.insert(addr + i*len);
QString hexStr1 = QString::number(addr + i*len, 16).toUpper();
str = str + hexStr1 + ",";
}
}
}
if(file.isOpen())
file.close();
qDebug()<<"set size = "<<set.size();
qDebug()<<str;
}
void Serial::readData(){
if(!isCommunication) return;
if(!timerRead->isActive() && !flagOfUpgradeSTM32)
timerRead->start(50);
QByteArray recDat = serial->readAll();
if(com == "/dev/ttyAS5")
readFPGAData(recDat);
else if(com == "/dev/ttyAS2")
readSTM32Data(recDat);
}
unsigned char dataFPGA_FE[12] = {0};
unsigned char dataFPGA_00[78] = {0};
unsigned char dataFPGA_100[74] = {0};
unsigned char dataFPGA_180[26] = {0};
unsigned char dataFPGA_1B4[14] = {0};
unsigned char dataFPGA_1B8[12] = {0};
void Serial::readFPGAData(QByteArray data) {
recData.append(data);
if(recData.length() < curLen+10){
return;
}
if(timerRead->isActive())
timerRead->stop();
flagOfReadFinished = true;
QByteArray hexData = recData.mid(2, 3).toHex(' ').toUpper();
quint16 CRCRec = recData.at(recData.size()-3)<<8 + recData.at(recData.size()-2);
int addr=0;
addr |= static_cast<unsigned int>(recData[2]) << 16;
addr |= static_cast<unsigned int>(recData[3]) << 8;
addr |= static_cast<unsigned int>(recData[4]);
/***************出队列***************/
{
QMutexLocker locker(&Mutex);
if(recData[1]==0x01 || !set.contains(addr)){
if(queue.size() > 0)
queue.dequeue();
}
}
if(queue.size() > 0){
qDebug()<<"send FPGA queue data 0";
emit sendQueueData(0,0,NULL,0,0);
}
int headCode=recData[0];
if(headCode != 0xAA){
qDebug()<<"FPGA接收数据帧头错误:Frameheader"<<QString::number(headCode).toInt() << "addr:"<<hexData;
recData.clear(); // 帧头错误,清空缓冲区防止持续累积
return ;
}
if(!calCRC16CodeIn(recData)){
FPGACRCErrorCNt++;
QString hexString = QString(recData.mid(2, 3).toHex());
qDebug()<<"FPGA CRC校验码错误:CRC"<<CRCRec<<"addr:"<<hexString<<hexData;
recData.clear(); // CRC错误,清空缓冲区防止持续累积
// CRC错误时也需要出队,否则队列会积压
{
QMutexLocker locker(&Mutex);
if(queue.size() > 0)
queue.dequeue();
}
return;
}
if(recData[1] == 0x02 && set.contains(addr) && recData[7] != 0x00){
qDebug()<<"FPGA写错误";
recData.clear();
emit resendFPGAData(2,addr,NULL,1,0);
return;
}
if(set.contains(addr)){
if(queueFPGA.size() > 0)
queueFPGA.dequeue();
}
if(recData[1]==0x01){
switch(addr){
case 0x0000FE:
memcpy(dataFPGA_FE,recData.constData(),12);
handleFPGAVersion(dataFPGA_FE);//FPGA version
break;
case 0x000000:
memcpy(dataFPGA_00,recData.constData(),78);
emit getFPGAStatus(dataFPGA_00);
break;
case 0x100:
memcpy(dataFPGA_100,recData.constData(),74);
emit getFPGAPhaseDetectHighTm(dataFPGA_100);
break;
case 0x180:{
//dataofFPGACalandarAndDat=reinterpret_cast<unsigned char*>(recData.data());
memcpy(dataFPGA_180,recData.constData(),26);
emit getFPGACalandarAndDat(dataFPGA_180);
unsigned int testData=0;
testData = dataFPGA_180[18];
testData <<=8;
testData += dataFPGA_180[17];
testData <<=8;
testData += dataFPGA_180[16];
testData <<=8;
testData += dataFPGA_180[15];
break;
}
case 0x1B4:
memcpy(dataFPGA_1B4,recData.constData(),14);
emit getFPGACnt3CurrValue(dataFPGA_1B4);
break;
case 0x1B8:
memcpy(dataFPGA_1B8,recData.constData(),12);
emit getFPGAXXXDay(dataFPGA_1B8);
break;
}
}
recData.clear(); // 正常处理完毕,清空缓冲区
}
unsigned char dataSTM32_FF[30];
unsigned char dataSTM32_07[9];
unsigned char dataSTM32_FA[10];
unsigned char dataSTM32_A1[15];
void Serial::readSTM32Data(QByteArray data) {
if(flagOfUpgradeSTM32){
showData(data,12);
if(data.size()>0 && (unsigned char)data[0] == 0x79){
UpgradeACK = true;
qDebug()<<"UpgradeACK ="<<UpgradeACK;
}
serial->readAll();
return;
}
recData.append(data);
if(recData.length() < curLen+7){
return;
}
if(timerRead->isActive())
timerRead->stop();
flagOfReadFinished = true;
{
QMutexLocker locker(&Mutex);
if(queue.size() > 0){
queue.dequeue();
}
}
if(queue.size() > 0){
qDebug()<<"send STM32 queue data 0";
emit sendQueueData(0,0,NULL,0,0);
}
int addr = recData[2];
int headCode = recData[0];
if(headCode != 0xBB){
recData.clear();
qDebug()<<"STM32接收数据帧头错误."<<QString::number(headCode).toInt() << "addr:"<<QString::number(addr).toInt();
return ;
}
if(recData[1] != 0xF0 && recData[1] != 0x01 && recData[1] != 0x02){
qDebug()<<"STM32接收指令字节错误."<< "addr:"<<QString::number(addr).toInt();
recData.clear(); // 指令字节错误,清空缓冲区
return ;
}
if(!calCRC16CodeIn(recData)){
STM32CRCErrorCNt++;
qDebug()<<"STM32 CRC校验码错误."<<"addr:"<<QString::number(addr).toInt();
recData.clear(); // CRC错误,清空缓冲区防止持续累积
return;
}
int dataLen = recData[3]; // 假设 recData[3] 是数据长度字段
int tailIndex = dataLen + 6;
if (tailIndex >= recData.size()) {
qDebug() << "STM32 帧尾索引越界,数据不完整";
recData.clear(); // 数据不完整,清空缓冲区
return;
}
if(recData[recData[3]+6] != 0x55){
qDebug()<<"STM32接收数据帧尾错误."<<"addr:"<<QString::number(addr).toInt();
recData.clear(); // 帧尾错误,清空缓冲区
return;
}
if(recData[1]==0x01){
switch(addr){
case 0xFF:
memcpy(dataSTM32_FF,recData.constData(),30);
emit getSTM32Status(dataSTM32_FF);//FPGA version
break;
case 0x07:
memcpy(dataSTM32_07,recData.constData(),9);
emit getPulseCnt(dataSTM32_07);
break;
case 0xFA:
memcpy(dataSTM32_FA,recData.constData(),10);
emit getSTM32Version(dataSTM32_FA);
break;
case 0xA1:
memcpy(dataSTM32_A1,recData.constData(),15);
emit getSTM32Time(dataSTM32_A1);
break;
}
}
else if(recData[1]==0x02){
if(addr == 0xFE && recData[4] == 0x00)
emit powerOffReady();
}
recData.clear(); // 正常处理完毕,清空缓冲区
}
void Serial::sendSerialDataFromTimer(){
sendSerialData(0,0,NULL,0,0);
}
void Serial::readTimeOut(){
timerRead->stop();
serial->clear(QSerialPort::Input);
recData.clear(); // 超时时清空接收缓冲区,防止残留数据污染下次接收
if(com == "/dev/ttyAS5")
qDebug()<<"Read FPGA Serial data Timeout";
else if(com == "/dev/ttyAS2")
qDebug()<<"Read STM32 Serial data Timeout";
sendSerialData(0,0,NULL,0,0);
}
// 每个逻辑写操作以一条记录入队;sendDataToFPGA 内部负责分包,队列只记录逻辑单元
static constexpr int QUEUE_FPGA_MAX = 50; // queueFPGA 积压上限
static constexpr int QUEUE_STM32_MAX = 100; // queue 积压上限
void Serial::enQueue(int cmd, int addr, unsigned char *data, int len, int type, bool flag){
const send_Data sendData = {cmd, addr, data, len, type};
if(flag){
// 积压保护:FPGA 响应跟不上时丢弃旧条目,防止内存无限增长
if(queueFPGA.size() > QUEUE_FPGA_MAX){
qDebug()<<"queueFPGA 积压过多,清空旧数据,当前大小:"<<queueFPGA.size();
queueFPGA.clear();
}
queueFPGA.append(sendData);
}
else{
QMutexLocker locker(&Mutex);
if(queue.size() > QUEUE_STM32_MAX){
qDebug()<<"queue 积压过多,清空旧数据,当前大小:"<<queue.size();
queue.clear();
}
queue.append(sendData);
}
}
void Serial::getDataFromQueue(int &cmd, int &addr, unsigned char *& data, int &len, int &type, bool flag){
if(flag){
for(int i=0;i<queueFPGA.size();i++){
if(queueFPGA.at(i).addr == addr){
cmd = queueFPGA.at(0).cmd;
addr = queueFPGA.at(0).addr;
data = queueFPGA.at(0).data;
len = queueFPGA.at(0).len;
type = queueFPGA.at(0).type;
qDebug()<<"队列num: "<<i;
return;
}
}
qDebug()<<"队列中没有这个地址的数据:"<<addr;
}
else{
if(queue.isEmpty()){
qDebug()<<"queue is empty!!";
return;
}
cmd = queue.at(0).cmd;
addr = queue.at(0).addr;
data = queue.at(0).data;
len = queue.at(0).len;
type = queue.at(0).type;
}
}
void Serial::sendSerialData(int cmd,int addr, unsigned char* data, int len,int type){
if(!isCommunication) return;
if(flagOfUpgradeSTM32) return;
bool flag=false; //地址标志位
if(type == 1 && set.contains(addr)){
flag = true;
enQueue(cmd,addr,data,len,type,1);
}
else if(type != 0){
enQueue(cmd,addr,data,len,type,0);
}
if(type == 1){
emit queueSizeFPGA(queue.size());
emit queueFPGASizeSIG(queueFPGA.size());
}
else
emit queueSizeSTM32(queue.size());
if(type == 0){
qDebug()<<"resend FPGA data";
getDataFromQueue(cmd,addr,data,len,type,flag);
if(type == 1){
qDebug()<<"send FPGA queue data";
sendDataToFPGA(cmd,addr,data,len);
}
if(type == 2){
qDebug()<<"send STM32 queue data";
sendDataToSTM32(cmd,addr,data,len);
}
}
else if(type == 1){
if(flag || queue.size() == 1){
sendDataToFPGA(cmd,addr,data,len);
}
else{
getDataFromQueue(cmd,addr,data,len,type,flag);
sendDataToFPGA(cmd,addr,data,len);
}
}
else if(type ==2){
if(queue.size() == 1){
sendDataToSTM32(cmd,addr,data,len);
}
else{
getDataFromQueue(cmd,addr,data,len,type,0);
sendDataToSTM32(cmd,addr,data,len);
}
}
}
void Serial::sendDataToSTM32(int cmd,int addr, unsigned char* data, int len)
{
if (!data && len > 0) {
qDebug() << "data 指针为空但 len>0";
return;
}
QByteArray sendData(30,0x00);
qint64 bytesWritten=0;
quint16 CRCCode=0;
sendData[0]=0xBB;
if(cmd == 1)
curLen = len;
else
curLen = 1;
if(cmd == 1){
sendData[0] = 0xBB;
sendData[1] = 0x01;
sendData[2] = addr;
sendData[3] = len;
CRCCode=calCRC16CodeOut(sendData,4);
sendData[4]=CRCCode>>8;
sendData[5]=CRCCode;
sendData[6]=0x55;
sendData.resize(7);
serial->clear(QSerialPort::Input);
bytesWritten=serial->write(sendData,7);
serial->flush();
serial->waitForBytesWritten(waitTime);
if (bytesWritten == -1) {
qDebug() << "STM32写入数据失败。read";
} else {
// qDebug() << "STM32成功发送 " << bytesWritten << " 个字节的数据。read";
flagOfReadFinished = false;
recData.clear();
STM32WriteCnt++;
}
}
else if(cmd==2){
sendData[0] = 0xBB;
sendData[1] = 0x02;
sendData[2] = addr;
sendData[3] = len;
for(int i=0;i<len;i++){
sendData[4+i]=data[i];
}
CRCCode=calCRC16CodeOut(sendData,4+len);
sendData[4+len]=CRCCode>>8;
sendData[4+len+1]=CRCCode;
sendData[4+len+2]=0x55;
sendData.resize(len+7);
serial->clear(QSerialPort::Input);
bytesWritten=serial->write(sendData,len+7);
serial->flush();
serial->waitForBytesWritten(waitTime);
if (bytesWritten == -1) {
qDebug() << "STM32写入数据失败。";
} else {
flagOfReadFinished = false;
recData.clear();
STM32WriteCnt++;
}
}
}
void Serial::sendDataToFPGA(int cmd,int addr, unsigned char* data, int len){
if(!data) return;
QByteArray sendData(MAX_LEN1+10,0x00);
qint64 bytesWritten=0;
quint16 CRCCode=0;
int num = 0;
if(cmd == 1)
curLen = len;
else
curLen = 1;
if(cmd == 1){
sendData[0]= 0xAA;
sendData[1]= 0x01;
sendData[2] = addr>>16;
sendData[3] = addr>>8&0xFF;
sendData[4] = addr&0xFF;
sendData[5] = 0x00;
sendData[6] = len;
CRCCode=calCRC16CodeOut(sendData,7);
sendData[7]=CRCCode>>8;
sendData[8]=CRCCode;
sendData[9]=0x55;
sendData.resize(10);
serial->clear(QSerialPort::Input);
bytesWritten=serial->write(sendData,len+10);
serial->flush();
serial->waitForBytesWritten(2);
if (bytesWritten == -1) {
qDebug() << "fpga写入数据失败。read";
} else {
flagOfReadFinished = false;
recData.clear();
FPGAWriteCnt++;
}
}
else{
int max = 0;
if(cmd == 0xD2)
max = MAX_LEN1;
else
max = MAX_LEN2;
if(len > max){
num = len/max;
for(int i = 0;i < num; i++){
sendData.fill(0x00);
sendData[0] = 0xAA;
sendData[1] = cmd;
sendData[2] = addr>>16;
sendData[3] = addr>>8&0xFF;
sendData[4] = addr&0xFF;
sendData[5] = max>>8;
sendData[6] = max;
for(int j=0;j<max;j++){
sendData[7+j] = data[i*max + j];
}
CRCCode=calCRC16CodeOut(sendData,max+7);
sendData[max+7]=CRCCode>>8;
sendData[max+7+1]=CRCCode;
sendData[max+7+2]=0x55;
serial->clear(QSerialPort::Input);
bytesWritten=serial->write(sendData,max+10);
serial->flush();
if(cmd == 0xD2)
serial->waitForBytesWritten(12);
else
serial->waitForBytesWritten(2);
if (bytesWritten == -1) {
// qDebug() << "fpga写入数据失败。";
} else {
flagOfReadFinished = false;
recData.clear();
FPGAWriteCnt++;
// qDebug() << "fpga成功发送 " << bytesWritten << " 个字节的数据。";
}
addr += max;
}
len = len%max;
if(len == 0) return;
}
bytesWritten=0;
CRCCode = 0;
sendData.fill(0x00);
sendData[0]=0xAA;
sendData[1] = cmd;
for(int i=0;i<len;i++){
sendData[7+i]=data[num*max + i];
}
sendData[2] = addr>>16;
sendData[3] = addr>>8&0xFF;
sendData[4] = addr&0xFF;
sendData[5] = len>>8;
sendData[6] = len;
CRCCode=calCRC16CodeOut(sendData,7+len);
sendData[7+len]=CRCCode>>8;
sendData[7+len+1]=CRCCode;
sendData[7+len+2]=0x55;
sendData.resize(len+10);
serial->clear(QSerialPort::Input);
bytesWritten=serial->write(sendData,len+10);
if(addr == 0xB170)
qDebug() << "Counter2 sectional group: " << sendData.toHex(' ');
serial->flush();
if(cmd == 0xD2)
serial->waitForBytesWritten(12);
else
serial->waitForBytesWritten(2);
if (bytesWritten == -1) {
// qDebug() << "fpga写入数据失败。";
} else {
flagOfReadFinished = false;
recData.clear();
FPGAWriteCnt++;
// qDebug() << "fpga成功发送 " << bytesWritten << " 个字节的数据。";
}
}
}
quint16 Serial::calCRC16CodeOut(QByteArray data, int length)
{
if(length > data.size()) return;
quint16 crc = 0xFFFF;
for (int i = 1; i < length; ++i) {
crc ^= (quint16)data[i] << 8;
for (int j = 0; j < 8; ++j) {
if (crc & 0x8000) {
crc = (crc << 1) ^ 0x1021;
} else {
crc <<= 1;
}
}
}
return crc;
}
bool Serial::calCRC16CodeIn(QByteArray data){
if(!data.size()) return;
quint16 crc = 0xFFFF;
quint16 CRC = 0;
int length;
length = data.size() - 3;
if(length > 0){
for (int i = 1; i < length; ++i) {
crc ^= (quint16)data[i] << 8;
for (int j = 0; j < 8; ++j) {
if (crc & 0x8000) {
crc = (crc << 1) ^ 0x1021;
} else {
crc <<= 1;
}
}
}
}
else{
qDebug()<<"串口接收数据长度有误";
return false;
}
CRC = data[data.size() - 3];
CRC = CRC<<8;
CRC = CRC + data[data.size() - 2];
if(CRC != crc){
qDebug()<<"crc Error";
showData(data,1);
}
return(CRC == crc);
}
void Serial::showData( QByteArray dat,int type)
{
int i,len;
QString s="";
len = dat.length();
for(i=0;i<len;i++)
{
s+=QString().sprintf("%02X ",(unsigned char)dat.at(i));
}
if(type == 1)
qDebug()<<"CRC error: "<<s;
}
bool Serial::getSerialStatus(int type){
if(type == 1)
return serial->isOpen();
else
return 0;
}
void Serial::getReceivedFromFPGAData(QByteArray fromFPGADataArr)
{
unsigned char* target =NULL;
unsigned char* source=NULL;
int length = 0;
if(fromFPGADataArr[4]==0xfe){
length = 2;
}
else{
target = this->FPGARecDataSavePtr;
}
target = this->FPGARecDataSavePtr;
if(fromFPGADataArr.isEmpty()) qDebug()<<"recDataFromFPGA error";
else source = reinterpret_cast<unsigned char *>(fromFPGADataArr.data());
length = this->FPGARecDataLen;
source=source+7;
for(int i=0;i<length;i++){
target[i]=source[i];
}
if(fromFPGADataArr[4]==0xfe){
if(target[1]!=0x60){
target[0]=0;
target[1]=0;
}
}
}
unsigned int versionNum = 0;
void Serial::handleFPGAVersion(unsigned char *data){
versionNum = data[8];
versionNum <<=8;
versionNum += data[7];
emit getFPGAVersion(versionNum);
}
void Serial::handleSTM32Status(unsigned char *datPtr){
// emit getSTM32Status(datPtr);
}
void Serial::handleGearPumpVal(unsigned char *dataPtr){
// emit getGearPumpVal(dataPtr);
}
void Serial::handlePulseCnt(unsigned char *dataPtr){
// emit getPulseCnt(dataPtr);
}
void Serial::close(){
isCommunication = false;//关闭发送
while (!queueFPGA.isEmpty()) {
queueFPGA.dequeue();
}
while (!queue.isEmpty()) {
queue.dequeue();
}
serial->close();
}
void Serial::upgradeSTM32File(QString fileName){
flagOfUpgradeSTM32 = 1;
system("echo 231 > /sys/class/gpio/export");
system("echo 232 > /sys/class/gpio/export");
system("echo out > /sys/class/gpio/gpio231/direction");
system("echo out > /sys/class/gpio/gpio232/direction");
system("echo 1 > /sys/class/gpio/gpio231/value");
system("echo 1 > /sys/class/gpio/gpio232/value");
QThread::msleep(100);
system("echo 0 > /sys/class/gpio/gpio232/value");
emit progress(0,1);
UpgradeSTM32(fileName);
}
void Serial::UpgradeSTM32(QString fileName){
QString f = "/udisk/" + fileName;
QFile file(f);
if (!file.open(QIODevice::ReadOnly)) return;
QByteArray bin = file.readAll();
file.close();
if (!sync()) { emit progress(0,2); qDebug()<<"[ERR] sync failed"; return; }
QThread::msleep(500);
if(!getCMD()) { emit progress(0,2); qDebug()<<"[ERR] get cmd failed"; return; }
QThread::msleep(500);
if (!eraseChip()) { emit progress(0,2); qDebug()<<"[ERR] Erase failed"; return; }
QThread::msleep(500);
if (!writeBin(bin,0x08000000)) { emit progress(0,2); qDebug()<<"[ERR] Write failed"; return; }
QThread::msleep(500);
if (!go()) { emit progress(0,2); qDebug()<<"[ERR] Go fail"; return; }
emit progress(100,0);
qDebug()<<"[INFO] Upgrade success!";
system("echo 0 > /sys/class/gpio/gpio231/value");
system("echo 1 > /sys/class/gpio/gpio232/value");
QThread::msleep(100);
system("echo 0 > /sys/class/gpio/gpio232/value");
}
bool Serial::waitForAck(int timeoutMs) {
QElapsedTimer timer;
timer.start();
while (timer.elapsed() < timeoutMs) {
if (UpgradeACK) {
UpgradeACK = false;
qDebug() << "ACK succeed";
return true;
}
// 处理事件,让 readyRead 有机会被触发
QCoreApplication::processEvents(QEventLoop::AllEvents, 50);
QThread::msleep(10);
}
qDebug() << "ACK timeout after" << timeoutMs << "ms";
return false;
}
bool Serial::sync(){
// 1. 发送同步字节 0x7F
QByteArray syncByte;
syncByte.append(0x7F);
sendDataToUART2(syncByte, 1);
return waitForAck(500);
}
bool Serial::getCMD(){
return sendCmd(0x00);
}
bool Serial::sendCmd(uint8_t cmd) {
serial->clear(QSerialPort::AllDirections);
recData.clear(); // 清空类的接收缓冲区
UpgradeACK = false;
// 1. 发送命令和补码
QByteArray sendData;
sendData.append((char)cmd);
sendData.append((char)~cmd);
qDebug() << "Sending command:" << QString::number(cmd, 16).toUpper()
<< "Complement:" << QString::number(~cmd & 0xFF, 16).toUpper();
sendDataToUART2(sendData, 2);
// 2. 等待 ACK
return waitForAck(500);
}
bool Serial::eraseChip() {
if (!sendCmd(0x43)) {
qDebug() << "Erase command failed";
return false;
}
QThread::msleep(500);
return sendCmd(0xFF);
}
bool Serial::writeBin(QByteArray bin, uint32_t addr){
QByteArray chunk;
for (int i = 0; i < bin.size(); i += 256) {
// 1. 发送写命令 0x31
if (!sendCmd(0x31)) {
qDebug() << "Write command failed at offset";
return false;
}
chunk = bin.mid(i, 256);
// 2. 发送地址和长度
char header[5];
header[0] = (addr + i) >> 24; // 地址高位
header[1] = (addr + i) >> 16;
header[2] = (addr + i) >> 8;
header[3] = (addr + i);
header[4] = checkSumForUpgrade(header,4);
qDebug() << "Writing to address:" << QString::number(addr + i, 16)
<< "length:" << chunk.size();
serial->write(header, 5);
if (!waitForAck(500)) {
qDebug() << "Address ACK failed";
return false;
}
QThread::msleep(50);
// 4. 发送数据 + 校验和
QByteArray dataWithChecksum = chunk;
dataWithChecksum.prepend((char)(dataWithChecksum.size()-1));
const unsigned char* constDataPtr = reinterpret_cast<const unsigned char*>(dataWithChecksum.constData());
dataWithChecksum.append(checkSumForUpgrade(constDataPtr,dataWithChecksum.size()+1));
serial->write(dataWithChecksum);
if (!waitForAck(500)) {
qDebug() << "Data write failed";
return false;
}
QThread::msleep(50);
emit progress(100 * i / bin.size(), 1);
}
emit progress(100,1);
return true;
}
unsigned char Serial::checkSumForUpgrade(unsigned char *data,int len){
int i;
unsigned char cs;
cs = 0;
for ( i=0; i<len; i++ )
cs ^= data[i];
return cs;
}
bool Serial::go(uint32_t addr){
if (!sendCmd(0x21)) return false;
char a[5] = {(char)(addr >> 24), (char)(addr >> 16),
(char)(addr >> 8), (char)(addr), 0x00};
uint8_t sum = 0;
for (int i = 0; i < 4; ++i) sum ^= a[i];
a[4] = sum;
serial->write(a, 5);
return waitForAck(200);
}
bool Serial::sendDataToUART2(QByteArray data,int len){
qint64 bytesWritten=0;
serial->clear(QSerialPort::Input);
bytesWritten=serial->write(data,len);
serial->flush();
serial->waitForBytesWritten(waitTime);
if (bytesWritten == -1) {
qDebug() << "STM32写入数据失败";
} else {
qDebug() << "STM32成功发送 " << bytesWritten << " 个字节的数据";
showData(data,13);
}
QThread::msleep(100);
}