首页 > 其他分享 >STM32 f407 多通道ADC采集+DMA传输 基于HAL库和Cubemx配置

STM32 f407 多通道ADC采集+DMA传输 基于HAL库和Cubemx配置

时间:2024-09-28 13:50:33浏览次数:3  
标签:DMA HAL 多通道 滤波 adc3 ADC3 ADC

在实际应用中ADC往往是要和DMA一起使用的,DMA将ADC转换值放入预设好的变量中,该过程不占用CPU资源,需要读取ADC输入时再让CPU读取变量即可。

下面记录使用cubemx配置多通道ADC采集的具体流程,并编写对ADC采样值进行滤波的程序(选择开发板、开启外部时钟和SW调试接口、Project Manager设置相关操作略过)

1.选择要使用的ADC和对应通道

f407内部ADC资源如下,我们选择ADC3的通道10、11、12、13进行ADC采集

图片来源29. ADC—电压采集 — [野火]STM32 HAL库开发实战指南——基于野火F4系列开发板 文档

在cubemx中选择

2.配置ADC参数

Scan Conversion Mode:如果是单通道转换设置为DISABLE,如果是多通道AD转换设置为ENABLE;

Continuous Conversion Mode:配置是启动自动连续转换还是单次转换。选择ENABLE配置为使能自动连续转换,如果是DISABLE则配置为单次转换,转换一次后停止需要手动控制才重新启动转换;

Number of Conversion:进行规则组的通道配置。如果没有特殊需要把所有的通道都放在规则组即可,这里使用了4个通道就把number of conversion设置为4,并把channel分配到每一个RANK

Sampling Time:越大则ADC结果越准确。由于我们使用了DMA,采样时并不需要CPU等待,所以这里的耗时几乎对程序没什么影响。而ADC转换精度是我们很在意的,所以直接将其设为最大的480时钟周期。

DMA Continuous Requests:选择Enable,开启DMA传输(在没有分配DMA时是不可以Enable的,进行完3再来设置)。

3.配置DMA

点击Add添加ADC3的DMA传输通道,并将Mode设置为周期模式即可(即不断的将ADC转换值搬运到指定区域)

4.生成代码,开启DMA传输

首先DMA需要一个目的地,即把ADC转换的结果往哪个变量中搬运,所以我们先创建一个变量用于储存ADC搬运的结果。由于我们还要对ADC转换值进行平均滤波,所以这里把计算过程中需要的变量全部创建了,并保存在结构体ADC3_sampling中

#define Filter_width 30	
typedef struct
{
	uint8_t adc_count;
	uint16_t adc3_dma_storage[4*Filter_width];   
	uint32_t adc3_sum_A1, adc3_sum_A2, adc3_sum_A3, adc3_sum_A4;
	uint16_t adc3_average_A1, adc3_average_A2, adc3_average_A3, adc3_average_A4;
	uint32_t time;
}ADC3_SAMPLING;
extern ADC3_SAMPLING ADC3_sampling;

由于我们的结构体ADC3_sampling在main中定义,而我们要把滤波函数写到adc对应的文件中,所以用extern声明。filter width是我们定义的滤波器宽度

ADC转换值储存只能使用uint16_t数据类型!不然DMA搬运时会混乱!

PS:由于滤波是对adc采样值的处理,只与adc相关的函数就放到adc文件中,这样做是为了整个工程更有条理。而把变量定义到main中是为了后续的调试方便,可以在main中就看到所有的变量

开启DMA传输(注意要MX_ADC3_Init()的后面)

HAL_ADC_Start_DMA(&hadc3, (uint32_t *)ADC3_sampling.adc3_dma_storage, 4*Filter_width);

5.对采样值进行滤波

在我的实际项目中,虽然Sampling Time已被设为480,但不进行滤波的话ADC每次的采样值任然存在很大偏差,所以进行滤波是必要的。

首先重定义HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc),该函数在DMA将ADC转换结果传输完成时被调用。然后在回调函数中进行滤波操作。

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{	
    for(uint8_t i=0; i<30; i++)
	{
		// 计算累计值
		ADC3_sampling.adc3_sum_A4 += ADC3_sampling.adc3_dma_storage[4*i];
		ADC3_sampling.adc3_sum_A3 += ADC3_sampling.adc3_dma_storage[4*i+1];
		ADC3_sampling.adc3_sum_A2 += ADC3_sampling.adc3_dma_storage[4*i+2];
		ADC3_sampling.adc3_sum_A1 += ADC3_sampling.adc3_dma_storage[4*i+3];
	}
	// 计算均值
	ADC3_sampling.adc3_average_A4 = 0.8057 * ADC3_sampling.adc3_sum_A4/Filter_width;
	ADC3_sampling.adc3_average_A3 = 0.8057 * ADC3_sampling.adc3_sum_A3/Filter_width;
	ADC3_sampling.adc3_average_A2 = 0.8057 * ADC3_sampling.adc3_sum_A2/Filter_width;
	ADC3_sampling.adc3_average_A1 = 0.8057 * ADC3_sampling.adc3_sum_A1/Filter_width;
	// 累计值清零以待下次计算		
	ADC3_sampling.adc3_sum_A4 = 0;
	ADC3_sampling.adc3_sum_A3 = 0;
	ADC3_sampling.adc3_sum_A2 = 0;
	ADC3_sampling.adc3_sum_A1 = 0;
}

注意0.8057是3300/4096得来的。分别代表3.3V和2^12

