316 lines
9.1 KiB
C++
316 lines
9.1 KiB
C++
#include "app_icd.h"
|
||
#include <QDebug> // 用于调试输出
|
||
#include "apps/crc16/crc.h"
|
||
#include <QDateTime>
|
||
#include <QFile>
|
||
|
||
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<quint8>(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<quint32>(data[row][col]) & 0x3FF;
|
||
|
||
// 将10位值添加到缓冲区
|
||
bitBuffer = (bitBuffer << 10) | value;
|
||
bitsInBuffer += 10;
|
||
|
||
// 每当缓冲区有至少8位时,提取一个字节
|
||
while (bitsInBuffer >= 8) {
|
||
bitsInBuffer -= 8;
|
||
quint8 byte = static_cast<quint8>((bitBuffer >> bitsInBuffer) & 0xFF);
|
||
this->ICD_volValuePara.append(byte);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 处理缓冲区中剩余的位(如果有)
|
||
if (bitsInBuffer > 0) {
|
||
quint8 lastByte = static_cast<quint8>((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<const uchar*>(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;
|
||
}
|