STM32的ADC校准过程

以下是STM32 ADC校准的详细技术说明,包含实际操作步骤和注意事项:

一、ADC校准的必要性

  1. 误差来源分析

    • 零点偏移误差(Offset Error):输入0V时输出不为0
    • 增益误差(Gain Error):满量程时的线性偏差
    • 非线性误差(DNL/INL):转换曲线的阶梯偏差
    • 温度漂移(典型值±2℃时±4LSB)
  2. 校准目标

    • 12位ADC的有效精度达到±1LSB
    • 减少芯片个体差异影响
    • 补偿供电电压波动带来的误差

二、STM32内置校准流程

1. 校准寄存器操作流程
// 适用于STM32F1/F4系列的标准校准流程
void ADC_Calibration(ADC_TypeDef* ADCx) {
    // 1. 使能ADC复位校准
    ADCx->CR2 |= ADC_CR2_RSTCAL;
    while(ADCx->CR2 & ADC_CR2_RSTCAL); // 等待复位完成

    // 2. 启动校准过程
    ADCx->CR2 |= ADC_CR2_CAL;
    while(ADCx->CR2 & ADC_CR2_CAL);    // 等待校准完成

    // 3. 获取校准因子(F4系列需要)
    #if defined(STM32F4xx)
    uint32_t cal_value = ADCx->CALFACT;
    #endif
}
2. 校准时序要求
步骤最小时间典型值条件
电源稳定等待10μs20μs上电后首次使用前
复位校准时间2个ADC周期-内部自动控制
校准过程时间12位模式:28个周期≈7μs @14MHz与ADC时钟频率相关

三、外部校准进阶方法

1. 两点校准法(推荐)
// 使用标准电压源校准
#define VREF_3V0  3.000f  // 外部精密参考电压
#define ADC_RES   4095.0f // 12位分辨率

void Advanced_Calibration() {
    // 连接已知电压到ADC通道
    float measured_0V = Read_ADC(0);    // 短接GND
    float measured_3V = Read_ADC(VREF); // 连接3V标准源
    
    // 计算校准系数
    float scale = VREF_3V0 / (measured_3V - measured_0V);
    float offset = measured_0V * scale;
    
    // 存储到Flash
    Save_CalibrationParams(offset, scale);
}

float Get_CalibratedValue(uint16_t raw) {
    return (raw * saved_scale) - saved_offset;
}
2. 校准参数存储

推荐使用Flash的最后页存储校准参数:

typedef struct {
    float offset;
    float scale;
    uint32_t crc;
} ADC_CalibData;

#define CALIB_ADDR 0x0800F000 // Flash最后一页

void Save_CalibrationParams(float offset, float scale) {
    ADC_CalibData data = {
        .offset = offset,
        .scale = scale,
        .crc = Calculate_CRC32(&data, sizeof(data)-4)
    };
    
    FLASH_Unlock();
    FLASH_ProgramWord(CALIB_ADDR, *(uint32_t*)&data);
    //... 连续写入多个word
    FLASH_Lock();
}

四、温度补偿校准

当工作温度变化超过±10℃时需进行补偿:

// 读取内部温度传感器(需先校准)
float Read_Temperature() {
    // 启用温度传感器通道
    ADC->CCR |= ADC_CCR_TSVREFE;
    
    // 读取温度传感器原始值
    uint16_t raw = Read_ADC(ADC_CHANNEL_TEMP);
    
    // 应用校准参数(从Flash读取)
    float vsense = raw * VREF/4095.0f;
    float temperature = ((vsense - V25)/Avg_Slope) + 25;
    
    return temperature;
}

// 温度补偿公式
void Temp_Compensation() {
    static float coeff[3] = {1.0, 0.003, 0.00002}; // 典型补偿系数
    float temp = Read_Temperature();
    current_scale = saved_scale * (coeff[0] + coeff[1]*temp + coeff[2]*temp*temp);
}

五、校准验证方法

  1. 静态测试

    // 测试代码
    void Test_ADC_Accuracy() {
        Connect_KnownVoltage(1.65f); // 连接精准1.65V
        uint32_t sum = 0;
        for(int i=0; i<1000; i++){
            sum += Read_ADC();
        }
        float avg = sum / 1000.0f;
        float error = fabs((avg * 3.3f/4095) - 1.65f);
        printf("实测误差:%.2f mV", error*1000);
    }
    
  2. 动态性能测试

    • 使用信号发生器输入正弦波
    • 通过FFT分析ENOB(有效位数)
    • 计算THD(总谐波失真)应小于-60dB

六、软件滤波增强

结合硬件校准使用数字滤波:

#define FILTER_DEPTH 16

typedef struct {
    uint16_t buffer[FILTER_DEPTH];
    uint8_t index;
} MovingAverage_Filter;

