1005 lines
29 KiB
C++
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);
|
|
}
|