STM32CubeMX教程13 ADC - 单通道转换

目录

1、准备材料

2、实验目标

3、ADC概述

4、实验流程

4.0、前提知识

4.1、CubeMX相关配置

4.1.1、时钟树配置

4.1.2、外设参数配置

4.1.3、外设中断配置

4.2、生成代码

4.2.1、外设初始化调用流程

4.2.2、外设中断调用流程

4.2.3、添加其他必要代码

5、常用函数

6、烧录验证

6.1、实验具体流程

6.2、实验现象

7、软件触发ADC采集

8、注释详解

参考资料


1、准备材料

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

STM32CubeMX软件(Version 6.10.0)

野火DAP仿真器

keil µVision5 IDE(MDK-Arm)

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

XCOM V2.6串口助手

1个滑动变阻器

2、实验目标

使用STM32CubeMX软件配置STM32F407开发板的ADC实现单通道ADC采集,具体为使用ADC1_IN5通道通过软件/定时器触发采集滑动变阻器上的分压

3、ADC概述

ADC即模拟数字转换,是将模拟电压量转换为数字量的一种手段,如下图所示为STM32F407单个ADC的结构框图(注释1),其主要包括5个部分,分别为①ADC电源引脚、②ADC输入引脚、③ADC触发源、④ADC转换规则和⑤ADC中断触发,下面从这五个方面分别介绍STM32F407的ADC

①ADC电源引脚有VDDA、VSSA、VREF+和VREF-四个引脚,STM32的ADC采集范围为VREF- ≤ VIN ≤ VREF+,一般将ADC的负端参考电压与VSSA短接然后接地,将ADC的正端参考电压接VDDA即3.3V,这样ADC的采集范围就设置为0~3.3V,对于12位分辨率的ADC,其采集数字量范围为0-4095,这样就可以将0-3.3V的电压映射到0-4095的数字量,使其可以相互转化,ADC电源即参考电压引脚具体描述如下图所示(注释1)

STM32F407有三个ADC可供使用,每个ADC又拥有16个通道ADCx_IN[15:0],其中ADC1还拥有Temperature Sensor Channel、Vrefint Channel和Vbat Channel三个内部通道,Temperature Sensor Channel通道用于测量芯片内部温度,范围为-40℃~125℃,精度为±1.5℃,Vrefint Channel用于测量内部参考电压,Vbat Channel用于测量备用电源电压的一半,ADC的转换主要依靠12位分辨率的片上模数转换器

注入通道和规则通道均有16个触发源,可以选择定时器外部源触发/定时器比较捕获触发/软件常规触发,具体参看上图ADC框架中的紫色框框

④ADC启动转换时需要按照一定通道顺序转化,该顺序由规则通道和注入通道两者共同决定,其中注入通道其数据寄存器为4*16位,因此可以同时转换四个通道,但是规则通道的数据寄存器只有一个16位的寄存器,因此必须一个通道一个通道的转换,每转换完一个通道,就需要及时将转换完成的结果从规则通道数据寄存器中读出去,其中注入通道类似ADC通道转换过程的中断,如下图所示(注释2)

ADC的中断事件有DMA溢出、ADC转换结束、注入转换结束和模拟看门狗事件共四个事件,前三个中断和其名字表述类似,当转换结束/溢出时就会产生中断,模拟看门狗可以设置ADC转换值的上限和下限,当超出限制之后就会产生中断,可以用于警报,如下表所示(注释1)

ADC有独立模式、二重和三重采集模式,当只有ADC1启动时只能使用独立模式,当ADC1/2启动时可以使用二重采集模式,当ADC1/2/3/全部启动时可以使用三重采集模式,本实验只介绍独立模式

4、实验流程

4.0、前提知识

本实验为ADC独立模式单通道单次转换模式,主要利用ADC1_IN5通道由软件/定时器启动ADC转换,如果是软件手动启动的ADC转换则在单次转换模式下每次转换完成一次之后均需要再次手动启动ADC转换,另外需要注意ADC在开始精确转换之前需要一段稳定时间tSTAB,如下图所示为ADC转化所经过的路径

4.1、CubeMX相关配置

请先阅读“STM32CubeMX教程1 工程建立”实验3.4.1小节配置RCC和SYS

4.1.1、时钟树配置

系统时钟树配置均设置为STM32F407总线能达到的最高时钟频率,具体如下图所示

4.1.2、外设参数配置

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

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

在Pinout & Configuration页面左边功能分类栏目Analog中单击其中ADC1,在Mode中勾选需要使用的输入通道,本实验为单通道转换实验,因此任意勾选IN0~IN15之间的任一通道均可,笔者勾选了IN5

