【工具使用】STM32CubeMX-单ADC模式规则通道配置

news2024/10/6 5:53:34

一、概述

    无论是新手还是大佬,基于STM32单片机的开发,使用STM32CubeMX都是可以极大提升开发效率的,并且其界面化的开发,也大大降低了新手对STM32单片机的开发门槛。
    本文主要讲述STM32芯片的ADC的配置及其相关知识。

二、软件说明

    STM32CubeMX是ST官方出的一款针对ST的MCU/MPU跨平台的图形化工具,支持在Linux、MacOS、Window系统下开发,其对接的底层接口是HAL库,另外习惯于寄存器开发的同学们,也可以使用LL库。STM32CubeMX除了集成MCU/MPU的硬件抽象层,另外还集成了像RTOS,文件系统,USB,网络,显示,嵌入式AI等中间件,这样开发者就能够很轻松的完成MCU/MPU的底层驱动的配置,留出更多精力开发上层功能逻辑,能够更进一步提高了嵌入式开发效率。
    演示版本 6.7.0

三、ADC简介

    ADC是普通攻击持续输出核心的简称,是……不好意思,拿错剧本了。ADC(Analog-to-Digital Converter的缩写),指模/数转换器或者模数转换器。是指将连续变化的模拟信号转换为离散的数字信号的器件。作为单片机最常用的一种外设之一,我们先来看下普通ADC的工作原理。

    然后再来看下ST里ADC这个外设有什么特别之处(不同单片机ADC的配置界面及框图可能会有所不同,本文以STM32F072RB为例,简述下最基本的配置)。可以看到这里除了ADC核心转换部分,还有外围一堆设置项。接下来我们就按这个框图来讲解一下ST里的ADC功能。(其中核心转换部分就跟上面讲的工作原理差不多,这部分跟配置使用相关性不大,就不再细讲,主要看配置部分)

在这里插入图片描述

  • 输入

    以此图为例,其ADC采样通道数有19个,包括0到11和15到18这16个普通外部ADC采样通道(ADC_IN),一路内部温度检测通道(VSENSE),一路参考电压采样通道(VREFINT),一路备份电源采样通道(VBAT)。因为ADC转换器同一时间只能转换一个通道的数据,所以输入部分的配置主要是选择需要转换的通道,由CH_SEL决定。
    这里可能有人就有疑问了,这个单片机只有一个ADC转换器,如果我要同时采两个或者两个以上的数据时,是不是就不能用这个单片机了?
    是的,但这只限于真正意义上的同时采样,也就是要求完全同一时刻采样的时候,这个才无法满足。而生活中大部分应用情况,只需要分时采样即可,就像我们用的电脑,电脑看似同时跑了很多个应用,但实际操作系统也是分时处理这些应用的,只是因为切换速度很快,人一般感知不到,所以看起来就像是同时在运行。回到ADC这里也一样,只要我们快速切换通道采样,那看起来也跟同时采一样。
    快速切换通道采样,我们一般称之为扫描(Scan),所以这里有这么一个配置项,扫描方向(SCANDIR),就是采样顺序是从前到后还是从后到前。一般对时序要求不高的场景,比如采几个温度值用来显示用的,可以不用关注这个顺序,但对时序采样有要示的场景就需要关注这个顺序了。

  • 触发源

    触发源,就是选择使用什么机制来启动ADC采集,ST支持两大类的触发机制,一种是常用的,由软件触发,设置ADSTART和ADSTP用来启动和停止ADC转换。另一种则是硬件触发,可配置触发源为定时器或外部中断。

  • 输出

    虽然图中看着功能比较多,但无非就两大类,一是硬件用的,给到模拟看门狗作为触发源使用;二是软件用的,可通过中断知会用户获取使用,也可以通过DMA进行自动传输。

  • 电源及参考源

    根据以上原理我们知道,采集ADC值是需要有个电压值与采集值作对比的,那么这个用于参考比较的电压值从哪来呢?答案就在这里,单片机的VREF+接口。所以这里可以得出一个电压的计算公式,其中VREF+可以默认按实际接入的参考电压直接代入:
V采集值 = (ADC原始值 / 2ADC位数) * VREF+
    这时候可能有人会有疑问,为什么不直接用VCC单片机电源就行,而要浪费一个IO口来作为参考源输入呢?因为单片机虽然说一般是3.3V供电,但实际单片机可支持的电压是有一定范围的,所以一般电源设计用于单片机供电的电压并不会很精确,如果直接用这个作为参考源,会导致ADC计算的误差偏大。
    比如下图A点时刻,实际VREF+是3.33V,而公式使用的是固定3.3V进行计算,这样就会导致计算的结果偏小。而B点时刻则是相反,计算结果偏大。
