This repository has been archived on 2026-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
SP713_CPP_QT/apps/icd/app_icd.cpp
2025-07-17 13:10:47 +08:00

316 lines
9.1 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}