在Configuration中对ADC1_IN5的转换参数进行配置,下面介绍一些比较重要的参数

------------------ ADCs_Common_Settings ------------------

①Mode(模式):现在只能选择独立模式,当同时启用了ADC1/2或ADC1/2/3时这里会出现多重ADC采集的模式可选

------------------------- ADC_Settings -------------------------

②Clock Prescaler(时钟分频):决定ADC转换的频率,分频越少ADC转换的频率越高,最少2分频,一个通道一次ADC转换的总时间为N+12个ADC时钟周期,其中N为设置的采样次数Cycles

③Resolution(ADC转换精度):可以选择12/10/8/6位精度的转换值,精度选择不同需要的转换时钟周期也不同

④Data Alignment(数据对齐):由于规则数据寄存器为16位,但是最高转换精度为12位,因此数据可以选择以右对齐/左对齐的方式放入寄存器

⑤Scan Conversion Mode(扫描转换模式):规则通道同时只能转换一个通道,启用该参数后,当规则通道中有多个通道等待转换时其转换完当前通道会自动转换组内的下一个通道

⑥Continuous Conversion Mode(连续转换模式):启用该参数,ADC结束一个转换立即开始一个新的转换,与参数⑤共同启用,则组内最后一个通道转换完毕后会立即切换到第一个通道继续转换

⑦DMA Continuous Requests(DMA请求):需要在DMA Settings中添加DMA请求后,该参数才可以使能

⑧End Of Conversion Selection(结束转换标志):选择是一个通道转换完就产生EOC标志,还是一个组内所有通道全部转换完才产生EOC标志

------------------ ADC_Regular_ConversionMode------------------

⑨NumberOfConversion(转换通道数量):常规规则通道希望转换的通道数量

⑩External Trigger Conversion Source(外部触发转换源)

⑪External Trigger Conversion Edge(外部触发转换边沿)

⑫Rank(规则通道排序)

------------------ ADC_Injected_ConversionMode------------------

⑬NumberOfConversion(注入通道转换模式通道数量):注入通道希望转换的通道数量

具体参数配置如下图所示

4.1.3、外设中断配置

在Pinout & Configuration页面左边System Core/NVIC中勾选ADC1/2/3全局中断,然后选择合适的中断优先级即可,步骤如下图所示

4.2、生成代码

请先阅读“STM32CubeMX教程1 工程建立”实验3.4.3小节配置Project Manager

单击页面右上角GENERATE CODE生成工程

4.2.1、外设初始化调用流程

在生成的工程代码主函数main()中调用了MX_ADC1_Init()函数完成了对ADC1基本参数的配置,ADC常规规则通道/注入通道等参数配置

然后在ADC初始化函数HAL_ADC_Init()函数中调用了HAL_ADC_MspInit()函数对ADC1时钟和中断进行了使能,对中断优先级进行了配置,对ADC1_IN5输入引脚做了复用操作

如下图所示为ADC1单通道初始化的具体函数调用流程

4.2.2、外设中断调用流程

使能ADC1/2/3全局中断后在stm32f4xx_it.c中自动生成了TIM4的中断处理函数ADC_IRQHandler()

ADC_IRQHandler()调用了HAL库的ADC中断处理函数HAL_ADC_IRQHandler(),该函数处理所有的ADC中断事件

在ADC转换完成之后最终调用了ADC转换完成中断回调函数HAL_ADC_ConvCpltCallback(),该函数为虚函数

如下图所示为ADC1单通道转换中断回调的具体函数调用流程

4.2.3、添加其他必要代码

在adc.c中重新实现ADC转换完成中断回调函数HAL_ADC_ConvCpltCallback(),在该函数中获取ADC的转换值,然后将其计算为电压值*1000,并将这两个值通过串口输出,具体代码如下图所示

源代码如下

/*转换完成中断回调*/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{/*定时器中断启动单通道转换*/if(hadc->Instance == ADC1){uint32_t val=HAL_ADC_GetValue(&hadc1);uint32_t Volt=(3300*val)>>12;printf("val:%d, Volt:%d\r\n",val,Volt);}
}

在主函数中以中断方式启动ADC转换,然后启动ADC的触发源TIM3定时器,具体代码如下图所示

5、常用函数

/*启动ADC转换*/
HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef *hadc)/*停止ADC转换*/
HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef *hadc)/*以中断方式启动ADC转换*/
HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef *hadc)/*停止ADC转换*/
HAL_StatusTypeDef HAL_ADC_Stop_IT(ADC_HandleTypeDef *hadc)/*轮询ADC是否转换完毕*/
HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef *hadc, uint32_t Timeout)/*获取ADC转换值*/
uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef *hadc)/*ADC转换完成中断回调函数*/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)