在这里插入图片描述

    那另外有人会说了,前面不是说了参考源电压也可以采集么,那我用采集的参考源电压代入公式来计算,不就可以消除这个偏差了么?确实可以,但回到前面讲的ST芯片中ADC的采样原理,虽说可以多通道采集,但实际是多通道分时采集的数据,也就是说采集的参考源电压值与采集的通道电压值并不是同一时刻的值,如果参考源电压波动较为频繁,则还是存在检测偏差。

    以下图为例,如果先采集的是参考源电压,那先采集到A点的值,然后经过一个采样周期后,再采集输入电压值,即D点的值,将这两个值代入公式中,计算出来的结果是偏大的。反之如果先采的是输入电压再采参考电压,则是采了B、C点的值,代入公式结果则是偏小。
在这里插入图片描述

    综上所述,这里推荐使用LDO输出的稳压源作为参考电压源。

  • 校准

    因为芯片做工的问题,ADC外设模块多多少少存在一定的差异常性,所以ST芯片里的ADC就提供了一个用于消除工艺或其他因素导致的芯片间检测差异的功能——校准。通过启动校准功能,ADC外设自身可以计算出一个校准值,用于消除零点偏差。ST官方是建议每次使能ADC时都需要校准一次。

  • 规则通道与注入通道*

    ADC的通道循环采集的方式有两种,一种是配置成规则通道,一种是配置成注入通道。第一次听到这两个名词可能会比较陌生,这里举个例子可能就比较清晰。
    比如现在配置1、2、3、4通道为规则通道,那么当启动采集后,ADC会按照1、2、3、4的顺序依次采集,如果配置了循环采集,则在采集完第4通道后自动启动下一个周期的采集。
    如果把1、2、3、4通道配置为注入通道,此时则需要一个触发启动源,触发源触发一个采集事件时,立即进行一次采集。
    就上面两个例子看下来,感觉像什么?是不是跟单片机的代码结构一样,规则通道就是主循环里一直跑的代码,而注入通道则是中断里执行的代码,中断可以随时打断主循环里的内容。不过虽说是立即打断规则通道的采集,但实际也是要等规则通道当前一次通道的值采样完成后才会进行注入通道的采样,就像主循环被中断打断,其实也是要等主循环里的某一条语句执行完成才可以切换。
    这一章节标星是因为本文不涉及规则通道及注入通道的配置,只是简述下这两者的概念。

四、ADC配置

  • 端口配置

    先选择端口,如果是内部ADC,如温度、参考电压、备份电压,则直接在左边Analog选项卡中选中ADC,在菜单栏中勾选需要检测的电压源。

在这里插入图片描述

    如果是外部端口,建议先从端口视图中找到对应需要检测的端口,选择ADC通道及GPIO的Analog复用功能。
在这里插入图片描述
    这一次我们只选择内部温度检测进行后面的操作。

  • 基本配置

在这里插入图片描述
时钟分频(Clock Prescaler): 主时钟给到ADC后,可根据不同需要设置分频系数,分频越低,能耗越低,当然对应的转换时间也会更长。
分辨率(Resolution): ADC位数不同,其采样精度就不一样,以3.3V参考源为例,6位的ADC,其转换电压的颗粒度是3.3/26,而12位的ADC,转换电压的颗粒度则是3.3/212。所以分辨率越高,其采样的精度也就越高,当然代价就是转换时间更长,能耗更高。
数据对齐方式(Data Alignment): 可以选择采样后的数据左对齐存放或右对齐存放。以12位ADC为例,比如采样出0x0123的值,当设置为右对齐时,ADC的DR寄存器中存放的值就是0x0123,设置成左对齐时,则是0x1230(原始数据左移(16 - ADC位数))。这里可能有人会有疑问,用右对齐就可以直接得到原始值,那左对齐有什么用?一开始我也觉得左对齐没用,但后面看到ST官方电机库里的换算实现才知道这个的好处。
回想下上面的电压换算公式,右对齐时,需要使用下面公式,这里需要知道分辨率的设置。
V = Data / 2分辨率 * VREF+
而数据左对齐时,只需要使用公式:
V = Data / 0xFFFF * VREF+

