目录前置说明1 全局参数头文件 global_param.h 新增波形 / FFT 相关定义2 SPI 底层新增读取整周期原始波形 fpga_spi.h/fpga_spi.cfpga_spi.h 新增接口声明fpga_spi.c 波形读取实现3 FFT 基波提取独立模块 fft_meter.c/fft_meter.hfft_meter.hfft_meter.c 完整 FFT 运算 计量算法4 主函数 main.c 整合 FFT 校准检定分支5 Flash 校准参数存储 ct_cal_flash.c 不变复用原有6 工程关键配置要点保证 FFT 精度与实时性7 计量逻辑说明完全基于原始采样无 FPGA 预处理数据参与前置说明硬件链路FPGAad4134_spi_capture_opt输出ch_data[0~5]6 通道 24bit 有符号原始采样一周期点数PERIOD_POINTS1024/512/256依赖库ARM CMSIS-DSP 硬件 FFT 浮点库STM32H7 开启 FPU 双精度计量逻辑读取整周期原始波形 → FFT 提取 50Hz 基波幅值 / 相位 → JJG169-2010 计算比值误差、相位角差 → 温漂线性补偿双模式兼容主线快速检定使用 FPGA 预处理 IQ 幅值相位溯源校准模式使用原始波形 FFT 独立计算做比对校验。1 全局参数头文件 global_param.h 新增波形 / FFT 相关定义#ifndef GLOBAL_PARAM_H #define GLOBAL_PARAM_H #include stdint.h #include math.h #include arm_math.h // 与FPGA顶层严格同步三档采样点数 #define SAMPLE_256 256 #define SAMPLE_512 512 #define SAMPLE_1024 1024 #define PERIOD_POINTS SAMPLE_1024 // 0.02级互感器检定误差阈值 JJG169 #define FI_LIMIT 0.02f #define DELTA_LIMIT 1.0f // 6工位互感器定义 #define STATION_NUM 6 #define FPGA_FRAME_LEN 32 #define PHASE_MAX 65536U #define RAD_TO_MIN 3437.7468f // FFT最大缓存长度 #define SAMPLE_MAX_LEN 1024 // 单工位校准参数结构体 typedef struct{ float rated_kn; // 额定变比 float k_f; // 比差温漂系数 %/℃ float k_delta; // 角差温漂系数 /℃ float fi_offset; // 固定比差偏移 float delta_offset; // 固定角偏移 }CT_Cal_t; // FFT基波提取结果 typedef struct{ float32_t amp; // 基波幅值 float32_t phase; // 基波相位 [-π,π] rad }FFT_Result_t; // 主线FPGA预处理检定结果 typedef struct{ uint8_t valid; float fi; float delta_min; uint16_t mag_x; uint16_t ph_x; float temp; uint8_t is_pass; }CT_Result_t; extern CT_Cal_t ct_cal[STATION_NUM]; extern CT_Result_t ct_res[STATION_NUM]; extern float env_temp; extern uint16 std_mag; extern uint16 std_ph; // FFT全局缓存 extern int32_t raw_wave_buf[STATION_NUM][SAMPLE_MAX_LEN]; extern FFT_Result_t fft_res[STATION_NUM]; // DSP FFT全局句柄 extern arm_cfft_instance_f32 fft_handle; extern float32_t fft_in_buf[SAMPLE_MAX_LEN]; extern float32_t fft_mag_buf[SAMPLE_MAX_LEN/2]; #endif2 SPI 底层新增读取整周期原始波形 fpga_spi.h/fpga_spi.cfpga_spi.h 新增接口声明// 读取指定工位一整周期PERIOD_POINTS点24bit原始采样波形 HAL_StatusTypeDef FPGA_ReadRawWave(uint16_t station, int32_t *wave_out);fpga_spi.c 波形读取实现HAL_StatusTypeDef FPGA_ReadRawWave(uint16_t station, int32_t *wave_out) { if(FPGA_SPI_SendReq(CMD_READ_RAW, station) ! HAL_OK) { return HAL_ERROR; } uint16_t point_cnt 0; uint16_t frame_offset 4; // 循环解析SPI帧内24bit采样数据填充整周期波形 while(point_cnt PERIOD_POINTS) { if(frame_offset 2 FPGA_FRAME_LEN) { if(FPGA_SPI_SendReq(CMD_READ_RAW, station) ! HAL_OK) return HAL_ERROR; frame_offset 4; } // 拼接24bit有符号采样3字节大端 int32_t raw_24 ((int32_t)rx_buf[frame_offset2] 16) | ((int32_t)rx_buf[frame_offset1] 8) | rx_buf[frame_offset]; // 24bit符号扩展至32bit if(raw_24 0x00800000) raw_24 | 0xFF000000; wave_out[point_cnt] raw_24; frame_offset 3; } return HAL_OK; }3 FFT 基波提取独立模块 fft_meter.c/fft_meter.hfft_meter.h#ifndef FFT_METER_H #define FFT_METER_H #include global_param.h // 初始化FFT句柄程序启动调用一次 void FFT_Init_Handle(void); // 输入32bit原始波形数组输出50Hz基波幅值、相位 void FFT_Calc_Fundamental(int32_t *wave_in, FFT_Result_t *fft_out); // 基于FFT基波结果计算补偿后比差 % float Calc_RatioError_FFT(float32_t std_amp, float32_t test_amp, uint16_t st, float temp); // 基于FFT基波相位计算补偿后角差 单位分 float Calc_PhaseDelta_FFT(float32_t std_phase, float32_t test_phase, uint16_t st, float temp); // 0.02级合格判定 uint8_t Check002Class_FFT(float fi, float delta); #endiffft_meter.c 完整 FFT 运算 计量算法#include fft_meter.h arm_cfft_instance_f32 fft_handle; float32_t fft_in_buf[SAMPLE_MAX_LEN]; float32_t fft_mag_buf[SAMPLE_MAX_LEN/2]; void FFT_Init_Handle(void) { arm_cfft_init_f32(fft_handle, PERIOD_POINTS); } void FFT_Calc_Fundamental(int32_t *wave_in, FFT_Result_t *fft_out) { uint16_t i; // 1. 24bit有符号原始采样转浮点FFT输入 for(i 0; i PERIOD_POINTS; i) { fft_in_buf[i] (float32_t)wave_in[i]; } // 2. 复数FFT运算实数输入虚部初始0 arm_cfft_f32(fft_handle, fft_in_buf, 0, 1); // 3. 计算各频点幅值 arm_cmplx_mag_f32(fft_in_buf, fft_mag_buf, PERIOD_POINTS / 2); // 采样率 Fs 50 * PERIOD_POINTS频率分辨率 F_res Fs / PERIOD_POINTS 50Hz // 0:直流分量1:50Hz基波 uint16_t fund_idx 1; float32_t I fft_in_buf[2 * fund_idx]; float32_t Q fft_in_buf[2 * fund_idx 1]; // 4. 基波幅值、反正切相位 fft_out-amp sqrtf(I * I Q * Q); fft_out-phase atan2f(Q, I); // [-π, π] } // JJG169-2010 比差公式 FFT波形版 float Calc_RatioError_FFT(float32_t std_amp, float32_t test_amp, uint16_t st, float temp) { float Kn ct_cal[st].rated_kn; float fi_raw (Kn * std_amp - test_amp) / test_amp * 100.0f; // 温漂线性补偿 出厂固定偏移 float fi_comp fi_raw ct_cal[st].k_f * temp ct_cal[st].fi_offset; return fi_comp; } // 相位差换算角差单位分 float Calc_PhaseDelta_FFT(float32_t std_phase, float32_t test_phase, uint16_t st, float temp) { float delta_rad std_phase - test_phase; // 相位区间修正 [-π, π]消除0/2π跳变 if(delta_rad M_PI) delta_rad - 2.0f * M_PI; if(delta_rad -M_PI) delta_rad 2.0f * M_PI; // 弧度转分 float delta_min delta_rad * RAD_TO_MIN; // 温漂出厂偏移补偿 float delta_comp delta_min ct_cal[st].k_delta * temp ct_cal[st].delta_offset; return delta_comp; } uint8_t Check002Class_FFT(float fi, float delta) { if(fi FI_LIMIT || fi -FI_LIMIT) return 0; if(delta DELTA_LIMIT || delta -DELTA_LIMIT) return 0; return 1; }4 主函数 main.c 整合 FFT 校准检定分支#include fft_meter.h // 全局波形缓存 int32_t raw_wave_buf[STATION_NUM][SAMPLE_MAX_LEN]; FFT_Result_t fft_res[STATION_NUM]; int main(void) { // CubeMX初始化省略 CT_Cal_FlashLoad(); FFT_Init_Handle(); // 初始化FFT硬件句柄 HAL_TIM_Base_Start_IT(htim8); TFT_Init(); while(1) { ETH_UploadTask(); PrintTask(); // 校准模式按键触发读取原始波形FFT双路比对 if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) GPIO_PIN_RESET) { Run_FFT_Calibration_Mode(); } HAL_Delay(10); } } // 校准模式读取6通道原始波形FFT独立计算误差与FPGA结果比对 void Run_FFT_Calibration_Mode(void) { uint16_t st; // 1. 读取6工位一周期原始24bit采样波形 for(st 0; st STATION_NUM; st) { if(FPGA_ReadRawWave(st, raw_wave_buf[st]) ! HAL_OK) { continue; } // 2. FFT提取基波幅值相位 FFT_Calc_Fundamental(raw_wave_buf[st], fft_res[st]); } // 标准通道工位0基波基准 float32_t fft_std_amp fft_res[0].amp; float32_t fft_std_ph fft_res[0].phase; // 3. 循环计算6工位FFT比差、角差 for(st 0; st STATION_NUM; st) { float fi_fft Calc_RatioError_FFT(fft_std_amp, fft_res[st].amp, st, env_temp); float delta_fft Calc_PhaseDelta_FFT(fft_std_amp, fft_res[st].phase, st, env_temp); uint8_t pass Check002Class_FFT(fi_fft, delta_fft); // 存入缓存屏幕/上位机双路比对显示 TFT_Show_FFT_Compare(st, fi_fft, delta_fft, pass); ETH_Save_FFT_Result(st, fi_fft, delta_fft); } } // TIM8 100ms主线检定原有FPGA预处理方案不变 void TIM8_UP_IRQHandler(void) { // 原有主线代码省略不改动实时检定逻辑 }5 Flash 校准参数存储 ct_cal_flash.c 不变复用原有6 工程关键配置要点保证 FFT 精度与实时性CubeMX 内核配置内核时钟 480MHz开启 L1 I/D CacheFPU双精度浮点fpv5_dp添加 CMSIS-DSP 库全局宏定义ARM_MATH_DSP编译器宏编译选项添加-mfloat-abihard -mfpufpv5-dp-dp -DARM_MATH_DSP内存分配FFT 大缓存fft_in_buf/raw_wave_buf放置外部 FMC SRAM避免 RAM 溢出两种工作模式分工正常检定使用 FPGA 预处理iq_mag/phase_out100ms 快速刷新界面溯源校准 / 出厂标定按键触发 FFT 模式基于原始 24bit 波形独立计算与 FPGA 结果比对验证整机 0.02 级精度。7 计量逻辑说明完全基于原始采样无 FPGA 预处理数据参与数据源头FPGA AD4134 24bit 差分原始采样无 FPGA 内部解调、滤波、CORDIC 处理频谱提取STM32 硬件 FFT 提取 50Hz 工频基波自动滤除 3/5/7 次谐波干扰幅值相位纯软件反正切、开方计算独立一套计量链路误差标准严格遵循 JJG169-2010 电流互感器检定规程公式温漂补偿复用同一套多点标定温漂系数抵消互感器与模拟电路温度漂移双路校验FFT 软件计算结果与 FPGA 硬件锁相结果同时显示用于整机精度溯源标定。