// 保存SWV数据到CSV文件(修复版本)
void save_SWV_data_to_csv(lv_SWV_Param* params, int** current_data_all, uint16_t* data_counts,
data_result* peak_data, uint8_t total_scans) {
FRESULT res;
FIL file;
UINT bytes_written;
char filename[50];
char date_str[10], time_str[10];
uint32_t number;
char buffer[100];
// 获取当前日期和时间
get_current_datetime(date_str, time_str);
// 获取下一个文件编号
number = get_next_file_number();
// 生成文件名
sprintf(filename, "%s_%s%s_%08lu.csv", s_Globle.ps_Parpam->sensor_type, date_str, time_str, number);
// 创建并打开文件
res = f_open(&file, filename, FA_CREATE_ALWAYS | FA_WRITE);
if (res != FR_OK) {
printf("Failed to create file: %d\n", res);
return;
}
// 写入参数头信息
f_printf(&file, "Scan Type,SWV\n");
f_printf(&file, "InitEval,%d\n", params->InitEval);
f_printf(&file, "FinalEval,%d\n", params->FinalEval);
f_printf(&file, "IncrEval,%d\n", params->IncrEval);
f_printf(&file, "AmplitudeE,%d\n", params->AmplitudeE);
f_printf(&file, "QuiteTime,%d\n", params->QuiteTime);
f_printf(&file, "Frequency,%d\n", params->Frequency);
f_printf(&file, "Range,%d\n", params->Range);
f_printf(&file, "Number of Scans,%d\n", params->Number);
f_printf(&file, "Analyse Potential,%d\n", params->analyse_potential);
f_printf(&file, "Light Type,%d\n", params->light_type);
f_printf(&file, "Light Power (mW),%d\n", params->light_mW);
f_printf(&file, "Min Range,%d\n", params->minrange);
f_printf(&file, "Max Range,%d\n", params->maxrange);
f_printf(&file, "Date,=\"%s\"\n", date_str);
f_printf(&file, "Time,=\"%s\"\n", time_str);
f_printf(&file, "File Number,%08lu\n", number);
f_printf(&file, "\n"); // 空行分隔参数和数据
// 写入峰值数据
f_printf(&file, "Peak Data\n");
f_printf(&file, "Scan,Voltage(mV),Current(uA)\n");
for (int i = 0; i < total_scans; i++) {
f_printf(&file, "%d,%d,%d\n", i+1,
peak_data[i].voltage, peak_data[i].current);
}
// 计算平均峰值
int avg_voltage = 0;
int avg_current = 0;
for (int i = 0; i < total_scans; i++) {
avg_voltage += peak_data[i].voltage;
avg_current += peak_data[i].current;
}
if (total_scans > 0) {
avg_voltage /= total_scans;
avg_current /= total_scans;
}
f_printf(&file, "Average,%d,%d\n", avg_voltage, avg_current);
f_printf(&file, "\n"); // 空行分隔峰值数据和扫描数据
// 生成电压序列
int init = params->InitEval;
int final = params->FinalEval;
int incr = params->IncrEval;
int dir = (init < final) ? 1 : -1;
// 计算预期的数据点数
int expected_points = abs(final - init) / incr + 1;
// 写入扫描数据表头
f_printf(&file, "Voltage(mV)");
for (int i = 0; i < total_scans; i++) {
f_printf(&file, ",Scan%d(uA)", i+1);
}
f_printf(&file, "\n");
// 找出所有扫描中的最大数据点数
int max_data_points = 0;
for (int i = 0; i < total_scans; i++) {
if (data_counts[i] > max_data_points) {
max_data_points = data_counts[i];
}
}
// 确保不超过预期点数
if (max_data_points > expected_points) {
max_data_points = expected_points;
}
// 写入扫描数据(按电压对齐)
for (int i = 0; i < max_data_points; i++) {
int voltage = init + incr * i * dir;
f_printf(&file, "%d", voltage);
for (int scan_idx = 0; scan_idx < total_scans; scan_idx++) {
// 确保不越界访问
if (i < data_counts[scan_idx]) {
f_printf(&file, ",%d", current_data_all[scan_idx][i]);
} else {
f_printf(&file, ","); // 数据不足时留空
}
}
f_printf(&file, "\n");
}
// 关闭文件
f_close(&file);
printf("Data saved to %s\n", filename);
}
uint8_t CMD;
uint8_t status;
uint8_t Sensor;
uint16_t Year;
uint8_t Month;
uint8_t Day;
uint8_t Hour;
uint8_t Minute;
uint8_t Second;
uint8_t battery;
char* timeStr;
uint8_t CurrentMode;
float Res_val;
uint16_t data_index;
uint16_t swv_data_index;
float* ITData=NULL;
float* CVData=NULL;
float* SWVData=NULL;
float* diffData=NULL;
int* current_data=NULL;
int* voltage_data=NULL;
uint16_t last_cont = 0;
bool Dire = true; // 用于判断当前扫描方向
uint32_t DataCount = 0; // 总数据点计数(需初始化)
uint32_t ScandataCount = 0; // 已完成扫描数据计数(需初始化)
#define MAX_TOTAL_DATA_POINTS 200 // 所有扫描的总数据点最大数量
#define MAX_SCANS 3 // 最大扫描次数
data_result anodic_peak, cathodic_peak;
// 保存所有电压和电流值
int voltage_data_all[MAX_TOTAL_DATA_POINTS];
int current_data_all[MAX_TOTAL_DATA_POINTS];
uint32_t total_data_count = 0; // 总数据点数
data_result anodic_peak_data[MAX_SCANS],cathodic_peak_data[MAX_SCANS]; // 每个扫描的峰值数据
// 在合适的位置定义二维数组
int *current_data_scans[MAX_SCANS]; // 存储每次扫描的电流数据
int voltage_sequence[200]; // 存储电压序列(所有扫描相同)
// 在开始扫描前初始化最大最小值(仅第一次扫描)
static bool first_scan = true;
// 增加扫描计数
static uint8_t cv_scan_count = 1;
// 在CV模式中添加静态数组来存储所有扫描的数据
static int* voltage_data_scans[MAX_SCANS] = {NULL};
static int* current_data_scans[MAX_SCANS] = {NULL};
// 增加扫描计数
static uint8_t scan_count = 1;
// 在合适的地方定义数据点数数组
uint16_t data_counts[MAX_SCANS];
//命令处理函数
static uint8_t ExecuteCMD(s_Globle_Para *ps_Globle) {
ps_Globle->u8_CMD = UART_ACK_FAULT_ALL;
ps_Globle->u8_CMD_Data_LEN = UART_DATA_0_BYTE;
switch (ps_Globle->u8_ACK) {
case UART_ACK_Uart_DeviceOK://通信方式设置完成
if (ps_Globle->u8_ACK_Data_LEN == UART_DATA_20_BYTE) {
printf("UARTOK\r\n");
HEARTBEAT_flag=1;
}
break;
case UART_ACK_HEARTBEAT_OK:
printf("UART_ACK_HEARTBEAT_OK\r\n");
// 假设mPackAfterUnpack是接收缓冲区,UART_BUF_DATA_SHIFT是数据起始偏移
// 解包基础信息
CMD = ps_Globle->u8_ACK_Data[0]; // 下位机当前命令(对应u8_ACK_Data[0])
status = ps_Globle->u8_ACK_Data[1]; // 下位机当前状态(对应u8_ACK_Data[1])
Sensor = ps_Globle->u8_ACK_Data[2]; // 传感器状态(对应u8_ACK_Data[2])
// 解包时间信息(年、月、日、时、分、秒)
Year = (ps_Globle->u8_ACK_Data[3] << 8) | ps_Globle->u8_ACK_Data[4]; // 年(对应u8_ACK_Data[3-4])
Month = ps_Globle->u8_ACK_Data[5]; // 月(对应u8_ACK_Data[5])
Day = ps_Globle->u8_ACK_Data[6]; // 日(对应u8_ACK_Data[6])
Hour = ps_Globle->u8_ACK_Data[7]; // 时(对应u8_ACK_Data[7])
Minute = ps_Globle->u8_ACK_Data[8]; // 分(对应u8_ACK_Data[8])
Second = ps_Globle->u8_ACK_Data[9]; // 秒(对应u8_ACK_Data[9])
// 解包设备状态
battery = ps_Globle->u8_ACK_Data[10]; // 电量(对应u8_ACK_Data[10])
CurrentMode = ps_Globle->u8_ACK_Data[11]; // 当前测试模式(对应u8_ACK_Data[11])
//获取对应状态用于LVGL界面更新
ps_Globle->ps_DeviceStatus->battery_percent=battery;//获取电量
//ps_Globle->ps_DeviceStatus->sensor=Sensor;//获取传感器状态
//时间字符串
sprintf(timeStr, "%04d-%02d-%02d %02d:%02d:%02d", Year, Month, Day,Hour,Minute,Second);
// 打印基础信息
printf("===== 设备状态 =====\r\n");
printf("CMD: %x\r\n",CMD);
printf("status:%d\r\n",status); // 可根据枚举值转换为文字(如0=空闲,1=测量中)
printf("Sensor:%d\r\n",Sensor);
printf("timeStr:%s\r\n",timeStr);
printf("battery: %d\r\n",battery);
printf("CurrentMode:%d\r\n",CurrentMode); // 可转换为文字(如1=CV模式,2=IT模式)
break;
case UART_ACK_SET_IT_PARAM_OK:
printf("UART_ACK_SET_IT_PARAM_OK\r\n");
//处理计算参数
uint32_t raw = (ps_Globle->u8_ACK_Data[0] << 24) | (ps_Globle->u8_ACK_Data[1] << 16) | (ps_Globle->u8_ACK_Data[2] << 8) | ps_Globle->u8_ACK_Data[3];
memcpy(&Res_val, &raw, sizeof(float));
printf("cal:%f\r\n",Res_val);
// HEARTBEATTimer->start();//0716 lytest
break;
case UART_ACK_SET_CV_PARAM_OK:
printf("UART_ACK_SET_CV_PARAM_OK\r\n");
//处理计算参数
uint32_t raw2 = (ps_Globle->u8_ACK_Data[0] << 24) | (ps_Globle->u8_ACK_Data[1] << 16) | (ps_Globle->u8_ACK_Data[2] << 8) | ps_Globle->u8_ACK_Data[3];
memcpy(&Res_val, &raw2, sizeof(float));
printf("cal:%f\r\n",Res_val);
// HEARTBEATTimer->start();//0716 lytest
break;
case UART_ACK_SET_SWV_PARAM_OK:
printf("UART_ACK_SET_SWV_PARAM_OK\r\n");
//处理计算参数
uint32_t raw3 = (ps_Globle->u8_ACK_Data[0] << 24) | (ps_Globle->u8_ACK_Data[1] << 16) | (ps_Globle->u8_ACK_Data[2] << 8) | ps_Globle->u8_ACK_Data[3];
memcpy(&Res_val, &raw3, sizeof(float));
printf("cal:%f\r\n",Res_val);
// HEARTBEATTimer->start();//0716 lytest
break;
case UART_ACK_CHECK_SENSOR_OK:
if (ps_Globle->u8_ACK_Data_LEN == UART_DATA_1_BYTE) {
printf("UART_ACK_CHECK_SENSOR_OK\r\n");
ps_Globle->ps_DeviceStatus->sensor=(ps_Globle->u8_ACK_Data[0]);//获取传感器状态
printf("sensorstate:%d\r\n",ps_Globle->ps_DeviceStatus->sensor);
//处理传感器状态
handle_sensor_state_update(ps_Globle->ps_DeviceStatus->sensor);
}
break;
case UART_CMD_START_IT_MEASURE_OK:
printf("UART_CMD_START_IT_MEASURE_OK\r\n");
// 释放旧内存
if (ITData != NULL) myfree(SRAMEX, ITData);
if (current_data != NULL) myfree(SRAMEX, current_data);
if (voltage_data != NULL) myfree(SRAMEX, voltage_data);
//分配内存
ITData = (float*)mymalloc(SRAMEX, s_Globle.ps_Parpam->sensor_datasum * sizeof(float));
current_data = (int*)mymalloc(SRAMEX, s_Globle.ps_Parpam->sensor_datasum * sizeof(int));
voltage_data = (int*)mymalloc(SRAMEX, s_Globle.ps_Parpam->sensor_datasum * sizeof(int));
// 检查分配结果
if (ITData == NULL || current_data == NULL || voltage_data == NULL) {
printf("内存分配失败!\r\n");
break;
}
// 重置计数器
data_index = 0;
last_cont = 0;
//创建定时器开始定时获取数据
handle_sensor_getdata();
break;
case UART_CMD_START_CV_MEASURE_OK:
printf("UART_CMD_START_CV_MEASURE_OK\r\n");
// 释放旧内存
if (CVData != NULL) myfree(SRAMEX, CVData);
if (current_data != NULL) myfree(SRAMEX, current_data);
if (voltage_data != NULL) myfree(SRAMEX, voltage_data);
//分配内存
CVData = (float*)mymalloc(SRAMEX, s_Globle.ps_Parpam->sensor_datasum * sizeof(float));
current_data = (int*)mymalloc(SRAMEX, s_Globle.ps_Parpam->sensor_datasum * sizeof(int));
voltage_data = (int*)mymalloc(SRAMEX, s_Globle.ps_Parpam->sensor_datasum * sizeof(int));
// 检查分配结果
if (CVData == NULL || current_data == NULL || voltage_data == NULL) {
printf("内存分配失败!\r\n");
break;
}
// 重置计数器
data_index = 0;
last_cont = 0;
//创建定时器开始定时获取数据
handle_sensor_getdata();
break;
case UART_CMD_START_SWV_MEASURE_OK:
printf("UART_CMD_START_SWV_MEASURE_OK\r\n");
// 释放旧内存
if (SWVData != NULL) myfree(SRAMEX, SWVData);
if (current_data != NULL) myfree(SRAMEX, current_data);
if (voltage_data != NULL) myfree(SRAMEX, voltage_data);
//分配内存
SWVData = (float*)mymalloc(SRAMEX, s_Globle.ps_Parpam->sensor_datasum * sizeof(float));
diffData = (float*)mymalloc(SRAMEX, s_Globle.ps_Parpam->sensor_datasum * sizeof(float));
current_data = (int*)mymalloc(SRAMEX, s_Globle.ps_Parpam->sensor_datasum * sizeof(int));
voltage_data = (int*)mymalloc(SRAMEX, s_Globle.ps_Parpam->sensor_datasum * sizeof(int));
// 检查分配结果
if (SWVData == NULL || current_data == NULL || voltage_data == NULL || diffData==NULL) {
printf("内存分配失败!\r\n");
break;
}
// 重置计数器
data_index = 0;
last_cont = 0;
//创建定时器开始定时获取数据
handle_sensor_getdata();
break;
case UART_ACK_GET_DATA_OK://获取数据成功
{
// 静态变量跟踪上次模式,用于检测模式变化
static int last_mode = -1;
// 检查模式是否变化,如果变化则重置滤波器
if (last_mode != s_Globle.ps_Parpam->current_mode && s_Globle.ps_Parpam->filter) {
ResetAllFilters();
last_mode = s_Globle.ps_Parpam->current_mode;
}
if(s_Globle.ps_Parpam->current_mode==ITMode){
// 接收新数据并存储到ITData
for (uint16_t i = 0; i < ps_Globle->u8_ACK_Data_LEN; i += 2) {
uint16_t raw = (ps_Globle->u8_ACK_Data[i] << 8) | ps_Globle->u8_ACK_Data[i+1];
float raw_current = AppCHRONOAMPCalcCurrent((int16_t)raw, Res_val);
if(s_Globle.ps_Parpam->filter)ITData[data_index] = IT_RealTimeFilter(raw_current);// 应用IT模式实时滤波
else ITData[data_index] = raw_current;
data_index++; // 累计总数据量
}
// 更新进度条
float persent = (float)data_index / s_Globle.ps_Parpam->sensor_datasum * 100;
handle_sensor_scanbar_update(persent);
// 实时处理新增数据并更新曲线
if (data_index > last_cont) {
uint16_t new_count = data_index - last_cont; // 新增数据数量
uint16_t start_idx = last_cont; // 新增数据起始索引
//计算扩展因子
// uint32_t scale = compute_scale_factor_fast(ITData, new_count);
// printf("scale:%d\r\n",scale);
//滤波处理
// LinearSmooth7(ITData, cont);
// 计算新增数据的电压和电流
for (int i = 0; i < new_count; i++) {
uint16_t idx = start_idx + i;
voltage_data[idx] = (idx + 1) * s_Globle.ps_Parpam->IT_Param.sampleInterval; // 电压=索引+1
current_data[idx] = (int)(ITData[idx] * 1000000); // 电流计算,统一扩展因子
}
// 调用增量更新函数,仅更新最新的new_count个数据点
update_chart_with_voltage_current(voltage_data, current_data, start_idx, new_count, ITMode);
first_scan=false;//不是第一次扫描
// 更新上次处理位置,下次从这里开始
last_cont = data_index;
draw_flag=1;
}
if(data_index==s_Globle.ps_Parpam->sensor_datasum){//累加数据点数等于测量数据总数
control_getdata_timer(0);//停止定时器
float analyse_time = (float)lv_Mode_Parpam.IT_Param.analyse_time / lv_Mode_Parpam.IT_Param.sampleInterval;
anodic_peak.voltage=voltage_data[(int)analyse_time-1];
anodic_peak.current=current_data[(int)analyse_time-1];//保留分析电流值
//处理传感器状态
handle_sensor_result_update(&anodic_peak,&cathodic_peak);
//保存数据到SD卡
save_IT_data_to_csv(&s_Globle.ps_Parpam->IT_Param,
voltage_data,
current_data,
data_index,
&anodic_peak);
first_scan=true;//第一次扫描
}
}
else if(s_Globle.ps_Parpam->current_mode==CVMode){
// 接收新数据并存储到CVData
for (uint16_t i = 0; i < ps_Globle->u8_ACK_Data_LEN; i += 2) {
uint16_t raw = (ps_Globle->u8_ACK_Data[i] << 8) | ps_Globle->u8_ACK_Data[i+1];
float raw_current = AppCHRONOAMPCalcCurrent((int16_t)raw, Res_val);
if(s_Globle.ps_Parpam->filter)CVData[data_index] = CV_RealTimeFilter(raw_current);// 应用IT模式实时滤波
else CVData[data_index] = raw_current;
data_index++; // 累计总数据量
}
// 更新进度条
float persent = (float)data_index / s_Globle.ps_Parpam->sensor_datasum * 100;
handle_sensor_scanbar_update(persent);
// 计算当前方向下的总步数
uint16_t totalstep = Dire ?
(s_Globle.ps_Parpam->CV_Param.HighEval - s_Globle.ps_Parpam->CV_Param.InitEval) /
s_Globle.ps_Parpam->CV_Param.SampleInt :
(s_Globle.ps_Parpam->CV_Param.InitEval - s_Globle.ps_Parpam->CV_Param.LowEval) /
s_Globle.ps_Parpam->CV_Param.SampleInt;
if (totalstep == 0) totalstep = 1; // 避免除零错误
// 实时处理新增数据
if (data_index > last_cont) {
uint16_t new_count = data_index - last_cont; // 新增数据点数
uint16_t start_idx = last_cont; // 起始索引
for (int i = 0; i < new_count; i++) {
uint16_t idx = start_idx + i;
uint16_t currentStep = DataCount - ScandataCount; // 当前周期内的步数
// 计算电压值(关键修改)
if (currentStep < totalstep) {
// 第一个半周期
if (Dire) {
voltage_data[idx] = s_Globle.ps_Parpam->CV_Param.InitEval +
currentStep * s_Globle.ps_Parpam->CV_Param.SampleInt;
} else {
voltage_data[idx] = s_Globle.ps_Parpam->CV_Param.InitEval -
currentStep * s_Globle.ps_Parpam->CV_Param.SampleInt;
}
} else {
// 第二个半周期
uint16_t stepInHalf = currentStep - totalstep;
if (Dire) {
voltage_data[idx] = s_Globle.ps_Parpam->CV_Param.HighEval -
stepInHalf * s_Globle.ps_Parpam->CV_Param.SampleInt;
} else {
voltage_data[idx] = s_Globle.ps_Parpam->CV_Param.LowEval +
stepInHalf * s_Globle.ps_Parpam->CV_Param.SampleInt;
}
}
// 计算电流值(带缩放)
current_data[idx] = (int)(CVData[idx] * 1000000); // 缩放因子根据需求调整
// 更新全局计数
DataCount++;
// 检查周期结束并更新状态
if (currentStep + 1 == 2 * totalstep) {
ScandataCount += 2 * totalstep;
if (s_Globle.ps_Parpam->CV_Param.InitEval != s_Globle.ps_Parpam->CV_Param.LowEval) {
Dire = !Dire; // 切换扫描方向
}
}
}
// 调用增量更新函数,仅更新最新的new_count个数据点
update_chart_with_voltage_current(voltage_data, current_data, start_idx, new_count, first_scan);
last_cont = data_index; // 更新已处理位置
draw_flag = 1;
first_scan=false;//不是第一次扫描了
}
if(data_index >= s_Globle.ps_Parpam->sensor_datasum){//完成一圈扫描
control_getdata_timer(0);//停止定时器
// 确保数据索引一致
if (data_index > 0) {
// 执行峰值检测
find_CV_peaks(voltage_data, current_data, data_index,
&anodic_peak, &cathodic_peak);
// 输出峰值信息(可根据需要显示在UI上)
if (anodic_peak.index != -1) {
printf("阳极峰: 电压=%d mV, 电流=%d A (索引=%d)\n",
anodic_peak.voltage, anodic_peak.current, anodic_peak.index);
// // 在图表上标记阳极峰
// mark_peak_on_chart(anodic_peak.voltage, anodic_peak.current, "Anodic Peak");
}
if (cathodic_peak.index != -1) {
printf("阴极峰: 电压=%d mV, 电流=%d A (索引=%d)\n",
cathodic_peak.voltage, cathodic_peak.current, cathodic_peak.index);
// // 在图表上标记阴极峰
// mark_peak_on_chart(cathodic_peak.voltage, cathodic_peak.current, "Cathodic Peak");
}
// 计算峰电位差(ΔEp)
if (anodic_peak.index != -1 && cathodic_peak.index != -1) {
int delta_ep = abs(anodic_peak.voltage - cathodic_peak.voltage);
printf("峰电位差(ΔEp) = %d mV\n", delta_ep);
// // 判断是否为可逆体系(ΔEp ≈ 59mV/n)
// if (delta_ep > 50 && delta_ep < 70) {
// printf("体系显示可逆电化学行为\n");
// }
}
}
// // 增加扫描计数
// static uint8_t cv_scan_count = 1;
//处理传感器状态
handle_sensor_result_update(&anodic_peak,&cathodic_peak);
// 保存当前扫描的峰值数据
anodic_peak_data[cv_scan_count-1] = anodic_peak;
cathodic_peak_data[cv_scan_count-1]=cathodic_peak;
// 在每次扫描完成后保存数据
voltage_data_scans[cv_scan_count-1] = mymalloc(SRAMEX, data_index * sizeof(int));
current_data_scans[cv_scan_count-1] = mymalloc(SRAMEX, data_index * sizeof(int));
for (uint16_t i = 0; i < data_index; i++) {
voltage_data_scans[cv_scan_count-1][i] = voltage_data[i];
current_data_scans[cv_scan_count-1][i] = current_data[i];
}
// 检查是否需要再次扫描
if(cv_scan_count < s_Globle.ps_Parpam->CV_Param.SweepSegments) {
cv_scan_count++; // 增加扫描计数
// 重置数据索引
data_index = 0;
last_cont = 0;
// 切换到下一个图表系列
lv_chart_series_t* next_ser = lv_chart_get_series_next(guider_ui.screen_scan_scan_chart,
guider_ui.screen_factorypattern_chart_elect_0);
if(!next_ser) {
next_ser = lv_chart_get_series_next(guider_ui.screen_scan_scan_chart, NULL);
}
guider_ui.screen_factorypattern_chart_elect_0 = next_ser;
lv_chart_hide_series(guider_ui.screen_scan_scan_chart, guider_ui.screen_factorypattern_chart_elect_0, false);
// 发送开始测试指令
TX_CMD_Pack(UART_CMD_START_CV_MEASURE);
// 确保发送缓冲区缓存一致性
SCB_CleanDCache_by_Addr((uint32_t *)s_UART.u_Buffer_Tx[0].u8_Buffer_T,
UART_TX_BUFFER_SIZE);
// 启动DMA接收
HAL_UART_Receive_DMA(&g_uart7_handle,
s_UART.u_Buffer_Rx[s_UART.u8_Uart_Rx_index].u8_Buffer_R,
UART_RX_BUFFER_SIZE);
s_UART.u8_Uart_Rx_DmaComplete = 0;
HAL_UART_Transmit_DMA(&g_uart7_handle,
s_UART.u_Buffer_Tx[0].u8_Buffer_T,
UART_TX_BUFFER_SIZE);
// 更新状态
lv_label_set_text(guider_ui.screen_scan_scan_label_state, "SCANNING");
s_Globle.ps_Parpam->current_status=TEST_STATUS_TESTING;//正在测量状态
} else {
// 所有扫描完成,停止定时器
control_getdata_timer(0);
// 在保存CSV时,调用修改后的函数
save_CV_data_to_csv(&s_Globle.ps_Parpam->CV_Param,
voltage_data_scans,
current_data_scans,
data_index,
anodic_peak_data,
cathodic_peak_data,
cv_scan_count); // 传递扫描次数
// 重置计数器
cv_scan_count = 1;
total_data_count = 0;
first_scan=false;//设置第一次扫描,为下次扫描做准备
// 在CV模式完成后释放内存
for (int i = 0; i < cv_scan_count; i++) {
if (voltage_data_scans[i] != NULL) {
myfree(SRAMEX, voltage_data_scans[i]);
voltage_data_scans[i] = NULL;
}
if (current_data_scans[i] != NULL) {
myfree(SRAMEX, current_data_scans[i]);
current_data_scans[i] = NULL;
}
}
}
}
}
else if(s_Globle.ps_Parpam->current_mode == SWVMode) {
// 接收新数据并存储到ITData
for (uint16_t i = 0; i < ps_Globle->u8_ACK_Data_LEN; i += 2) {
uint16_t raw = (ps_Globle->u8_ACK_Data[i] << 8) | ps_Globle->u8_ACK_Data[i+1];
float raw_current = AppCHRONOAMPCalcCurrent((int16_t)raw, Res_val);
if(s_Globle.ps_Parpam->filter)SWVData[data_index] = SWV_RealTimeFilter(raw_current);// 应用IT模式实时滤波
else SWVData[data_index] = raw_current;
data_index++; // 累计总数据量
}
// 更新进度条
float persent = (float)data_index / (s_Globle.ps_Parpam->sensor_datasum *2) * 100;
handle_sensor_scanbar_update(persent);
// 实时处理新增数据并更新曲线
if (data_index > last_cont) {
uint16_t new_count = data_index - last_cont; // 新增数据数量
uint16_t start_idx = last_cont; // 新增数据起始索引
uint16_t diff_count = 0;
// 计算SWV差值数据
for (uint16_t i = start_idx; i < data_index; i += 2) {
if (i + 1 < data_index) {
// 计算正向和反向脉冲的差值
float diff = SWVData[i] - SWVData[i+1];
diffData[diff_count] = diff;
diff_count++;
}
}
// 电压计算
float init = s_Globle.ps_Parpam->SWV_Param.InitEval;
float incr = s_Globle.ps_Parpam->SWV_Param.IncrEval;
int dir = (init < s_Globle.ps_Parpam->SWV_Param.FinalEval) ? 1 : -1;
// 为新增数据计算电压和电流
for (uint16_t i = 0; i < diff_count; i++) {
uint16_t idx = start_idx/2 + i;
int voltage_val = init + (incr * (idx+1)) * dir;
int current_val = (int)(diffData[i] * 1000000);
// 保存到全局数据数组
if (total_data_count < MAX_TOTAL_DATA_POINTS) {
voltage_data_all[total_data_count] = voltage_val;
current_data_all[total_data_count] = current_val;
total_data_count++;
}
// 实时更新图表
voltage_data[idx] = voltage_val;
current_data[idx] = current_val;
}
// 调用增量更新函数
update_chart_with_voltage_current(voltage_data, current_data,
start_idx/2, diff_count,
first_scan);
first_scan=false;//不是第一次扫描了
// 更新上次处理位置
last_cont = data_index;
draw_flag = 1;
}
// 检查是否完成
if(data_index >= s_Globle.ps_Parpam->sensor_datasum * 2) {
// 所有扫描完成,停止定时器
control_getdata_timer(0);
// 处理当前扫描的结果
float analyse_potential = (float)(lv_Mode_Parpam.SWV_Param.analyse_potential - lv_Mode_Parpam.SWV_Param.InitEval)/lv_Mode_Parpam.SWV_Param.IncrEval;
int analyse_index = (int)analyse_potential - 1;
if (analyse_index < 0) analyse_index = 0;
if (analyse_index >= data_index/2) analyse_index = data_index/2 - 1;
anodic_peak.voltage = voltage_data[analyse_index];
anodic_peak.current = current_data[analyse_index];
// 处理传感器状态
handle_sensor_result_update(&anodic_peak, &cathodic_peak);
// 保存当前扫描的峰值数据
anodic_peak_data[scan_count-1] = anodic_peak;
// 分配内存并复制当前扫描的数据
current_data_scans[scan_count-1] = mymalloc(SRAMEX, (data_index/2) * sizeof(int));
for (uint16_t i = 0; i < data_index/2; i++) {
current_data_scans[scan_count-1][i] = current_data[i];
}
// 检查是否需要再次扫描
if(scan_count < s_Globle.ps_Parpam->SWV_Param.Number) {
scan_count++; // 增加扫描计数
// 重置数据索引
data_index = 0;
last_cont = 0;
// 切换到下一个图表系列
lv_chart_series_t* next_ser = lv_chart_get_series_next(guider_ui.screen_scan_scan_chart,
guider_ui.screen_factorypattern_chart_elect_0);
if(!next_ser) {
next_ser = lv_chart_get_series_next(guider_ui.screen_scan_scan_chart, NULL);
}
guider_ui.screen_factorypattern_chart_elect_0 = next_ser;
lv_chart_hide_series(guider_ui.screen_scan_scan_chart, guider_ui.screen_factorypattern_chart_elect_0, false);
// 发送开始测试指令
TX_CMD_Pack(UART_CMD_START_SWV_MEASURE);
// 确保发送缓冲区缓存一致性
SCB_CleanDCache_by_Addr((uint32_t *)s_UART.u_Buffer_Tx[0].u8_Buffer_T,
UART_TX_BUFFER_SIZE);
// 启动DMA接收
HAL_UART_Receive_DMA(&g_uart7_handle,
s_UART.u_Buffer_Rx[s_UART.u8_Uart_Rx_index].u8_Buffer_R,
UART_RX_BUFFER_SIZE);
s_UART.u8_Uart_Rx_DmaComplete = 0;
HAL_UART_Transmit_DMA(&g_uart7_handle,
s_UART.u_Buffer_Tx[0].u8_Buffer_T,
UART_TX_BUFFER_SIZE);
// 更新状态
lv_label_set_text(guider_ui.screen_scan_scan_label_state, "SCANNING");
s_Globle.ps_Parpam->current_status=TEST_STATUS_TESTING;//正在测量状态
} else {
// 所有扫描完成,停止定时器
control_getdata_timer(0);
// 在每次扫描完成后记录数据点数
data_counts[scan_count-1] = data_index/2;
// 保存数据时传递数据点数数组
save_SWV_data_to_csv(&s_Globle.ps_Parpam->SWV_Param,
current_data_scans,
data_counts, // 改为传递数组
anodic_peak_data,
scan_count);
// 重置计数器
scan_count = 1;
total_data_count = 0;
first_scan=true;//第一次扫描
}
}
}
break;
}
case UART_ACK_STOP_OK:
printf("UART_ACK_STOP_OK\r\n");
// 停止获取数据定时器
control_getdata_timer(0);//停止定时器
if(s_Globle.ps_Parpam->current_mode==ITMode){
float analyse_time=(float)lv_Mode_Parpam.IT_Param.analyse_time/lv_Mode_Parpam.IT_Param.sampleInterval;//存储分析电流
if(data_index>=(int)analyse_time){
anodic_peak.voltage=voltage_data[(int)analyse_time-1];
anodic_peak.current=current_data[(int)analyse_time-1];//保留分析电流值
}else{
//赋值结果
anodic_peak.voltage=voltage_data[data_index-1];
anodic_peak.current=current_data[data_index-1];//保留分析电流值
}
//保存当前数据到SD卡
save_IT_data_to_csv(&s_Globle.ps_Parpam->IT_Param,
voltage_data,
current_data,
data_index,
&anodic_peak);
}else if(s_Globle.ps_Parpam->current_mode==CVMode){
// 执行峰值检测
find_CV_peaks(voltage_data, current_data, data_index,
&anodic_peak, &cathodic_peak);
// 输出峰值信息(可根据需要显示在UI上)
if (anodic_peak.index != -1) {
printf("阳极峰: 电压=%d mV, 电流=%d A (索引=%d)\n",
anodic_peak.voltage, anodic_peak.current, anodic_peak.index);
}
if (cathodic_peak.index != -1) {
printf("阴极峰: 电压=%d mV, 电流=%d A (索引=%d)\n",
cathodic_peak.voltage, cathodic_peak.current, cathodic_peak.index);
}
// 计算峰电位差(ΔEp)
if (anodic_peak.index != -1 && cathodic_peak.index != -1) {
int delta_ep = abs(anodic_peak.voltage - cathodic_peak.voltage);
printf("峰电位差(ΔEp) = %d mV\n", delta_ep);
}
// 只保存当前扫描的数据(单次扫描)
// 分配临时数组存储当前扫描数据
int* temp_voltage = (int*)mymalloc(SRAMEX, data_index * sizeof(int));
int* temp_current = (int*)mymalloc(SRAMEX, data_index * sizeof(int));
memcpy(temp_voltage, voltage_data, data_index * sizeof(int));
memcpy(temp_current, current_data, data_index * sizeof(int));
// 在保存CSV时,调用修改后的函数
save_CV_data_to_csv(&s_Globle.ps_Parpam->CV_Param,
&temp_voltage,
&temp_current,
data_index,
anodic_peak_data,
cathodic_peak_data,
cv_scan_count); // 传递扫描次数
// 释放临时内存
myfree(SRAMEX, temp_voltage);
myfree(SRAMEX, temp_current);
}
else if(s_Globle.ps_Parpam->current_mode==SWVMode){
// 计算分析点的位置
float analyse_potential = (float)(lv_Mode_Parpam.SWV_Param.analyse_potential - lv_Mode_Parpam.SWV_Param.InitEval)/lv_Mode_Parpam.SWV_Param.IncrEval;
int analyse_index = (int)analyse_potential - 1;
// 确保索引有效
if (analyse_index < 0) analyse_index = 0;
if (analyse_index >= data_index/2) analyse_index = data_index/2 - 1;
if(data_index >= (int)analyse_potential){
anodic_peak.voltage = voltage_data[analyse_index];
anodic_peak.current = current_data[analyse_index];//保留分析电流值
} else {
//赋值结果
anodic_peak.voltage = voltage_data[data_index/2 - 1];
anodic_peak.current = current_data[data_index/2 - 1];//保留分析电流值
}
// 保存当前扫描的数据到current_data_scans数组
if (scan_count <= MAX_SCANS) {
current_data_scans[scan_count-1] = mymalloc(SRAMEX, (data_index/2) * sizeof(int));
for (uint16_t i = 0; i < data_index/2; i++) {
current_data_scans[scan_count-1][i] = current_data[i];
}
}
// 保存峰值数据
anodic_peak_data[scan_count-1] = anodic_peak;
// 在每次扫描完成后记录数据点数
data_counts[scan_count-1] = data_index/2;
// 保存数据时传递数据点数数组
save_SWV_data_to_csv(&s_Globle.ps_Parpam->SWV_Param,
current_data_scans,
data_counts, // 改为传递数组
anodic_peak_data,
scan_count);
}
//处理传感器状态
handle_sensor_result_update(&anodic_peak,&cathodic_peak);
break;
}
return 0;
}Scan Type SWV
InitEval 200
FinalEval 600
IncrEval 4
AmplitudeE 25
QuiteTime 2000
Frequency 10
Range 0
Number of Scans 2
Analyse Potential 500
Light Type 0
Light Power (mW) 2
Min Range 200
Max Range 400
Date 20250412
Time 011000
File Number 1
Peak Data
Scan Voltage(mV) Current(uA)
1 500 140
2 488 139
Average 494 139
Voltage(mV) Scan1(uA) Scan2(uA)
200 139
204 139
208 140
212 138
216 141
220 139
224 139
228 139
232 137
236 139
240 138
244 140
248 138
252 140
256 140
260 140
264 140
268 139
272 140
276 139
280 140
284 139
288 140
292 140
296 140
300 140
304 138
308 140
312 138
316 140
320 138
324 139
328 140
332 140
336 140
340 138
344 140
348 137
352 138
356 139
360 139
364 138
368 139
372 139
376 136
380 139
384 137
388 139
392 136
396 139
400 141
404 139
408 140
412 138
416 140
420 139
424 140
428 139
432 140
436 139
440 139
444 140
448 138
452 140
456 139
460 140
464 139
468 140
472 138
476 140
480 140
484 139
为什么会这样,第一圈数据直接为空了,而且第一圈数据已经是200-600的这里为什么又被省略了
最新发布