扫描方向(Scan Conversion Mode): 可选择从0到18向后扫描,也可以选择从18到0向前扫描。这个单片机只能支持这两个顺序扫描,F1之后的单片机,是支持自己设置扫描顺序的。
连续转换模式(Continuous Conversion Mode)和非连续转换模式(Discontinuous Conversion Mode): 设置成连续转换模式时,在一个组的ADC转换结束后,可以继续启动转换,不需要触发源介入。禁止时,则是在一个组转换结束后即停止转换,需要等到下个触发启动才开始转换。这两个我一直想吐槽,为什么非得分成两个配置项,外设也是有两个单独的寄存器进行设置。但这两个寄存器实则是互斥的关系,即开启了连续转换模式,就不能开启非连续转换模式;开启了非连续转换模式,就不能开启连续转换模式。
DMA传输模式(DMA Continuous Requests): 开启此功能可召唤DMA当搬运工帮你搬运数据,具体还需要配置DMA相关的参数,这部分本文就不作介绍,在单独的ADC+DMA篇章中细说。
结束方式选择(End Of Conversion Selection):
数据覆盖方式(Overrun Behaviour): 当ADC的DR寄存器里已经存有上次转换完的数据,并且未读取时,又有一次ADC通道转换完成时,可通过此选项,选择是保持之前的数据,还是用新的数据覆盖之前的数据。
低电压自动等待(Low Power Auto Wait): 低电压时不进行转换,等待电压恢复。
低电压自动断电(Low Power Auto Power Off): 低电压时断ADC外设的电,电压恢复后需要手动给ADC上电。
转换时间(Sampling Time): 前面原理讲到的,ADC转换需要一定的时间,而这个时间跟外部电路也有一定的关系,所以这个时间是根据外部电路可以做灵活调整,一般来讲时间设置越长,检测的准确性也就越高。如果对时序要求不高的场合,设置成最大的周期数即可。
外部触发源(External Trigger Conversion Source): 一般默认是软件触发,即需要在代码里调用启动转换的接口。另外可以选择是各种定时器事件触发。
外部触发方式(External Trigger Conversion Edge): 当选择了定时器事件触发后,这个选项可以选择是由定时器的上升沿、下降沿或边沿触发采样。
模拟看门狗使能(Enable Analog Watchdog Mode): 相当于一个比较器,当检测到的电压超过设定阀值时,可以触发一个中断。
下限阀值(Low Threshold): 设置触发中断的下限阀值。

  • 温度检测

    查看手册说明,采集到内部温度通道的ADC值后,可以使用以下的公式换算出当前温度值。
在这里插入图片描述

    其中TS_CAL1和TS_CAL2分别是30℃和110℃温度下对应的ADC采集值,但这个值哪来呢?别担心,这个是ST芯片出厂就给你内置好的一个值,在数据手册里有说明,只要获取这个地址的值即可。ST库里也提供有相关的宏。

在这里插入图片描述
    然后工程按如下配置,不考虑功耗的情况,我们只需要让其一直采样即可,不需要开启中断,只要用到数据的时候再去取就行。
在这里插入图片描述
    配置完成后,生成工程代码,在工程里添加如下代码:

#define TEMP110_CAL_ADDR ((uint16_t*) ((uint32_t) 0x1FFFF7C2))
#define TEMP30_CAL_ADDR ((uint16_t*) ((uint32_t) 0x1FFFF7B8))
float Temp = 0;
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_ADC_Init();
  /* USER CODE BEGIN 2 */
  /* HAL库实现 */
  HAL_ADC_Start(&hadc);
  #if 0
  /* LL库实现 */
  LL_ADC_Enable(ADC1);
  LL_ADC_REG_StartConversion(ADC1);
  #endif
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	/* HAL库实现 */
	int32_t adc_data = HAL_ADC_GetValue(&hadc);
	Temp = (110 - 30) * ((float)adc_data - *TEMP30_CAL_ADDR)
						/ (*TEMP110_CAL_ADDR - *TEMP30_CAL_ADDR)
						+ 30;
	/* LL库实现 */
	#if 0
	int32_t adc_data = LL_ADC_REG_ReadConversionData12(ADC1);
	Temp = (110 - 30) * ((float)adc_data - *TEMP30_CAL_ADDR)
						/ (*TEMP110_CAL_ADDR - *TEMP30_CAL_ADDR)
						+ 30;
	#endif
  }
}

    编译烧录进入调试。

  • 效果演示

在这里插入图片描述

    很奇怪在空调房里都检出50℃出来,不知道是不是板子吃灰太久有点问题。换个最新拿到的C0板子试了下,公式不大一样。
