1、准备材料

开发板(正点原子stm32f407探索者开发板V2.4

ST-LINK/V2驱动

STM32CubeMX软件(Version 6.10.0

keil µVision5 IDE(MDK-Arm

CH340G Windows系统驱动程序(CH341SER.EXE

XCOM V2.6串口助手

3个滑动变阻器

2、实验目标

使用STM32CubeMX软件配置STM32F407开发板的ADC实现ADC多通道DMA采集,具体为使用ADC_IN5/6/7三个通道进行DMA连续ADC转换

3、实验流程

3.0、前提知识

“STM32CubeMX教程13 ADC - 单通道转换”实验中提到过,规则通道只有一个16位的数据寄存器,因此规则通道同时只能转换一个ADC通道,而且每次转化完一个ADC通道就需要及时从数据寄存器中取出转化的数据,否则会被后面转化完毕的通道数据覆盖

这个时间非常短,一般不采用像单通道转化中使用中断提取处理每个单通道数据的方法,而是采用DMA连续转化的方法,将多通道转化完毕之后,在DMA的数据存储中将采集到的所有通道的数据一起处理

ADC是利用片上的模数转换器将外部的模拟量转化为数字量存储到内存中,数据传输方向应该只有从外设到内存这一种方向,因此可知ADC的DMA方向也只有外设到内存一种

从“STM32CubeMX DMA 直接内存读取”实验中可知ADC1的DMA通道有DMA2_Stream0 CH0 和 DMA2_Stream4 CH0 两个通道

ADC的DMA请求模式一般选择循环模式,在多通道ADC采集时,配合使能扫描转化模式,这样就可以连续转化多通道而不停止

由于ADC采集后的数据一般需要存储在内存中,因此在选择地址递增时,ADC外设地址不增加,内存地址选择递增

使用HAL_ADC_Start_DMA()以DMA方式启动ADC采集时需要指定存储的内存首地址,从函数的定义可知其为uint32_t*类型,因此在DMA配置时我们需要选择的数据宽度为字Word

3.1、CubeMX相关配置

3.1.0、工程基本配置

打开STM32CubeMX软件,单击ACCESS TO MCU SELECTOR选择开发板MCU(选择你使用开发板的主控MCU型号),选中MCU型号后单击页面右上角Start Project开始工程,具体如下图所示

开始工程之后在配置主页面System Core/RCC中配置HSE/LSE晶振,在System Core/SYS中配置Debug模式,具体如下图所示

详细工程建立内容读者可以阅读STM32CubeMX教程1 工程建立

3.1.1、时钟树配置

系统时钟使用8MHz外部高速时钟HSE,HCLK、PCLK1和PCLK2均设置为STM32F407能达到的最高时钟频率,具体如下图所示

3.1.2、外设参数配置

本实验需要需要初始化USART1作为输出信息渠道,具体配置步骤请阅读“STM32CubeMX教程9 USART/UART 异步通信

设置TIM3通用定时器溢出时间100ms,外部触发事件选择更新事件,参数详解请阅读“STM32CubeMX教程6 TIM 通用定时器 - 生成PWM波”实验,具体配置如下图所示

在Pinout & Configuration页面左边功能分类栏目Analog中单击其中ADC1,勾选IN5/6/7三个通道,在下方的参数设置中以ADC - 单通道转换实验为模板修改部分参数

Scan Conversion Mode :使能扫描转换模式,因此现在需要转换5/6/7三个通道,因此使能该模式之后,在规则通道转换为其中一个通道后就会接收转换下一个通道

DMA Continuous Requests :使能DMA连续转换请求,该参数的使能需要在配置完DMA请求之后才可选,配合参数 Scan Conversion Mode 可以实现连续不间断的对三个通道数据进行采集

End Of Conversion Selection :选择EOC flag at the end of all conversions,该参数表示当转换完毕一组ADC中的所有通道之后再产生EOC标志,进入中断

Number Of Conversion :规则通道转换数量现在为3,对应三个不同的通道,通道转换顺序及每个通道的采样时间由Rank及其下参数决定

具体参数配置如下图所示

单击Configuration中的DMA Settings选项卡对ADC1的DMA请求进行设置,单击ADD按键增加DMA请求,这里可选的只有一个ADC1

选择想要使用的DMA Stream,并设置优先级,将DMA请求模式设置为循环模式,外设地址不增加,内存地址递增,数据宽度选择字Word

为何如此配置?

请阅读本实验“3.0、前提知识”

如下图所示为ADC1的DMA请求具体设置

3.1.3、外设中断配置

在Pinout & Configuration页面左边System Core/NVIC中勾选DMA2 Stream0 全局中断,然后选择合适的中断优先级即可

注意这里没有勾选ADC1/2/3的全局中断,因为外设DMA中断使用的回调函数和外设本身中断的回调函数一般是同一个回调函数(为什么?请阅读本实验3.2.2小节),如果同时开始两者中断可能会导致重复进入中断函数

但是有些外设使用DMA时必须开启自身的中断,不同外设情况不一样

建议在外设使用DMA时,尽量不开启外设全局中断,必须开启的可以禁用外设主要事件源产生的硬件中断 (注释1)

上述步骤如下图所示

3.2、生成代码

3.2.0、配置Project Manager页面

单击进入Project Manager页面,在左边Project分栏中修改工程名称、工程目录和工具链,然后在Code Generator中勾选“Gnerate peripheral initialization as a pair of 'c/h' files per peripheral”,最后单击页面右上角GENERATE CODE生成工程,具体如下图所示

详细Project Manager配置内容读者可以阅读“STM32CubeMX教程1 工程建立”实验3.4.3小节

3.2.1、外设初始化调用流程

首先在生成的工程主函数main()中调用MX_DMA_Init()函数对ADC1用到的DMA时钟及其流的中断进行了配置

然后调用MX_ADC1_Init()函数对ADC1的基本参数、通道和通道参数进行了配置,并调用了HAL_ADC_Init()使用配置的参数初始化了ADC1

在初始化函数HAL_ADC_Init()中又调用了HAL_ADC_MspInit()函数,在该函数中使能了ADC1/GPIOA的时钟,对ADC1_IN5/6/7的输入引脚做了复用设置,然后对ADC1的DMA参数配置并进行了初始化,最后调用了__HAL_LINKDMA(adcHandle,DMA_Handle,hdma_adc1)将adc1外设与DMA流对象关联

具体的ADC DMA初始化调用流程如下图所示

3.2.2、外设中断调用流程

CubeMX中勾选DMA2_Stream0的全局中断后,会在stm32f4xx_it.c中增加DMA的中断服务函数DMA2_Stream0_IRQHandler()

在中断服务函数DMA2_Stream0_IRQHandler()中调用了HAL库的DMA全局中断处理函数,该函数中根据各种标志判断DMA传输完成/失败/一半完成等事件,然后根据不同的事件调用不同的回调函数,这里DMA传输完成之后调用了hdma->->XferCpltCal1back()

上述过程如下图所示

这个函数指针在以DMA方式启动ADC采集时被指向DMA传输完成回调ADC_DMAConvCplt()函数

在该DMA传输完成回调ADC_DMAConvCplt()函数中最终调用了ADC采集完成回调HAL_ADC_ConvCpltCallback()函数,该函数上一个实验我们重新实现过

上述过程如下图所示

之前所有的外设回调函数都是直接调用了HAL库提前准备好的虚函数,比如ADC的采集完成回调函数HAL_ADC_ConvCpltCallback(),用户直接实现该虚函数即可

但是DMA不是一个外设,而是数据传输手段,大多数外设都可以使用,因此DMA的各种事件回调函数不是一个真正的函数,而是一个函数指针

当我们以DMA传输的方式启动某个外设的时候,就会将该外设对应事件的中断服务函数地址赋值给对应事件DMA中断回调函数指针

3.2.3、添加其他必要代码

在主函数中以DMA的方式启动ADC采集传输,然后启动ADC1的触发源TIM3定时器,具体代码如下图所示

在adc.c中重新实现DMA传输完成回调函数,在该函数中取出ADC转换完成的三通道采集值,然后处理并通过串口输出,具体代码如下图所示

一些定义及函数源代码如下

/*main.c中的全局变量定义*/
uint32_t DataBuffer[BATCH_DATA_LEN]; /*main.h中的变量外扩及宏定义*/
#define BATCH_DATA_LEN 3
extern uint32_t DataBuffer[BATCH_DATA_LEN]; /*DMA转换完成中断回调*/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
/*定时器DMA启动多通道转换*/
uint32_t val=0,Volt=0;
for(uint8_t i=0;i<BATCH_DATA_LEN;i++)
{
val=DataBuffer[i];
Volt=(3300*val)>>12;
printf("ADC_IN%d, val:%d, Volt:%d\r\n",i+5,val,Volt);
}
printf("\r\n");
}

4、常用函数

/*以DMA方式启动ADC采集*/
HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef *hadc, uint32_t *pData, uint32_t Length) /*结束以DMA方式启动的ADC采集*/
HAL_StatusTypeDef HAL_ADC_Stop_DMA(ADC_HandleTypeDef *hadc)

5、烧录验证

烧录程序,单片机上电之后,串口不断的输出三个通道的ADC采集值,笔者将三个滑动变阻器按照通道5、通道6和通道7的顺序,分别从一端缓慢拧到另一端,可以从串口输出的数据看到,通道5/6/7三个通道采集到的ADC数据从最大4095慢慢变到最小值0

6、注释详解

注释1:详细内容请阅读STM32Cube高效开发教程(基础篇)14.5.1小节内容

更多内容请浏览 STM32CubeMX+STM32F4系列教程文章汇总贴

STM32CubeMX教程14 ADC - 多通道DMA转换的更多相关文章

  1. STM32 ADC多通道转换DMA模式与非DMA模式两种方法(HAL库)

    一.非DMA模式(转) 说明:这个是自己刚做的时候百度出来的,不是我自己做出来的,因为感觉有用就保存下来做学习用,原文链接:https://blog.csdn.net/qq_24815615/arti ...

  2. stm32 ADC模数转换 ADC多通道 ADC DMA

    通过调节电位器,改变AD转换值和电压值 STM32F1 ADC 配置步骤 1.使能GPIO时钟和ADC时钟 2.配置引脚模式为模拟输入 3.配置ADC的分频因子 4.初始化ADC参数,ADC_Init ...

  3. STM32 ADC多通道转换

    描述:用ADC连续采集11路模拟信号,并由DMA传输到内存.ADC配置为扫描并且连续转换模式,ADC的时钟配置为12MHZ.在每次转换结束后,由DMA循环将转换的数据传输到内存中.ADC可以连续采集N ...

  4. STM32L0开发——ADC多通道采集,IDE和IAR开发注意事项

    keil开发L0系列是免费的,官方提供许可的.因此建议Keil开发,L011F3由于flash只有8K,因此不建议HAL库,建议使用cubemx+LL(或snippets库).0.起初,可以参考官方库 ...

  5. STM32—ADC多通道采集电压

    文章目录 ADC详解 程序说明 函数主体 引脚配置 ADC和DMA配置 主函数 ADC详解 前面的博客中详细介绍了STM32中ADC的相关信息,这篇博客是对ADC内容的一个总结提升,ADC的详细介绍: ...

  6. Hi3518EV200平台ADC多通道采样

    Hi3518EV200平台ADC多通道采样流程 Hi3518EV200 ADC 本文针对Hi3518EV200平台处理器,通过ADC单次采样方式,实现对多通道(1~4通道)ADC进行采样控制.本文仅仅 ...

  7. STM32使用HAL库实现ADC单通道转换

    STM32的ADC转换还是很强大的,它具有多个通道选择,这里我就不细说,不了解的可以自行百度,这里只是选取单通道,实现ADC转换.在文章开始之前,我说一下数据左对齐跟右对齐的差别,以前一直糊里糊涂的, ...

  8. AIR32F103(六) ADC,I2S,DMA和ADPCM实现录音播放功能

    目录 AIR32F103(一) 合宙AIR32F103CBT6开发板上手报告 AIR32F103(二) Linux环境和LibOpenCM3项目模板 AIR32F103(三) Linux环境基于标准外 ...

  9. [SQL基础教程]1-4 SQL 表的创建

    [SQL基础教程]1-4 SQL 表的创建 创建数据库 语法 CREATE DATABASE <数据库名称> // example CREATE DATABASE shop; 创建表 语法 ...

  10. [译]Vulkan教程(14)图形管道基础之固定功能

    [译]Vulkan教程(14)图形管道基础之固定功能 Fixed functions 固定功能 The older graphics APIs provided default state for m ...

随机推荐

  1. 轻松掌握组件启动之MongoDB(下):高可用复制集架构环境搭建

    引言 上一章节中,我们详细介绍了在典型的三节点复制集环境中搭建MongoDB的步骤和注意事项.从准备配置文件到启动MongoDB进程,我们一步步指导读者完成了环境的设置.在本章节中,我们将进一步深入, ...

  2. Sell Pigs 题解

    Sell Pigs 双倍经验 题目大意 有 \(n\) 个顾客前来买猪,共有 \(m\) 个猪圈,每个顾客携带着某一些猪圈的钥匙,需要买一定数量的猪.在顾客买完后,我们可以将打开的猪圈中的猪随意移动, ...

  3. 线程的查看方式&运行原理

    观察多个线程同时运行 主要是理解 交替执行 谁先谁后,不由我们控制 查看进程线程的方法 windows 任务管理器可以查看进程和线程数,也可以用来杀死进程 tasklist 查看进程 taskkill ...

  4. sizeof结构体数组指针和sizeof数组指针的区别

    请思考一下 以下代码输出的 sizeof 分别是多少? #include <stdio.h> typedef struct { char name[100]; unsigned char ...

  5. Java笔记——数组静态初始化开始

    一维数组: 静态初始化: 定义格式:(1)数据类型[] 数组名 = new 数组类型[] (2)数组类型[] 数组名 ={元素1,元素2,.....} 练习:数组元素逆序: public static ...

  6. 从源码分析 Redis 异步删除各个参数的具体作用

    以前对异步删除几个参数的作用比较模糊,包括网上的很多资料都是一笔带过,语焉不详. 所以这次从源码(基于 Redis 7.0.5)的角度来深入分析下这几个参数的具体作用: lazyfree-lazy-u ...

  7. python内置模块——logging

    内置模块-logging loging模块是python提供的内置模块,用来做日志处理. 日志等级: 等级 释义 级别数值 CRITICAL(fatal) 致命错误,程序根本跑不起来 50 ERROR ...

  8. windows中MySQL忘记密码

    前言:   一直都是连接公司项目数据库,许久未连接本地的数据库,密码忘记了 步骤: 进入本机安装mysql的bin目录下 暂停mysql服务 net stop mysql 设置跳过密码授权登录  my ...

  9. C语言所有运算符及优先级、结合性

    C 语言所有运算符及优先级.结合性 参考:<C Primer Plus 第六版> Tip:有关优先级.结合性的表格在最后面. [1]算数运算符 '+'("加号")(二元 ...

  10. 使用CompletableFuture实现多个异步任务并行完成后合并结果

    业务场景 需要同时从多个副本数据库中查询数据,并对查询结果进行合并去重处理后返回前端. 实现过程涉及多数据源切换,这里不作过多讨论. 编码实现 实现过程: 1.定义异步查询数据方法: 2.通过Comp ...