#include "app_icd.h" #include // 用于调试输出 #include "apps/crc16/crc.h" #include #include APP_Icd::APP_Icd(QObject *parent) : QObject(parent) { // 创建驱动实例 this->m_spiDriver = new DRV_Spi(this); this->m_uartDriver = new DRV_Uart(this); // 初始化协议帧相关参数的大小 this->ICD_ctrlPara.resize(11); this->ICD_volValuePara.resize(320); this->ICD_allData.resize(340); // 初始化协议帧相关参数的初值 this->ICD_allData.fill(0x00); this->ICD_ctrlPara.fill(0x00); this->ICD_volValuePara.fill(0x00); // 设置包头 this->ICD_allData[0] = 0x9F; this->ICD_allData[1] = 0xE4; } APP_Icd::~APP_Icd() { } bool APP_Icd::ICD_init() { if(!ICD_initSpi()) { qWarning() << "SPI initialization failed"; return false; } if(!ICD_initUart()) { qWarning() << "UART initialization failed"; return false; } return true; } bool APP_Icd::ICD_initSpi() { // 这里添加SPI初始化逻辑 return true; } bool APP_Icd::ICD_initUart() { // //枚举当前的uart设备号 // this->m_uartDriver->Uart_enumDevice(); return true; } /** * @brief 计算QByteArray的累加和校验 * @param data 输入数据 * @param endPos 截止位置(-1表示计算到末尾) * @return 累加和(溢出自动截断为8位) */ quint8 APP_Icd::ICD_calcChecksum(const QByteArray &data, int endPos) { quint8 sum = 0; if (data.isEmpty()) return sum; // 计算有效长度 int length = (endPos < 0 || endPos >= data.size()) ? data.size() : endPos + 1; // 累加计算 for (int i = 0; i < length; ++i) { sum += static_cast(data.at(i)); // 自动处理溢出 } return sum; } // 电压命令编码 bool APP_Icd::ICD_volCMDProtoEncode(uint8_t CMD, uint8_t group, uint8_t subGroup) { //判断值是否超出范围 if((CMD > 0x03) || (group > 0xAA) || (subGroup > 0xAA)) return false; // 设置控制字参数 this->ICD_ctrlPara[0] = group; this->ICD_ctrlPara[1] = subGroup; // 调用主协议编码函数 return this->ICD_sumProtoEncode(CMD, this->ICD_ctrlPara); } // 写寄存器命令编码 bool APP_Icd::ICD_regWCMDProtoEncode(uint8_t dacID, uint8_t dacCH, uint8_t funcEN, uint8_t adcCurrConfig) { //判断值是否超出范围 // if((funcEN > 0x0F)) // return false; // 填充默认值0 this->ICD_ctrlPara.fill(0x00); // 设置控制字参数 this->ICD_ctrlPara[0] = dacID; this->ICD_ctrlPara[1] = dacCH; this->ICD_ctrlPara[2] = funcEN; this->ICD_ctrlPara[3] = adcCurrConfig; // 调用主协议编码函数 return this->ICD_sumProtoEncode(SP_CMD_REG_WR, this->ICD_ctrlPara); } // 写寄存器命令编码 bool APP_Icd::ICD_regRCMDProtoEncode(uint8_t dacID) { //判断值是否超出范围 if((dacID > 0x14)) return false; // 填充默认值0 this->ICD_ctrlPara.fill(0x00); // 设置控制字参数 this->ICD_ctrlPara[0] = dacID; // 调用主协议编码函数 return this->ICD_sumProtoEncode(SP_CMD_REG_RD, this->ICD_ctrlPara); } bool APP_Icd::ICD_sumProtoEncode(uint8_t CMD, const QByteArray &ctrl_data) { // this->ICD_allData.resize(338); // 设置控制字指令 this->ICD_allData[2] = CMD; // 将控制字参数添加到主协议帧上 this->ICD_allData.replace(3, ctrl_data.size(), ctrl_data); // 设置帧计数 this->ICD_allData[14] = this->ICD_allData[14] + 1; // 设置校验和 this->ICD_allData[15] = this->ICD_calcChecksum(this->ICD_allData, 14); // 设置电压类型:同值为0x01,异值为0x02 if((CMD == SP_CMD_SAME_VALUE) || (CMD == SP_CMD_DIF_VALUE)){ this->ICD_allData[16] = CMD - 1; }else{ this->ICD_allData[16] = 0; } // 将256个10bit数据转化为320个字节的数据 this->ICD_pack10BitData(this->DAC256_10bit_data); // 将电压参数赋值到allData中 this->ICD_allData.replace(17, ICD_volValuePara.size(), ICD_volValuePara); // 计算320个字节的CRC16校验和 QByteArray crc16Result = crc16Reverse(this->ICD_volValuePara); // 将CRC16校验和添加到ICD_allData中 this->ICD_allData.replace(337, crc16Result.size(), crc16Result); // 设置校验和 this->ICD_allData[339] = this->ICD_calcChecksum(this->ICD_allData, 338); // 调用串口/SPI发送函数 if(this->m_uartDriver->m_DRV_Uart_Infors.devIsOpened){ // 串口发送数据 this->m_uartDriver->Uart_Write(this->ICD_allData); // 记录数据 this->ICD_addContextToDataRecordingFile(true, this->ICD_allData); } return true; } // 设置DAC256 10Bit参数 bool APP_Icd::ICD_setDAC256Data10bit(int row, int col, int value) { if((row > 15) || (col > 15) || (value > 1023)) return false; this->DAC256_10bit_data[row][col] = value; return true; } // 将256个10bit的数据转化为320个8bit数据 QByteArray APP_Icd::ICD_pack10BitData(int data[16][16]) { quint32 bitBuffer = 0; // 32位缓冲区 int bitsInBuffer = 0; // 缓冲区中当前位数 this->ICD_volValuePara.clear(); for (int row = 0; row < 16; ++row) { for (int col = 0; col < 16; ++col) { // 确保数据是10位 (0-1023) quint32 value = static_cast(data[row][col]) & 0x3FF; // 将10位值添加到缓冲区 bitBuffer = (bitBuffer << 10) | value; bitsInBuffer += 10; // 每当缓冲区有至少8位时,提取一个字节 while (bitsInBuffer >= 8) { bitsInBuffer -= 8; quint8 byte = static_cast((bitBuffer >> bitsInBuffer) & 0xFF); this->ICD_volValuePara.append(byte); } } } // 处理缓冲区中剩余的位(如果有) if (bitsInBuffer > 0) { quint8 lastByte = static_cast((bitBuffer << (8 - bitsInBuffer)) & 0xFF); this->ICD_volValuePara.append(lastByte); } // 确保输出正好是320字节(不足补零) while (this->ICD_volValuePara.size() < 320) { this->ICD_volValuePara.append('\0'); } return this->ICD_volValuePara; } // 创建数据记录文件 bool APP_Icd::ICD_newDataRecordingFile(void) { // 生成带时间戳的文件名 QString timestamp = QDateTime::currentDateTime().toString("yyyyMMdd_hhmmss"); QString fileName = QString("%1_%2.txt").arg("SP713_UART_SPI_Data_Recording").arg(timestamp); // 创建文件并检查是否成功 QFile file(fileName); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { return false; } // 关闭文件 file.close(); // 设置数据记录文件名 this->dataRecordingFile = fileName; return true; } // 添加记录至txt文件 bool APP_Icd::ICD_addContextToDataRecordingFile(bool isWrite, QByteArray &Data) { if (this->dataRecordingFile.isEmpty()) { return false; } // 打开文件(追加模式) QFile file(this->dataRecordingFile); if (!file.open(QIODevice::Append | QIODevice::Text)) { return false; } QTextStream out(&file); // 写入时间戳和特定字符串 QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"); if(isWrite){ out << timestamp << " tx data: "; // 时间戳和特定字符串 }else{ out << timestamp << " rx data: "; // 时间戳和特定字符串 } // 将QByteArray转换为16进制字符串,用空格分隔 QString hexData = Data.toHex(' ').toUpper(); out << hexData << "\n"; // 写入16进制数据并换行 file.close(); return true; } // 解析函数 ParsedData APP_Icd::ICD_parseRegisterData(const QByteArray &revData) { ParsedData result = {}; // 检查数据长度 (至少需要7个字节: REG7-REG1) if(revData.size() < 7) { qWarning() << "Invalid data length, expected at least 7 bytes"; return result; } // 从REG7到REG1解析 (数据顺序是REG7在前) const uchar *data = reinterpret_cast(revData.constData()); // REG2 (索引5,因为数据顺序是REG7(0),REG6(1),...,REG1(6)) result.EN_TADC = (data[5] >> 7) & 0x01; result.N_CLKDIV18 = ((data[5] >> 5) & 0x03); // 取B6和B5 result.VCON = ((data[5] >> 2) & 0x03); // 取B4和B3 result.CH_TEST = ((data[5] >> 1) & 0x01) << 8; // CH_TEST[8] result.FBK_EN = (data[5]) & 0x01; // REG3 (索引4) result.TEMPTEST_EN = (data[4] >> 7) & 0x01; result.TRIG_TADC = (data[4] >> 6) & 0x01; result.TEST_TADC = (data[4] >> 5) & 0x01; result.ICON18 = (data[4]) & 0x0F; // 取B4-B1 // REG4 (索引3) result.CH_TEST |= data[3]; // CH_TEST[7:0] // REG5 (索引2) result.ADC_OUT = data[2]; // ADC_OUT[7:0] // REG6 (索引1) result.EOC = (data[1] >> 7) & 0x01; result.ADC_OUT |= ((data[1] & 0x03) << 8); // ADC_OUT[9:8] result.D_FB = ((data[1] >> 2) & 0x03); // D_FB[9:8] // REG7 (索引0) result.D_FB = (result.D_FB << 8) | data[0]; // D_FB[7:0] return result; }