IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32 CubeMx(四)ADC采样及简单的均值、中值、众数、卡尔曼滤波方法 -> 正文阅读

[嵌入式]STM32 CubeMx(四)ADC采样及简单的均值、中值、众数、卡尔曼滤波方法

1.ADC采样

1.1 ADC采样原理

我们知道单片机是数字芯片,只认识由0和1组成的逻辑序列,但是我们现实当中有很多模拟的物理量,如温度,这些模拟量该如何被单片机系统处理呢,这就会用到AD转换,AD转换的英文就是Analog to Digital ,由模拟量转化为数字量;而DA,则为Digital to Analog,数字量转化为模拟量。那单片机是如何实现转化的呢?

AD转换芯片上的数据手册上都会告诉你一个信息,这个芯片是8位的,这个芯片是10位,还有12位的,16的。这就代表着单片机AD采样后所能得到的最大值。如何AD采样时8位的那对应的值就为0-255,10位对应的值为0-1023,12位对应的值就为0-4095。对于一个12位AD转换芯片而言,如果输入电压为0,那单片机读到的就是0,如果输入电压是VCC,那单片机读到的就是4095,已经知道了这两个点(0,0),(VCC,4095),根据两点就可以确定一个公式,这时候你就可以求出任意电压值所对应的数字量是多少了

1.2 STM32F4 ADC简介

来自原子哥STM32开发指南HAL库版本。

STM32F4xx 系列一般都有 3 个 ADC,这些 ADC 可以独立使用,也可以使用双重/三重模式(提高采样率)。 STM32F4 的 ADC 是 12 位逐次逼近型的模拟数字转换器。 它有 19 个通道,可测量 16 个外部源、 2 个内部源和 Vbat 通道的信号。 这些通道的 A/D 转换可以单次、连续、扫描或间断模式执行。 ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中。 模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。

ADC 电源要求:全速运行时为 2.4 V 到 3.6 V,慢速运行时为 1.8 V。但是一定别接到 5V 上面去,否则可能烧坏 ADC!
数电小知识: ADC 是12位逐次逼近型模数转换器,输出数值范围是 0 ~ 2^12 -1(0 ~ 4095),满量程是 3.3V ,分辨率就是最低有效位(LSB)的对应输入电压值。分辨率 =3300/4095 ≈ 0.806mV

STM32F407ZGT6 包含有 3 个 ADC。 STM32F4 的 ADC 最大的转换速率为 2.4Mhz,也就是转换时间为 0.41us (在 ADCCLK=36M,采样周期为 3 个 ADC 时钟下得到),不要让 ADC 的时钟超过 36M,否则将导致结果准确度下降。

STM32F4 将 ADC 的转换分为 2 个通道组:规则通道组和注入通道组。规则通道相当于你正常运行的程序,而注入通道呢,就相当于中断。在你程序正常执行的时候,中断是可以打断你的执行的。同这个类似,注入通道的转换可以打断规则通道的转换, 在注入通道被转换完成之后,规则通道才得以继续转换。
在这里插入图片描述
关于模式配置,过于复杂,而且平时基本的使用不会涉及到太多,所以没有做过多理解。

1.3 工程配置

配置工程读取摁键KEY_UP按下时的电压值。
1.开启ADC1的IN1
在这里插入图片描述
可以看ADC的IN1对应的IO口是PA1。
在这里插入图片描述

2.开启串口1来接收读取到的数据。
在这里插入图片描述
3.使能GPIO_PA0。
并将采样通道PA1,接入到PA0。
在这里插入图片描述

2. 滤波代码的编写

对于读取的模拟量肯定要进行滤波,不然模拟量变化过快无法使用。
滤波的作用就是减少噪声与干扰对数据测量的影响。

2.0 重写printf函数

#include “stdio.h”
int fputc(int c,FILE *stream)
{
	uint8_t ch[1]={c};
	HAL_UART_Transmit(&huart1,ch,1,0xFFFF);
	return c;
}

2.1 未添加滤波代码和现象

		uint16_t ADC_value;
		HAL_ADC_Start(&hadc1);//开启ADC1的采样,要放在while中,一直开启
		ADC_value=HAL_ADC_GetValue(&hadc1);//得到采样值
		HAL_Delay(10);//采完样之后加一个小段的延时,防止数据未被记录
		printf("ADC_value = %d\r\n", ADC_value);
		HAL_Delay(500);

