|
| 很给力! |
|
#define SAMPLE_RATE 500 // 每500us采样一次(2kHz) u16 adc_samples[40]; // 采样缓冲区(20ms/500us=40个样本) u8 sample_index = 0; u32 sample_sum = 0; // 采样总和 u8 full_window = 0; // 窗口是否填满标志 // 全局变量用于平滑滤波 #define FILTER_SHIFT 5 // 使用5位右移实现1/32系数 // 定时器1中断(500us周期) void Timer1_ISR(void) interrupt 3 { static uint adc_timer = 0; uint raw_adc; uint filtered_adc = 0; // 滤波后的ADC值(累加形式) u16 raw_value; // ====== 校准完成处理 ====== if (cal_ok_display) { cal_ok_counter++; if (cal_ok_counter >= 2000) { // 2000 * 500us = 1秒 cal_ok_display = 0; in_calibration = 0; // 退出校准模式 } } // 显示刷新 Display(); // ADC采样控制 if(++adc_timer >= (SAMPLE_RATE/500)) { adc_timer = 0; // 启动ADC转换 ADC_RES = 0; ADC_RESL = 0; ADC_CONTR = (ADC_CONTR & 0xF0) | 0x40 | 11; // 通道11 } // 读取上次ADC结果 if(ADC_CONTR & 0x20) { raw_adc = ((ADC_RES & 0x03) << 8) | ADC_RESL; ADC_CONTR &= ~0x20; // 滑动窗口处理 if(full_window) { sample_sum -= adc_samples[sample_index]; } sample_sum += raw_adc; adc_samples[sample_index] = raw_adc; if(++sample_index >= sizeof(adc_samples)/sizeof(adc_samples[0])) { sample_index = 0; full_window = 1; } // 当窗口满时计算平均值 if(sample_index == 0 && full_window) { u16 avg = sample_sum / 40; // 40个样本平均 raw_avg = avg; // 保存原始平均值用于校准 // 原始ADC值转换 (0-1023 -> 0-250) raw_value = (u16)((unsigned long)avg * calibration / 1023); /********** IIR低通滤波 **********/ if (filtered_adc == 0) { filtered_adc = (uint)raw_value << FILTER_SHIFT; } else { filtered_adc = filtered_adc - (filtered_adc >> FILTER_SHIFT) + raw_value; } // 获取滤波后的值并四舍五入 pv_value = (filtered_adc + (1 << (FILTER_SHIFT-1))) >> FILTER_SHIFT; } } } // ====== 校准相关变量 ====== bit is_calibrated = 0; // 校准标志位 0-未校准 1-已校准 bit in_calibration = 0; // 校准模式标志 bit cal_ok_display = 0; // 显示OK标志 uint cal_ok_counter = 0; // OK显示计数器 uint raw_avg = 0; // 原始ADC平均值(0-1023) uint calibration = 250; // 校准系数 // ====== 校准模式按键处理 ====== if (in_calibration && !cal_ok_display) { // KEY4: 确认校准 if(key_pressed[3]) { key_pressed[3] = 0; // 清除按键标志 // 执行校准计算 if (raw_avg != 0) { calibration = (220 * 1023UL) / raw_avg; is_calibrated = 1; // 设置校准标志 cal_ok_display = 1; // 显示OK cal_ok_counter = 0; // 重置计数器 } } } |
交流取样.PNG (19.94 KB, 下载次数: 0)
cr8526 发表于 2025-6-30 23:11 存在这个隐患。所以我最终采用了电压互感器和电流互感器的方式来采样。 |
| 万一其中一个电阻烧了,会不会把人给电到的 |
| 能说说电路的原理吗? |