在这里插入图片描述
在这里插入图片描述

    同样的按照公式编写代码,烧录并调试。

#define TEMP30_CAL_ADDR ((uint16_t*) ((uint32_t) 0x1FFF7568))
float Temp = 0;
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ADC1_Init();
  /* USER CODE BEGIN 2 */
	HAL_ADC_Start(&hadc1);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		int32_t adc_data = HAL_ADC_GetValue(&hadc1);
		/* 因为这里参考电压是3.3V,所以不用公式里乘Vdd除3的操作 */
		Temp = (((float)adc_data) - *TEMP30_CAL_ADDR) / (2.53 * 4096 / 3300) + 30;

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

    33度,这个就正常多了。
在这里插入图片描述

五、注意事项

1、使用ADC+DMA的时候,留意下自动生成的代码中ADC和DMA的初始化顺序,之前旧版本生成的代码是有Bug的,因为ADC和DMA的初始化的调用顺序不对导致多个通道采集ADC值时会有异常。
2、F0没办法配置多通道的扫描顺序,只能按从0到18或从18到0的顺序进行采集。

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

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

相关文章

6. Springboot快速回顾(集成Dubbo)

Dubbo是实现远程调用的一个框架,阿里巴巴开源的。远程调用就是B服务器可以调用A服务器的方法。大型项目会被拆分成多个模块,部署在不同的服务器上。若将公共模块集中部署在一台服务器上,可以方便其他服务器调用。因此,需要Dubbo。…

java代码实现自动录入数据

之前工作中遇到粘贴复制大量数据&#xff0c;研究一下java代码解放双手 模拟鼠标录入数据 引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.3.0.RELEASE&…

本地私有化部署大模型RWKV-懒人包一键安装享受专属免费大模型-RWKV Runner

仓库地址&#xff1a;https://github.com/josStorer/RWKV-Runner 预设配置已经开启自定义CUDA算子加速&#xff0c;速度更快&#xff0c;且显存消耗更少。如果你遇到可能的兼容性问题&#xff0c;前往配置页面&#xff0c;关闭使用自定义CUDA算子加速 如果Windows Defender说这…

Flutter:架构概览

概览 Flutter本质上是一个跨平台的UI工具集&#xff0c;允许在各自操作系统上复用同样的代码。 尽可能提供原生体验的高性能和复用代码。 开发中&#xff0c;Flutter应用在一个VM上运行&#xff0c;使得可在保留状态且无需重新编译情况下&#xff0c;进行热加载。 发行时&…

【教程】Unity 联动 MSMQ 消息通讯

开发平台&#xff1a;Unity 2021.3.7 通讯平台&#xff1a;Windows 10 依赖DLL&#xff1a;System.Messaging.dll   一、本文目标 了解与操作 Windows 平台上建立 Unity 与 MSMQ 通讯机制。实现基础的通讯功能。   二、准备&#xff1a;启用 MSMQ 服务项 注意&#xff1a;默…

操作符——区别C++前置++和后置++

这里写目录标题 1.问题引出Q:重载或者--的时候如何区分前置和后置&#xff1f; 2.C规范3.前后置实现4.为什么i;可以 i&#xff1b;不行 1.问题引出 Q:重载或者–的时候如何区分前置和后置&#xff1f; 以前C对前置和后置没有很好的办法可以区分&#xff0c;为了解决这个问题&…

面试之SpringAOP的理解:

AOP(面向切面编程)指的是那些业务本身无关&#xff0c;但是被业务模块所共同调用的业务逻辑或责任&#xff08;日志管理&#xff0c;权限管理等&#xff09;封装起来&#xff0c;便于减少系统的重复代码&#xff0c;降低系统见的耦合性&#xff0c;有利于未来系统的扩展性。 S…

IOS开发工程师的发展前景怎么样

本文目录一览 1&#xff0c;iOS开发工程师就业前景怎么样2&#xff0c;北大青鸟java培训IOS开发前景怎么样3&#xff0c;iOS开发工程师就业前景怎么样4&#xff0c;作为一个iOS开发程序员我的未来何去何从5&#xff0c;IOS开发工程师的发展前景怎么样6&#xff0c;ios开发工程…

Ubuntu 20.04 L2TP VPN 自动重连脚本,cron定时任务设置

1、连接VNP脚本 reconnect_l2tp_vpn.sh #!/bin/sh ppp0_flagifconfig | grep ppp0 echo $ppp0_flag if [ -z "$ppp0_flag" ];thenecho "connet to vpn ..."# connet vpn# echo PASSWORD &#xff5c; sudo -S 这样可以不用手动输入密码!echo abc123| su…