uint16_t Filter_ADC_Value(uint16_t new_val) {
    static MovingAverage_Filter filter = {0};
    
    filter.buffer[filter.index] = new_val;
    filter.index = (filter.index + 1) % FILTER_DEPTH;
    
    uint32_t sum = 0;
    for(int i=0; i<FILTER_DEPTH; i++){
        sum += filter.buffer[i];
    }
    return sum / FILTER_DEPTH;
}

七、工程实践建议

  1. 校准周期

    • 首次出厂校准
    • 每6个月定期校准
    • 检测到温度突变>15℃时触发重新校准
  2. PCB布局要点

    • ADC电源引脚添加10μF+0.1μF去耦电容
    • 模拟走线与数字走线间距>3倍线宽
    • 敏感信号采用guard ring保护
  3. 异常处理机制

    #define ADC_OVERSHOOT_THRESHOLD 4050 // 3.3V对应4095
    
    void ADC_Check_Abnormal() {
        uint16_t val = Read_ADC();
        if(val > ADC_OVERSHOOT_THRESHOLD) {
            ADC_Reinit(); // 重新初始化ADC
            NVIC_SystemReset(); // 严重错误重启
        }
    }
    
  4. 低功耗模式校准

    void Enter_LowPowerMode() {
        ADC->CR2 &= ~ADC_CR2_ADON;  // 关闭ADC
        PWR_EnterSTOPMode();        // 进入STOP模式
        
        // 唤醒后重新校准
        ADC_Calibration(ADC1);
        ADC_Cmd(ADC1, ENABLE);
    }
    

这些校准技术的组合应用可使STM32 ADC的实际测量精度达到:

  • 常温下±0.5% FSR
  • 全温度范围±1.2% FSR
  • 长期稳定性±0.8% FSR

建议在浇花系统中对土壤湿度传感器每24小时执行一次自动零点校准(短接传感器输入),并结合温度补偿算法实现全天候精准测量。

### STM32F103 ADC 配置指南 STM32F103系列微控制器内置了一个高性能的模拟到数字转换器(ADC),能够实现单次和连续模式下的多通道采样。该器件支持多达18个外部输入通道,可以测量内部温度传感器信号以及Vrefint电压。 #### 初始化设置 为了使能并配置ADC模块,在初始化阶段需完成如下操作: - 解锁ADC外设时钟 - 设置分辨率、对齐方式等参数 - 启动校准过程以确保精度 ```c // 开启RCC时钟访问权限并启动ADC时钟 __HAL_RCC_ADC_CLK_ENABLE(); // 创建默认配置结构体实例 ADC_HandleTypeDef hadc; hadc.Instance = ADC1; if (HAL_ADC_Init(&hadc) != HAL_OK){ // 错误处理逻辑... } ``` #### 单次转换模式 当只需要获取一次性的AD值读取结果时可采用此方法。调用`HAL_ADC_Start()`函数触发开始命令;随后通过轮询等待结束标志位被置位来判断是否已完成数据采集工作[^1]。 ```c uint32_t adc_value; if(HAL_ADC_Start(&hadc)!= HAL_OK){ // 处理错误情况... } if(HAL_ADC_PollForConversion(&hadc, 1000) == HAL_OK){ adc_value = HAL_ADC_GetValue(&hadc); } else { // 超时或其他异常情形... } ``` #### 连续扫描模式 对于需要持续监控多个IO口电平的应用场景而言更为适用。在此种情况下应该先指定好要参与循环检测的目标引脚列表,并开启DMA传输功能以便高效地搬运大量样本点至内存缓冲区中存储起来待后续分析使用[^2]。 ```c static uint32_t aAdcValues[NO_OF_CHANNELS]; // DMA流/请求ID定义 #define DMA_STREAM_ID LL_DMA_STREAM_1 #define DMA_REQUEST_ID LL_DMAMUX_REQ_ADC1 LL_DMA_ConfigTransfer(DMA1, DMA_CHANNEL, LL_DMA_DIRECTION_PERIPH_TO_MEMORY | LL_DMA_PRIORITY_HIGH | LL_DMA_MODE_CIRCULAR | LL_DMA_PERIPH_NOINCREMENT | LL_DMA_MEMORY_INCREMENT | LL_DMA_PDATAALIGN_HALFWORD | LL_DMA_MDATAALIGN_HALFWORD); LL_DMA_SetPeriphAddress(DMA1,DMA_CHANNEL,(uint32_t)&(ADC1->DR)); LL_DMA_SetMemoryAddress(DMA1,DMA_CHANNEL,(uint32_t)aAdcValues); LL_DMA_SetDataLength(DMA1,DMA_CHANNEL,sizeof(aAdcValues)/sizeof(uint32_t)); /* Enable the DMA channel */ LL_DMA_EnableChannel(DMA1,DMA_CHANNEL); /* Start conversion with software trigger and enable continuous mode*/ LL_ADC_REG_StartConversionSWStart(ADC1); LL_ADC_REG_SetSequencerContinuousMode(ADC1,LL_ADC_SEQ_CONTINUOUS_ENABLED); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值