6、烧录验证

6.1、实验具体流程

“配置USART1用于输出信息 -> 配置通用定时器TIM3实现100ms定时 -> TIM3外部触发事件选择为更新事件 -> 启动ADC1的通道5并配置相关参数 -> 外部触发转换源选择TIM3的外部触发事件 -> 启动ADC1/2/3全局中断 -> 重新实现ADC转换完成中断回调HAL_ADC_ConvCpltCallback()函数 -> 在回调函数中读取ADC转换值并通过串口输出 -> 在主函数中启动定时器和ADC转换”

6.2、实验现象

烧录程序,上电后打开串口,串口会每100ms传来一次ADC采集的数据,旋转滑动变阻器从一端到另一端,可以看到ADC采集到的值从0逐渐变为最大值4095

7、软件触发ADC采集

如果你希望不采用定时器触发中断采集的方式,而是想使用软件手动触发轮询采集的方式,需要先将ADC规则转换模式中触发源修改为软件触发,然后使用HAL_ADC_Start()启动转换,使用HAL_ADC_PollForConversion()轮询检测是否转换完成,转换完成后使用可以HAL_ADC_GetValue()获取转换后的ADC值,具体参考如下图所示

源代码如下

HAL_ADC_Start(&hadc1);
if(HAL_ADC_PollForConversion(&hadc1,200)==HAL_OK)
{uint32_t val=HAL_ADC_GetValue(&hadc1);uint32_t Volt=(3300*val)>>12;printf("val:%d, Volt:%d\r\n",val,Volt);
}
HAL_Delay(500);

8、注释详解

注释1:图片来自STM32F4xx中文参考手册 RM0090

注释2:图片来自【STM32】HAL库 STM32CubeMX教程九---ADC_cubemx adc-CSDN博客

参考资料

STM32Cube高效开发教程(基础篇)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/591985.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

堆排序(C语言版)

一.堆排序 堆排序即利用堆的思想来进行排序,总共分为两个步骤: 1. 建堆 升序:建大堆 降序:建小堆 2. 利用堆删除思想来进行排序 1.1.利用上下调整法实现堆排序 第一步:建堆 好了,每次建堆都要问自己…

MVCC 并发控制原理-源码解析(非常详细)

基础概念 并发事务带来的问题 1)脏读:一个事务读取到另一个事务更新但还未提交的数据,如果另一个事务出现回滚或者进一步更新,则会出现问题。 2)不可重复读:在一个事务中两次次读取同一个数据时&#xff0c…

【逆向】从逆向角度看C++

从逆向角度看C 1.2.1 虚函数地址表(虚表) 定义:当类中定义有虚函数时,编译器会把该类中所有虚函数的首地址保存在一张地址表中,即虚函数地址表。虚表信息在编译后被链接到执行文件中,因此所获得的虚表地址…

《3D数学基础-图形和游戏开发》阅读笔记 | 3D数学基础 (学习中)

文章目录 3D数学基础矢量/向量概述 - 什么是向量单位矢量:只关注方向不关注大小 数学运算矢量的加法与减法减法的几何意义计算一个点到另一个点的位移矢量的点积与叉积 矩阵矩阵的几何意义 3D数学基础 矢量/向量 在笔记中 变量使用小写字母表示,a由于…

Linux实用指令篇

目录结构 Linux文件系统结构是从Unix文件结构演进过来的。在Linux文件系统中,通用的目录名用于表示一些常见的功能。 Linux 的文件系统是采用层级式的树状目录结构,在此结构中的最上层是 根目录 “/”,然后在此目录下再创建其他的目录。在L…

安装 Node.js、npm

安装 nodejs 安装Node.js的最简单的方法是通过软件包管理器。 Node.js官网:https://nodejs.org/en/download/ cd /usr/local/src/wget -c https://nodejs.org/dist/v18.16.0/node-v18.16.0-linux-x64.tar.xz xz -d node-v18.16.0-linux-x64.tar.xz tar -xf node…

轻松搞定软件开发:找对软件开发公司的流程与注意事项!

随着数字化时代的来临,软件开发在企业和个人生活中扮演着越来越重要的角色,然而,如何找到一家合适的软件开发公司却成为了一个令人头疼的问题。 本文将为你详细解读找软件开发公司的流程,以及在选择过程中需要注意的事项&#xf…

C#编程-编写和执行C#程序

