#include "serial.h" #include #include #include #include #include #include "DevOp.h" #include #include #include #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: "<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串口打开成功"; emit STM32Connected(true, ""); } } else { if(comport == "/dev/ttyAS5"){ qDebug() << "FPGA串口打开失败:" << serial->errorString(); } else{ qDebug() << "STM32串口打开失败:" << serial->errorString(); emit STM32Connected(false, 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(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()< 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 = "<isActive() && !flagOfUpgradeSTM32) timerRead->start(50); QByteArray recData = serial->readAll(); if(com == "/dev/ttyAS5") readFPGAData(recData); else if(com == "/dev/ttyAS2") readSTM32Data(recData); } 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(recData[2]) << 16; addr |= static_cast(recData[3]) << 8; addr |= static_cast(recData[4]); /***************出队列***************/ { QMutexLocker locker(&Mutex); if(recData[1]==0x01 || !set.contains(addr)){ if(queue.size() > 0) queue.dequeue(); } } if(queue.size() > 1){ qDebug()<<"send FPGA queue data 0"; emit sendQueueData(0,0,NULL,0,0); } int headCode=recData[0]; if(headCode != 0xAA){ qDebug()<<"FPGA接收数据帧头错误:Frameheader"< 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(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; case READ_BUILD_DAT: { int fpgaBuildDat = 0; fpgaBuildDat = recData[7]; emit FPGABuildDat(fpgaBuildDat); break; } } } } 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 ="<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() > 2){ 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接收数据帧头错误."<= recData.size()) { qDebug() << "STM32 帧尾索引越界,数据不完整"; return; } if(recData[recData[3]+6] != 0x55){ qDebug()<<"STM32接收数据帧尾错误."<<"addr:"<stop(); serial->clear(QSerialPort::Input); 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); } void Serial::enQueue(int cmd, int addr, unsigned char *data, int len, int type, bool flag){ send_Data sendData; if(flag){ int max = 0; if(cmd == 0xD2) max = MAX_LEN1; else max = MAX_LEN2; int num = len/max; if(len <= max){ sendData.cmd = cmd; sendData.addr = addr; sendData.data = data; sendData.len = len; sendData.type = type; queueFPGA.append(sendData); } else{ for(int i=0;i 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>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>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>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); 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;iisOpen(); 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(fromFPGADataArr.data()); length = this->FPGARecDataLen; source=source+7; for(int i=0;iclose(); } 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(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> 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); }