串口助手读取到的数据:
在这里插入图片描述
可见没有按键摁下时,依然会读到较高电压值。可能是存在上拉电阻、电磁场干扰或者按键抖动之类的问题干扰读数。
在这里插入图片描述
特别注意: STM32F4 的 ADC 精度貌似不怎么好, ADC 引脚直接接 GND,都可以读到十
几的数值,相比 STM32F103 来说,要差了一些,在使用的时候,请大家注意下这个问题。

在这里插入图片描述
摁下摁键后,也不全读数为4095,可见ADC采样精度一般。

2.2 添加均值滤波和现象

均值滤波的思路就是将一段时间内读取到的数据求和取平均,可以有效的消去抖动。

		uint16_t Last_ADC_Value;
		uint16_t ADC_Value;

		HAL_ADC_Start(&hadc1);//启动adc转化
		Last_ADC_Value = HAL_ADC_GetValue(&hadc1);	
		HAL_Delay(10);//采完样之后加一个小段的延时,防止数据未被记录		
		for(uint8_t i = 10;i>0;i--)
		{
			ADC_Value = HAL_ADC_GetValue(&hadc1);	
			HAL_Delay(10);
			Last_ADC_Value = ADC_Value + Last_ADC_Value;
		}
		Last_ADC_Value = Last_ADC_Value/10;
		printf("ADC_value = %d\r\n", Last_ADC_Value);
		HAL_Delay(500);

串口助手读取到的数据:
在这里插入图片描述
在这里插入图片描述
可以看到均值滤波对接地的情况并没有很好的处理效果。

2.3 添加中值滤波和现象

均值滤波的思路就是取一段时间内读取到的数据中间值,可以有效的消去异常值。

		uint16_t ADC_Value;
		HAL_ADC_Start(&hadc1);	                //启动ADC单次转换
        uint16_t buf[20]={0};
		for(uint8_t i=0;i<20;i++)
		{
			buf[i]=HAL_ADC_GetValue(&hadc1); //读取ADC转换数据
			HAL_Delay(10);
		}
		ADC_Value = buf[10];
		printf("ADC_value = %d\r\n", ADC_Value);
  		HAL_Delay(500);

串口助手读取到的数据:
在这里插入图片描述
在这里插入图片描述
其实看到这,很多人都想到了,无论是接高电平还是接地,这组数据都会有很多的波动,无论是均值滤波还是中值滤波的话,都不能有效的消除这些波动。但通过对这组数据的观察,我们发现接地时零出现的次数较多,接高电平时4095出现的次数较多。
由此,我们很容易想到通过重数滤波来实现效果。

2.4 添加众数滤波和现象

均值滤波的思路就是取一段时间内读取到的数据中出现次数最多的数。

/* USER CODE BEGIN PV */
uint16_t a=0;
uint16_t Most_num[4095]={0}; //数组太大,应该放在全局变量,防止堆栈段溢出
uint16_t i=0;
uint16_t max=0;
/* USER CODE END PV */
while中代码:
		for(i=0;i<20;i++)
		{
			HAL_ADC_Start(&hadc1);	    //启动ADC单次转换
			a=HAL_ADC_GetValue(&hadc1); //读取ADC转换数据 20个数据
			HAL_Delay(10);
			Most_num[a]++;              //读到的数据,其数组中对应的值+1
		}
		max = Most_num[0];						//查找数组中的最大数,并且最大数为出现的次数
		uint16_t k = 0;								//最大数对应的数组序号就是出现次数最多的数
		for(i=0;i<4096;i++)
		{		
			if(max<Most_num[i])
				k = i;		
		}
   	 	printf("ADC_value = %d\r\n", k);
    	HAL_Delay(500);
		for(i=0;i<4095;i++)	//清空数组,防止堆栈段溢出
		Most_num[i]=0;

串口助手读取到的数据:
在这里插入图片描述
在这里插入图片描述
可以看到滤波效果非常好

3.卡尔曼滤波

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-08-10 13:34:55  更:2021-08-10 13:35:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/12 10:15:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码