6.总结

很多教程喜欢从HAL_ADC_Start()和HAL_ADC_Start_IT()开始教,这样虽然能让理论知识理解的更加充分,但我觉得不是很有必要。因为其实HAL_ADC_Start_DMA ()内部的实现中是调用了HAL_ADC_Start_IT()的,用多了遇到问题多了自然就会去看内部实现了,然后自然而然就明白了。至于HAL_ADC_Start()这种阻塞式实现,完全不会用的到。

先会用,再精通!

补充:根据后续测试,采样4通道的数据30组并搬运耗时约2.8ms(CPU不参与),而滤波占用CPU的时间非常小,几乎可以忽略不计(小于10微秒)。应用时可以对滤波语句加上条件判断(比如设置标志位10ms进行一次ADC采样值滤波),整个ADC采样过程就几乎无感实现。

标签:DMA,HAL,多通道,滤波,adc3,ADC3,ADC
From: https://blog.csdn.net/weixin_57904199/article/details/142610365

相关文章

  • STM32 f407 多通道PWM输出 基于HAL库和Cubemx配置
    STM32PWM的相关理论知识可以参考江科大的视频教程,或者正点和野火的HAL库开发手册,以下是相关链接:[6-4]PWM驱动LED呼吸灯&PWM驱动舵机&PWM驱动直流电机_哔哩哔哩_bilibili31.TIM—高级定时器—[野火]STM32HAL库开发实战指南——基于野火F4系列开发板文档下面记录一下使......
  • Android CCodec Codec2 (十五)C2DmaBufAllocator
    Codec2框架采用了全新的Buffer分配机制C2Allocator,这一篇文章我们一起来瞧瞧C2DmaBufAllocator是如何工作的。1、C2AllocatorC2Allocator声明在C2Buffer.h中,它定义了如下接口:getName:返回Allocator独一无二的名称;getId:返回Allocator独一无二的id;getTraits:返回Allocator......
  • 告别XP系统HAL.DLL错误:详解修复工具使用步骤与技巧
    在WindowsXP操作系统中,HAL.DLL(硬件抽象层DLL)是一个至关重要的系统文件,它负责操作系统与硬件之间的交互。当HAL.DLL文件丢失、损坏或无法被系统正确识别时,系统可能会无法启动,并显示错误信息,如“缺少或损坏<Windows根目录>\system32\hal.dll”。针对这一问题,虽然直接名为“XP系......
  • 【C#】Halcon显示图像(读文件路径、缓存、创建空白图像)
    publicHTuplehv_ExpDefaultWinHandle;//输入图像宽高Int64Input_Image_Width=0,Input_Image_Height=0;///<summary>///加载图像///</summary>///<paramname="type">类型,0:内存地址;1:文件路径;2:图像;3:空白图像</param>///......
  • 题解:CF1799F Halve or Subtract
    \(\text{Link}\)介绍一下一种高维wqs的方法。此方法来自@YeahPotato的专栏严谨的WQS二分方法。题意给定一个长为\(n\)的序列\(v_{1\dotsn}\),三个常数\(d,a,b\)。你可以执行若干次以下两种操作:选择\(1\lei\len\),令\(v_i\gets\lceil\frac{v_i}{2}\rceil\)。......
  • STM32CubeMX+usart+DMA+Modbus从机
    前言单片机型号STM32f103zet6使用USART1串口来实现DMA收发使用DMA1通道5,来传输USART1接收的数据使用DMA1通道4,来传输USART1发送的数据实现了Modbus从机协议(03和06功能)1.准备工作modbuspoll和modbusslave模拟软件下载链接:https://pan.baidu.com/s/1cX8HC-rm3gsM......
  • 用Podman搭建LAMP开发环境的容器(六) -- 使用普通用户
    上接:用Podman搭建LAMP开发环境的容器(五)–端口转发现在这个容器还是直接用root用户跑的。虽然说如果只是开发环境的话,而且是一个虚拟机容器,直接用root用户工作应该也问题不大。不过我还是想在一般情况下用普通用户。首先我要改containerfile文件的脚本,来创建一个普通......
  • STM32驱动1.3寸(0.96寸)OLED显示屏 #基于HAL库#软件IIC通讯
    前言  本文用作记录基于HAL库搭建起来的软件IIC驱动OLED显示器。一、软件IIC原理  只需理解两点:1.IIC是一种通信总线,物理层面用于单片机与OLED的通信。2.软件IIC即模拟硬件IIC的引脚时序,可以灵活配置引脚。IC物理接口:IIC串行总线有两根信号线,一根是双向的数据线SDA,另......
  • 【BUAA S4 OS】Lab4challenge sigaction实现
    文章目录sigaction简介任务描述数据结构、宏等设计信号相关设置Env结构体添加成员错误返回值设置头文件中添加相关函数声明初始化与全局变量设置相关前置操作新增相关系统调用统一流程新增功能实现所需系统调用的具体实现信号处理流程实现信号处理的触发各类信号的发送......
  • 基于旗芯微FC4150系列的DMA详解
    1.概述DMA的中文名称是直接内存访问,它不需要CPU的参与,实现数据传输的技术(但是也会占用总线带宽,所以有时候使用DMA虽然会降低CPU负载,但提高访问数据速度并不高)。1.1旗芯微FC4150系列芯片DMA特征·所有数据的传输都是从源地址写入到目标地址,源地址和目标地址以及传输大小都是......