基于STM32的ADC采样及均值、众数滤波方法实现

本文详细介绍了STM32F103ZET6的ADC配置过程,包括设置SerialWire、启用HSE、配置时钟源和ADC通道,以及实现无滤波直接采样和均值、众数滤波采样。通过对比展示了滤波对ADC采样精度的提升。
摘要由CSDN通过智能技术生成

目录

一 ADC简介

二 STM32CubeMX配置

2.1 Debug设置成Serial Wire

2.2 开启高速外部时钟HSE

2.3 配置时钟源

2.4 配置ADC

2.5 配置串口,方便查看数据。

2.6 生成代码

三、程序编写

3.1 添加头文件

3.2 添加全局变量

 3.3 串口重定向

3.4 ADC采样代码编写

3.4.1 直接采样,不添加滤波

 3.4.2 添加均值滤波方法

 3.4.3 添加众数滤波方法


 

前言:本文的MCU采用STM32F103ZET6,使用CubeMX配置ADC初始化函数。本文实现了直接采样和使用众数滤波采样,通过对比两者的采样值,可以明显看到众数滤波对ADC的采样精度有很大的改善。

一 ADC简介

ADC,中文名称模数转换器。它可以将外部的模拟信号转化成数字信号。使用它去读取IO口上的数值将不再是简单的0或1,而是连续可变的数值。ADC采样就是把随时间连续变化模拟量转换为时间离散模拟量

ADC几个比较重要的参数: 

(1)测量范围:输入范围指的是ADC能够接受的模拟输入信号的电压范围。超出此范围的信号可能会被截断,导致失真。

(2)分辨率:分辨率是ADC输出的二进制位数,它表示ADC可以将输入模拟信号分成多少个离散的级别。假如 ADC 的测量范围为 0-5V,分辨率为12位,那么我们能测出来的最小电压就是 5V除以2 的 12 次方。更高的分辨率通常意味着更精确的采样,但也需要更多的处理能力。

(3)采样速率: 采样速率表示ADC在一秒内采集的样本数。它决定了ADC对模拟信号的采样频率。高采样速率通常有助于捕捉高频信号,但也可能导致更大的数据处理压力。

(4)参考电压: 参考电压是ADC用来比较和量化输入信号的基准电压。稳定的参考电压对于获得准确的ADC输出至关重要。

STM32F103ZET6 系列一般都有 3 个 ADC,这些 ADC 可以独立使用,也可以使用多模式(提高采样率)。 STM32F103ZET6的 ADC 是 12 位逐次逼近型的模拟数字转换器。 

 

二 STM32CubeMX配置


2.1 Debug设置成Serial Wire

不设置可能导致芯片自锁。

6573c2507c074d8eacaefff64ea4f6e7.png

2.2 开启高速外部时钟HSE

56c39fe7c4244e3aaa8dc455644ac9aa.png

2.3 配置时钟源

4c60646f8767419fae1952a0e35b7d6c.png

2.4 配置ADC

选择ADC的通道1,对应的引脚为PA1。

93054985c4a94bec9d920590699ff502.png

2.5 配置串口,方便查看数据。

选择USART1,配置成异步模式,对应的TX为PA9,RX为PA10。

981f7fb873fc4661baf6972ee9ba1273.png

2.6 生成代码

4c8991ade5be4bb191b7152ba0fa4268.png

e6f893a6c86c4705a5b0ae1151547c2d.png

三、程序编写

3.1 添加头文件

#include "stdio.h"

3.2 添加全局变量

float BAT=0;
int32_t AD_BAT=0;
uint16_t Most_data[4096]={0}; //放在全局变量防止堆栈段溢出
uint16_t k = 0;			//出现次数最多的数
uint16_t ii=0;
uint16_t max=0;

 3.3 串口重定向

int fputc(int ch, FILE *f)  //串口重定向
{
	HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF); 	
  	return ch;
}

3.4 ADC采样代码编写

3.4.1 直接采样,不添加滤波

代码如下:

    //开启ADC校准
	HAL_ADCEx_Calibration_Start(&hadc1);
	
	//开启ADC转换
	HAL_ADC_Start(&hadc1);										//first conv
	//等待转换完成
	if(HAL_ADC_PollForConversion(&hadc1, 200)== HAL_OK)
	{
		//获取在当前供电条件下的ADC采样值
		if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
		{
			AD_BAT = HAL_ADC_GetValue(&hadc1);
		}
	}		
    printf("ADC_value = %d\r\n",AD_BAT);
	HAL_ADC_Stop(&hadc1);										//stop conv

得到的采样值如下图,可以看到采样值在较大的范围内波动。

25c5c7ae28e542b688cf9a8ea90ce70c.png

 3.4.2 添加均值滤波方法

选取10次采样值的平均值做为最后的采样值,代码如下。

void ADC_GetValue(void)
{
  int32_t All_AD_BAT=0;
  for(uint8_t i=10;i>0;i--)
  {
	//开启ADC校准
    HAL_ADCEx_Calibration_Start(&hadc1);
	//开启ADC转换
	HAL_ADC_Start(&hadc1);										//first conv
	//等待转换完成
	if(HAL_ADC_PollForConversion(&hadc1, 200)== HAL_OK)
	{
	 //获取在当前供电条件下的ADC采样值
	 if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
	 {
		AD_BAT = HAL_ADC_GetValue(&hadc1);
	 }
												
	}	
	HAL_ADC_Stop(&hadc1);	        //stop conv
    HAL_Delay(1);
	All_AD_BAT += AD_BAT;          		
	}
    AD_BAT=All_AD_BAT/10;		

	BAT=3.3*AD_BAT/4095.0;              //位移传感器输出电压
    printf("ADC_value = %d\r\n",AD_BAT);

}

使用均值滤波得到的电压值相较于没有滤波更加稳定,可以使得到的电压值更加平滑。

 3.4.3 添加众数滤波方法

选取20次采样值中出现次数最多的做为最后的采样值,代码如下。

for(ii=0;ii<20;ii++)
		{
			//开启ADC校准
    	    HAL_ADCEx_Calibration_Start(&hadc1);
			//开启ADC转换
			HAL_ADC_Start(&hadc1);										//first conv
			//等待转换完成
			if(HAL_ADC_PollForConversion(&hadc1, 200)== HAL_OK)
			{
				//获取在当前供电条件下的ADC采样值
				if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
				{
					AD_BAT = HAL_ADC_GetValue(&hadc1);
				}
												
			}	
			HAL_ADC_Stop(&hadc1);	        //stop conv
            HAL_Delay(10);
			Most_data[AD_BAT]++;              //读到的数据,其数组中对应的值+1			
		}			
	
max = Most_data[0];						//查找数组中的最大数,并且最大数为出现的次数
for(ii=0;ii<4096;ii++)
		{		
			if(max<Most_data[ii])
				k = ii;		
		}
   	
for(ii=0;ii<4096;ii++)	//清空数组,防止堆栈段溢出
Most_data[ii]=0;
printf("ADC_value = %d\r\n",k);

得到的采样值如下图,可以看到采样值在很小的范围内波动。

52ba7c558f12404097868e373434536d.png

通过对比,可以看到添加了众数滤波后采样准确度更高了,对小频率的电压异常有很好的效果。

 

 

  • 27
    点赞
  • 83
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

如愿小李

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值