这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » ADC的过采样技术与STM32F407应用

共3条 1/1 1 跳转至

ADC的过采样技术与STM32F407应用

院士
2026-07-09 14:28:48     打赏

ADC的过采样技术与STM32F407应用

一、核心原理

STM32 ADC过采样是‌用时间换精度‌的低成本技术,利用量化噪声的白噪声特性,对同一信号多次采样后做数学处理,在不更换硬件的前提下提升有效分辨率。

  • 量化噪声整形‌:过采样将量化噪声功率分散到更宽的频带上,通过数字滤波器滤除带外噪声,使带内噪声功率降低 。

  • ‌分辨率提升规律‌:过采样率(OSR)每增加‌4倍‌,理论上可提升‌1 bit‌的有效分辨率(信噪比提高6 dB);若需提升n位分辨率,需进行4n次过采样,对应信噪比提升6dB,理论上可将12位ADC最高提升至16位及以上精度。。

  • ‌简化模拟前端‌:高采样率放宽了对模拟抗混叠滤波器的要求,允许使用过渡带更宽、成本更低的滤波器

二、软硬件实现差异

‌硬件过采样‌:仅STM32G4、H7、L4+等新款系列内置专用过采样器,直接通过寄存器配置即可实现,无需占用CPU资源,支持最高1024倍过采样率。

‌软件模拟过采样‌:F1、F4等老款无硬件单元的系列,可通过DMA连续采集、软件累加后右移的方式实现,效果和硬件方案一致,但会占用部分CPU资源。

三、关键配置要点

  • 开启功能:在CubeMX的ADC设置中,将Oversampling Mode选为ENABLE。

  • 参数匹配:过采样倍率设为4的N次方,右移位数等于要提升的分辨率位数(如16倍过采样对应右移2位,提升2位精度)。

  • 采样时间:可根据信号源阻抗选择1.5~480个ADC周期,高阻抗信号推荐选择更长的采样时间保证采样稳定。

四、STM32F407示例

STM32F407的ADC外设是12bit的采样精度,当我们采集模拟信号时可以利用过采样技术提高采样精度。即利用”每提升1位有效分辨率,过采样率需提高4倍”的规律来配置参数。我们以单ADC独立模式进行采样,在ADCCLK为36MHz、12位分辨率下,单次转换总耗时15个时钟周期,最高采样率可达‌2.4Msps‌,对应转换时间约0.417μs。

4.1 核心参数计算

  • ‌目标提升位数‌:16bit - 12bit = ‌4位‌

  • ‌所需最小过采样率‌:根据公式 OSR = 4^(N-M),代入数值得到 OSR = 4^4 = 256,即每输出1个16bit精度结果,需要采集‌256个原始12bit样本‌。

  • ‌采样率换算‌:原始ADC采样率为2.4MHz,最终输出的有效吞吐率为 2.4MHz / 256 ≈ 9.375kHz,需确保该速率高于被测信号的奈奎斯特频率。

  • 4.2 关键配置步骤

  • ‌硬件采样配置‌

将ADC的原始采样频率设置为目标输出速率的256倍,保证能在一个测量周期内完成256次连续采样。
  • ‌数据处理规则‌

用32位无符号整型变量累加256个12bit原始样本,累加完成后将总和‌右移4位‌(等价于除以16),即可得到等效16bit的高精度结果,避免溢出同时完成分辨率提升。

  • ‌必要前提条件‌

输入信号必须叠加至少1LSB的随机白噪声,让ADC输出码能在相邻数值间随机波动,完全静止的直流信号无法通过该方法提升精度。

4.3 实际效果说明

受ADC本身的微分非线性(DNL)、积分非线性(INL)硬件限制,STM32等主流MCU的12bit ADC通过该方案通常可实现‌15~16位的有效位数(ENOB)‌,接近理论16bit精度水平。

五、使用注意事项

  • 信号本身需要有至少1LSB的随机噪声,否则过采样无法实现精度提升。

  • 过采样会降低输出采样率,倍率越高响应速度越慢,需要平衡精度与实时性需求。

  • 该技术仅能抑制随机量化噪声,无法消除偏移、增益等系统性误差,高精度场景需配合ADC校准流程。

六、示例代码

最后附上HAL库的ADC初始化代码,配置ADC1采集3个通道并通过DMA存入数组。

#include "stm32f4xx_hal.h"

ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;
uint16_t adc_values; // 存储3个通道的结果

void MX_ADC1_DMA_Init(void) {
    // 1. DMA 配置
    __HAL_RCC_DMA2_CLK_ENABLE();
    hdma_adc1.Instance = DMA2_Stream0;
    hdma_adc1.Init.Channel = DMA_CHANNEL_0;
    hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE; // 外设地址固定
    hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;     // 内存地址递增
    hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_adc1.Init.Mode = DMA_CIRCULAR;          // 循环模式
    hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;
    HAL_DMA_Init(&hdma_adc1);
    __HAL_LINKDMA(&hadc1, DMA_Handle, hdma_adc1);

    // 2. ADC 配置
    __HAL_RCC_ADC1_CLK_ENABLE();
    hadc1.Instance = ADC1;
    hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; // 21MHz
    hadc1.Init.Resolution = ADC_RESOLUTION_12B;
    hadc1.Init.ScanConvMode = ENABLE;           // 开启扫描模式
    hadc1.Init.ContinuousConvMode = ENABLE;     // 连续转换
    hadc1.Init.DiscontinuousConvMode = DISABLE;
    hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; // 软件触发
    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    hadc1.Init.NbrOfConversion = 3;             // 3个通道
    hadc1.Init.DMAContinuousRequests = ENABLE;  // 开启DMA连续请求
    HAL_ADC_Init(&hadc1);

    // 3. 配置通道序列
    ADC_ChannelConfTypeDef sConfig = {0};
    
    // 通道 0 (例如 PA0) - Rank 1
    sConfig.Channel = ADC_CHANNEL_0;
    sConfig.Rank = 1;
    sConfig.SamplingTime = ADC_SAMPLETIME_56CYCLES;
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);

    // 通道 1 (例如 PA1) - Rank 2
    sConfig.Channel = ADC_CHANNEL_1;
    sConfig.Rank = 2;
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);

    // 通道 2 (例如 PA2) - Rank 3
    sConfig.Channel = ADC_CHANNEL_2;
    sConfig.Rank = 3;
    HAL_ADC_ConfigChannel(&hadc1, &sConfig);

    // 4. 启动 DMA 和 ADC
    HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_values, 3);
}






关键词: 过采样     ADC     DMA    

工程师
2026-07-09 23:39:02     打赏
2楼

过采样就是利用了抖动。这个抖动的概率分布成就了分辨率提高。


助工
2026-07-10 09:10:19     打赏
3楼

还没有在项目里面使用过“过采样”技术。感觉上,使用软件算法至少可以提升2bit的精度。

有机会我也试试


共3条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]