这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » NUCLEO-U083RC学习历程31-STM32ADC过采样及几种ADC采样的

共2条 1/1 1 跳转至

NUCLEO-U083RC学习历程31-STM32ADC过采样及几种ADC采样的处理方法

助工
2025-02-17 10:47:35     打赏

    对于STM32内部ADC采集时候,难免会受到外部干扰的,导致数据不稳定情况。一般在实际使用过程中,我们就需要对增加采样次数来提高分辨率的技术。而STM32cube MX 软件自带过采样的功能。下面就和大家介绍一下STM32如何使用软件配置过采样的功能,从而实现数据的稳定性。

    下面和大家具体分享一下软件配置步骤和注意事项:

一:过采样的基本知识分享:

1.1 基本的原理:使用STM32通过多次采取ADC的数据,并对结果进行取平均值处理,提高有效分辨率。每增加4倍的采样次数,分辨率可提高1位;我们在实际的使用过程中,可以根据自己的需求进行设置和更改。

二:软件配置步骤

2.1 配置ADC

选择ADC通道:确定要采样的模拟输入通道。

设置采样时间:根据信号特性调整采样时间。

配置ADC分辨率:通常设置为12位。

2.2 配置过采样

设置过采样比率:例如16倍过采样。

设置右移位数:根据过采样比率调整,如16倍过采样需右移2位。

2.3 启动ADC

启动转换:ADC开始采样并存储结果。

等待转换完成:通过轮询或中断方式检查转换状态。

2.4 读取和处理数据

读取ADC数据:从数据寄存器获取采样值。

计算平均值:对多次采样结果取平均,得到最终值。

STM32 cube MX 软件配置如下:

0217-1.png

主要代码如下所示:

    /* Start ADC group regular conversion */
    if (HAL_ADC_Start(&hadc1) != HAL_OK)
    {
      /* ADC conversion start error */
      Error_Handler();
    }
    /* Wait for ADC conversion completed */
    if (HAL_ADC_PollForConversion(&hadc1, 10) != HAL_OK)
    {
      /* End Of Conversion flag not set on time */
      Error_Handler();
    }                                          */
    uhADCxConvertedData_OVS_ratio16_shift4 = HAL_ADC_GetValue(&hadc1);
    HAL_ADC_Stop(&hadc1);
    hadc1.Init.OversamplingMode = ENABLE;
    hadc1.Init.Oversampling.Ratio = ADC_OVERSAMPLING_RATIO_16;
    hadc1.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_NONE;
    if (HAL_ADC_Init(&hadc1) != HAL_OK)
    {
      Error_Handler();
    }
    /* Start ADC group regular conversion */
    if (HAL_ADC_Start(&hadc1) != HAL_OK)
    {
      /* ADC conversion start error */
      Error_Handler();
    }
    if (HAL_ADC_PollForConversion(&hadc1, 10) != HAL_OK)
    {
      /* End Of Conversion flag not set on time */
      Error_Handler();
    }
    uhADCxConvertedData_OVS_ratio16_shift0 = HAL_ADC_GetValue(&hadc1);
    HAL_ADC_Stop(&hadc1);
    hadc1.Init.OversamplingMode = DISABLE;
    if (HAL_ADC_Init(&hadc1) != HAL_OK)
    {
      Error_Handler();
    }
    if (HAL_ADC_Start(&hadc1) != HAL_OK)
    {
      /* ADC conversion start error */
      Error_Handler();
    }
    if (HAL_ADC_PollForConversion(&hadc1, 10) != HAL_OK)
    {
      /* End Of Conversion flag not set on time */
      Error_Handler();
    }                                        */
    uhADCxConvertedData_OVS_disabled = HAL_ADC_GetValue(&hadc1);
   
    HAL_ADC_Stop(&hadc1);
    hadc1.Init.OversamplingMode = ENABLE;
    hadc1.Init.Oversampling.Ratio = ADC_OVERSAMPLING_RATIO_16;
    hadc1.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_4;
    if (HAL_ADC_Init(&hadc1) != HAL_OK)
    {
      Error_Handler();
    }
    /* Data value should not exceed range resolution 12 bits */
    if ((uhADCxConvertedData_OVS_ratio16_shift4 > __LL_ADC_DIGITAL_SCALE(LL_ADC_RESOLUTION_12B)) ||
        (uhADCxConvertedData_OVS_disabled > __LL_ADC_DIGITAL_SCALE(LL_ADC_RESOLUTION_12B)))
    {
      /* Error: Data not valid */
      Error_Handler();
    }
    /* Data value should not exceed range of resolution 16 bits */
    if (uhADCxConvertedData_OVS_ratio16_shift0 > 0xFFFF)
    {
      /* Error: Data not valid */
      Error_Handler();
    }
    if (fConvertedData_OVS_EquivalentValue12bits > __LL_ADC_DIGITAL_SCALE(LL_ADC_RESOLUTION_12B))
    {
      /* Error: Data not valid */
      Error_Handler();
    }