编写和执行C#程序 可以使用Windows记事本应用程序来编写C#程序。在记事本应用程序中创建C#程序后,您需要编译并执行该程序以获得所需的输出。编译器将程序的源代码转换为机器代码,这样计算机就能理解程序中的指令了。 注释 除了记事本,您还可以使用任何其他文本编辑器来编写…

UnityRenderStreaming使用记录(一)

UnityRenderStreaming 地址https://github.com/Unity-Technologies/UnityRenderStreaming 一、客户端相关 1、unity工程添加Package 2、WebRTC选Version 3.0.0-pre.6,升级会报错 导入Samples 3、打开Broadcast场景 二、服务器相关 这里使用github上的源码&…

kubeadm创建k8s集群

kubeadm来快速的搭建一个k8s集群: 二进制搭建适合大集群,50台以上。 kubeadm更适合中下企业的业务集群。 部署框架 master192.168.10.10dockerkubelet kubeadm kubectl flannelnode1192.168.10.20dockerkubelet kubeadm kubectl flannelnode2192.168.1…

MySQL数据库高级SQL语句及存储过程

目录 一、高级SQL语句 (一)case语句 1.语法定义 2.示例 (二)空值(NULL) 和 无值( ) 1.区别 2.示例 (1)字符长度 (2)判断方法 ① 空值(NULL) ② 无值( ) (3…

centos 7.9 升级系统默认的python2.7到python 2.7.18

centos 7.9 升级系统默认的python2.7到python 2.7.18 备份旧版本 mv /usr/bin/python /usr/bin/python_2.7.5 下载新版本 Download Python | Python.org Python Release Python 2.7.18 | Python.org wget https://www.python.org/ftp/python/2.7.18/Python-2.7.18.tgz cd /…

哨兵1号回波数据(L0级)FDBAQ压缩算法详解

本专栏目录: 全球SAR卫星大盘点与回波数据处理专栏目录-CSDN博客 1. 全球SAR卫星回波数据压缩算法统计 各国的SAR卫星的压缩算法按照时间轴排列如下: 可以看出传统的分块BAQ压缩算法(上图粉色)仍然是主流,哨兵1号其实也有传统的BAQ压缩模式。 本文介绍哨兵1号用的FDBAQ算…

【数据分析】指数移动平均线的直观解释

slavahead 一、介绍 在时间序列分析中,通常需要通过考虑先前的值来了解序列的趋势方向。序列中下一个值的近似可以通过多种方式执行,包括使用简单基线或构建高级机器学习模型。 指数(加权)移动平均线是这两种方法之间的稳健权衡。…

nginx源码分析-4

这一章内容讲述nginx的模块化。 ngx_module_t:一个结构体,用于描述nginx中的各个模块,其中包括核心模块、HTTP模块、事件模块等。这个结构体包含了一些模块的关键信息和回调函数,以便nginx在运行时能够正确地加载和管理这些模块。…

UE5.1_Gameplay Debugger启用

UE5.1_Gameplay Debugger启用 重点问题: Gamplay Debugger启用不知道? Apostrophe、Tilde键不知道是哪个? Gameplay调试程序 | 虚幻引擎文档 (unrealengine.com) Gameplay Debugger

day02 有序数组的平方 长度最小子数组 螺旋矩阵

题目1&#xff1a;977 有序数组的平方 题目链接&#xff1a;977 有序数组的平方 题意 返回非递减整数数组的每个数字的平方和 也按照递减排序 双指针★ 代码 class Solution { public:vector<int> sortedSquares(vector<int>& nums) {vector<int>…

VMware 虚拟机 ubuntu 20.04 硬盘扩容方法

前言 最近由于需要编译 【RK3568】的 Linux SDK&#xff0c;发现 虚拟机默认的 200G 空间不足了&#xff0c;因此想增加这个 200G 空间的限制&#xff0c;通过网络上查找了一些方法&#xff0c;加上自己亲自验证&#xff0c;确认 硬盘扩容 正常&#xff0c;方法也比较的容易&a…

Vue:Vue与VueComponent的关系图

1.一个重要的内置关系&#xff1a;VueComponent.prototype.proto Vue.prototype 2.为什么要有这个关系&#xff1a;让组件实例对象&#xff08;vc&#xff09;可以访问到 Vue原型上的属性、方法。 案例证明&#xff1a; <!DOCTYPE html> <html lang"en"&…

Java日期和时间(二)

新增的日期和时间 为什么要学习新增的日期和时间 1、代替Calendar LocalDate&#xff1a;年、月、日 LocalTime&#xff1a;时、分、秒 LocalDateTime&#xff1a;年、月、日、时、分、秒 ZoneId&#xff1a;时区 ZoneldDatetime&#xff1a;带时区的时间 2、代替Date Instan…