我爱学QT-QT信号和槽

1.给控件改名字 为了分析代码方便&#xff0c;我们要给控件改名字。要通俗易懂。 2.信号和槽 信号&#xff1a;信号就是指控件发出的特定的信号。 比如按钮的信号 槽&#xff1a;槽就是槽函数的意思&#xff0c;我们可以把槽函数绑定在某一个控件的信号上。 3.怎么关联信号…

IntelliJ IDEA中生成jar包并运行

1. 过程 依次选择菜单&#xff1a;File->Project Structure…&#xff0c;打开“Project Structure”界面。 在打开界面的左侧列表中选择&#xff1a;Artifacts&#xff0c;点击右侧出现的号。 在出现的菜单中依次选择&#xff1a;JAR->From modules with dependencies…

家政行业丨制作便捷高效的家政小程序

随着现代生活节奏的加快和家庭需求的多样化&#xff0c;越来越多的人开始寻找一种更方便、更高效的方式来获取家政服务。而家政小程序的兴起为这一需求提供了理想的解决方案。本文将简要介绍家政小程序是什么&#xff0c;探讨家政小程序的好处&#xff0c;并提供一些制作搭建家…

element上传文件对格式限制的处理

需求&#xff1a;上传的文件格式必须是pdf格式&#xff0c;方便查看 规定多种格式用逗号隔开 使用这个属性可以规定上传文件格式&#xff0c;但是有bug 可以手动改变显示的文件类型&#xff0c;还是可以传其他文件类型 所以需要在上传的时候限制上传的文件格式 上传组件 <…

X2000 Linux 调试VL53L4CD

由于VL53L4CD具有更高的精度&#xff0c;更低的功耗&#xff0c;所以尝试将VL53L4CD移植到X2000上进行测试。 一、下载驱动 en.VL53L4CD_LinuxDriver 二、SDK中加入驱动 1、加入源码 在\module_driver\devices下创建VL53L4CD文件夹&#xff0c;再将\en.VL53L4CD_LinuxDriver…

网络爬虫-jd滑块验证码

仅供研究学习使用。 目标站点 --> 京东网页登录 当我们输入账号密码后&#xff0c;点击登录&#xff0c;首先映入眼帘的是一个滑块&#xff0c;那我们先分析一下滑块吧。 上图是滑块的有关信息&#xff0c;左边的横线是请求的url&#xff0c;右边是参数&#xff0c;很显然&…

敏捷测试自动化

目录 前言&#xff1a; 敏捷宣言 敏捷软件开发VS传统方法 敏捷云服务 对什么进行自动化&#xff1f; 测试自动化的技巧 关于敏捷测试和自动化测试的关键信息 前言&#xff1a; 敏捷测试自动化是在敏捷开发环境中使用自动化工具和技术来支持测试活动的一种方法。它旨在提…

SQL使用(一):如何使用SQL语句去查询第二高的值

今天刷MYSQL题的时候刷到这样一个题&#xff1a; 编写一个 SQL 查询&#xff0c;获取 Employee 表中第二高的薪水&#xff08;Salary&#xff09; 。------------| Id | Salary |------------| 1 | 100 || 2 | 200 || 3 | 300 |------------例如上述 Employee 表&a…

时间序列预测 | Matlab自回归差分移动平均模型ARIMA时间序列预测,可实现多步预测,对未来的数据实现预测

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 时间序列预测 | Matlab自回归差分移动平均模型ARIMA时间序列预测,可实现多步预测,对未来的数据实现预测 评价指标包括:MAE、RMSE和R2等,代码质量极高,方便学习和替换数据。要求2018版本及以上。 部分源码 %% …

C语言比较容易出错的printf语句/cout语句

请问以下代码的输出结果是什么&#xff1f; int main() {int n 2;//cout << n << n << n--;printf("%d %d %d", n, n, n--);system("pause");return 0; } 结果&#xff1a; 很奇怪&#xff1f; 为什么会这样&#xff1f; 原来自己之…

MOVEit再现新漏洞,多个版本受影响

今年6月&#xff0c;文件共享工具MOVEit Transfer曾曝出SQL 注入漏洞&#xff0c;能让远程攻击者访问其数据库并执行任意代码。最近&#xff0c;MOVEit Transfer 母公司Progress Software又披露了三个新漏洞。 这三个漏洞分别是 CVE-2023-36932、CVE-2023-36933 和 CVE-2023-36…