ADC 配置为在单转换模式下从 SW 触发器转换单通道。ADC 过采样功能与 3 个设置一起使用:

第一步:启用 ADC 过采样:比率 16,位右移 4。

第二步:启用 ADC 过采样:比率 16,无位元右移。

第三步:禁用 ADC 过采样。

程序循环执行,上述步骤代码;

示例执行:

在主程序执行中,ADC 组使用 3 个过采样设置定期连续转换所选通道。

然后,对数据进行评估:

数据范围有效性检查

用户可以评估过采样的预期结果:启用过采样的 ADC 转换数据比禁用过采样的 ADC 转换数据的变化更小。

对 16 位的过采样转换数据进行软件计算,以获得相当于浮点分辨率 12 位的精确数据。

程序仿真效果如下所示:

0217-2.png

注意事项:

噪声水平:过采样适用于噪声较大的信号。

采样时间:确保采样时间足够捕获信号。

时钟频率:ADC时钟频率需满足过采样要求。

项目总结:

STM32 ADC过采样通过增加采样次数提高分辨率,适用于需要高精度但硬件分辨率不足的场景。合理配置过采样比率和右移位数是关键。

几种常用得滤波算法分享:

1:一阶互补滤波算法:

取值:k = 0-1,本次取值滤波结果 =(1-K),本次采样值需要加上上次滤波得结果数据

代码如下所示:

int firstdatadeal(int CurrValue, int lastValue, float K)
{    return K * CurrValue + (1-K) * lastValue;}

从代码中,我们可以看到该种滤波算法还是有很大得弊端的,效果比较一般,对于高精度的场合不建议使用。

2: 采用中值算法滤波

主要是程序在执行的时候,连续采集N次(需要注意下这里下,这里的N必须取值奇数),程序需要按大到小或者从小到达的顺序进行排序,然后取中间数值做为有效值。

代码如下:

int MidValueDeal(int N)
{      
    int value_buf[N];      int i,j,k,temp;      
    for( i = 0; i < N; ++i)      
    {        
     value_buf[i] = HAL_ADC_GetValue(&hadc1);  
    }
      for(j = 0 ; j < N-1; ++j)      
      {          
          for(k = 0; k < N-j-1; ++k)          
          {              //从小到大排序,冒泡法排序              
              if(value_buf[k] > value_buf[k+1])              
              {                
                  temp = value_buf[k];                
                  value_buf[k] = value_buf[k+1];                
                  value_buf[k+1] = temp;              
              }          
          }      
      }
      return value_buf[(N-1)/2];
  }

可以有效的去除数据因为外界干扰引起的数据的波动,对一些大滞后系统:比如温度、液位等变化缓慢的有良好的滤波效果,上述代码可以有效消除异常数据和平稳变化的采样值效果比较好;

3:算术平均数滤波

连续取值N个数据,对所有的数据进行取平均值;

代码如下:

int AverValueDeal(int N)
{    
    int sum = 0;     
    unsinged short i;    
    for(i = 0; i < N; ++i)     
    {        
        sum += HAL_ADC_GetValue(&hadc1);      
    }     
    return sum/N;
}

这里取值时候,需要根据被控对象进行选择,N值取值过大,会导致响应过慢,数据的灵敏度过低,所以采用算术平均值滤波时候,需要我们格外的注意;

4:滑动滤波算法

把连续取N个采样值看成一个队列,队列的长度固定为N。每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据(先进先出原则)。把队列中的N个数据进行算术平均运算,就可获得新的滤波结果;

#define N 10
int value_buf[N];
int sum=0; //数据总和
int Num=0; //当前队列中数组下标
int movedataFilter()
{      
    if(Num < N)      
    {          
        value_buf[Num] = HAL_ADC_GetValue(&hadc1);          
        sum += value_buf[Num];          
        Num++;          
        return sum/Num;      
    }      
    else      
    {          
       sum -= sum/N;          
       sum += HAL_ADC_GetValue(&hadc1);          
       return sum/N;      
    }
}

好了,几种常用的滤波算法,已经和大家分享完毕,欢迎大家相互讨论。




关键词: NUCLEO-U083RC     过采样功能     其他方法采    

院士
2025-02-17 23:26:52     打赏
2楼

这内容可是真丰富呀!

想了解过采样的小伙伴们赶紧来呀


共2条 1/1 1 跳转至

回复

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