|
#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; // 重置计数器
}
}
} |
|