当前位置: 首页 > news >正文

江协科技STM32学习- P21 ADC模数转换器

      🚀write in front🚀  
🔎大家好,我是黄桃罐头,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流
🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​ 

💬本系列哔哩哔哩江科大STM32的视频为主以及自己的总结梳理📚 

🚀Projeet source code🚀   

💾工程代码放在了本人的Gitee仓库:iPickCan (iPickCan) - Gitee.com

引用:

STM32入门教程-2023版 细致讲解 中文字幕_哔哩哔哩_bilibili

Keil5 MDK版 下载与安装教程(STM32单片机编程软件)_mdk528-CSDN博客

STM32之Keil5 MDK的安装与下载_keil5下载程序到单片机stm32-CSDN博客

0. 江协科技/江科大-STM32入门教程-各章节详细笔记-查阅传送门-STM32标准库开发_江协科技stm32笔记-CSDN博客

【STM32】江科大STM32学习笔记汇总(已完结)_stm32江科大笔记-CSDN博客

江科大STM32学习笔记(上)_stm32博客-CSDN博客

STM32学习笔记一(基于标准库学习)_电平输出推免-CSDN博客

STM32 MCU学习资源-CSDN博客

stm32学习笔记-作者: Vera工程师养成记

stem32江科大自学笔记-CSDN博客

术语:

英文缩写描述
GPIO:General Purpose Input Onuput通用输入输出
AFIO:Alternate Function Input Output复用输入输出
AO:Analog Output模拟输出
DO:Digital Output数字输出
内部时钟源 CK_INT:Clock Internal内部时钟源
外部时钟源 ETR:External clock 时钟源 External clock 
外部时钟源 ETR:External clock mode 1外部时钟源 Extern Input pin 时钟模式1
外部时钟源 ETR:External clock mode 2外部时钟源 Extern Trigger 时钟模式2
外部时钟源 ITRx:Internal trigger inputs外部时钟源,ITRx (Internal trigger inputs)内部触发输入
外部时钟源 TIx:external input pin 外部时钟源 TIx (external input pin)外部输入引脚
CCR:Capture/Comapre Register捕获/比较寄存器
OC:Output Compare输出比较
IC:Input Capture输入捕获
TI1FP1:TI1 Filter Polarity 1Extern Input 1 Filter Polarity 1,外部输入1滤波极性1
TI1FP2:TI1 Filter Polarity 2Extern Input 1 Filter Polarity 2,外部输入1滤波极性2

正文:

0. 概述

从 2024/06/12 定下计划开始学习下江协科技STM32课程,接下来将会按照哔站上江协科技STM32的教学视频来学习入门STM32 开发,本文是视频教程 P2 STM32简介一讲的笔记。


定时器共四个部分,分为八个小节笔记。本小节为第一部分第一节。

🌳在第一部分,是定时器的基本定时的功能:定时中断功能、内外时钟源选择

🌳在第二部分,是定时器的输出比较功能,最常见的用途是产生PWM波形,用于驱动电机等设备

🌳在第三部分,是定时器的输入捕获功能和主从触发模式,来实现测量方波频率

🌳在第四部分,是定时器的编码器接口,能够更加方便读取正交编码器的输出波形,编码电机测速


1.🚢ADC

STM32 小容量,中容量,和大容量产品系列:

小容量产品是指闪存存储器容量在16K至32K字节之间的STM32F101xx、STM32F102xx和STM32F103xx微控制器。

中容量产品是指闪存存储器容量在64K至128K字节之间的STM32F101xx、STM32F102xx和STM32F103xx微控制器。

大容量产品是指闪存存储器容量在256K至512K字节之间的STM32F101xx和STM32F103xx微控制器。

互联型产品是指STM32F105xx和STM32F107xx微控制器。

ADC模数转换器知识点

精华:ADC其实就像是一个电压表,把引脚的电压测出来放在一个变量里,这就是ADC的作用。 

ADC简介

  • ADC(Analog-Digital Converter)模拟-数字转换器,简称模数转换器或AD转换器
  • ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁。

🌵1.STM32主要是数字电路,数字电路只有高低电平,没有几v电压的概念,所以想读取电压值,就需要借助adc模数转换器来实现,adc读取引脚上的模拟电压转换为一个数据存在寄存器里,我们再把这个数据读取到变量里来就可以进行显示、判断、记录等操作了;

🌵2.数字到模拟的桥梁是DAC数字模拟转换器,使用DAC就可以将数字变量转换为模拟电压,PWM也是数字到模拟的桥梁,PWM实现的就是DAC的功能,同时PWM只有完全导通和完全断开两种状态,在这两种状态上都没有功率损耗,所以在直流电机调速这种大功率的应用场景使用pwm来等效模拟量是比DAC更好的选择并且pwm电路更加简单更加常用,所以pwm还是挤占了dac很多的应用空间,目前dac的应用主要是在波形生成领域比如信号发生器、音频解码芯片等这些领域pwm还是不好代替的)

  • 12位逐次逼近型ADC,1us转换时间。

🌵逐次逼近型是ADC的工作模式;12位和1us涉及到adc的俩个关键参数,第一个是分辨率,一般用多少位来表示,12位ad值表示范围就是0~2^12-1就是量化结果的范围0~4095,位数越高量化结果就越精细,对应分辨率就越高;第二个是转换时间就是转换频率,ad转换是需要花一小段时间的,这里1us就是表示从ad转换开始到产生结果需要花1us的时间,对应ad转换的频率就是1MHz(1MHz的周期是1微秒,是stm32的adc最快转换频率),如果你需要转换一个频率非常高的信号那就需要考虑一下这个转换频率是不是够用,如果你的信号频率比较低那这个最大1MHz的转换频率也完全够用

🌵输入电压范围:0~3.3V,转换结果范围:0~4095。(adc的输入电压一般要求是在芯片供电的负极和正极之间变化的,0v对应0,3.3v对应4095,中间都是一一对应的线性关系)

  • 18个输入通道,可测量16个外部和2个内部信号源。

🌵外部信号源就是16个gpio口,在引脚上直接接模拟信号就行了,不需任何额外的电路,引脚就直接能测电压;

🌵2个内部信号源内部温度传感器和内部参考电压,温度传感器可以测量cpu的温度,比如你电脑可以显示一个cpu的温度就可以用adc读取这个温度传感器来测量,内部参考电压是一个1.2v左右的基准电压,这个基准电压是不随外部供电电压变化而变化的,所以如果你芯片的供电不是标准的3.3v那测量外部引脚的电压可能就不对,这时就可以读取这个基准电压进行校准,这样就能得到正确的电压值了

  • 规则组注入组两个转换单元。

🌵是stm32 adc的增强功能,普通的ad转换流程是启动一次转换读一次值然后再启动再读值这样的流程,stm32的adc可以列一个组,一次启动一个组连续转换多个值并且有两个组,一个是用于常规使用的规则组,一个是用于突发事件的注入组

  • 模拟看门狗自动监测输入电压范围。

🌵一般可以用于测量光线强度,温度这些值,并且经常会有个需求,就是如果光线高于某个阈值/低于某个阈值或者温度高于某个阈值/低于某个阈值执行一些操作,这个高于某个阈值/低于某个阈值的判断就可以用模拟看门狗来自动执行,模拟看门狗可以监测指定的某些通道,当ad值高于设定的上阈值或低于下阈值时它就会申请中断,就可以在中断函数里执行相应的操作,这样就不用不断地手动读值再用if进行判断了

  • STM32F103C8T6 的ADC资源:ADC1、ADC2,10个外部输入通道。

🌵最多支持16个外部信号源,若想用更多的外部通道,可以选择引脚更多的型号,具体有多少个通道可以参考数据手册

补充知识:

补充get

🌾电位器(滑动变阻器),用电位器可产生一个0-3.3v连续变化的模拟电压信号,用stm32内部的ADC读取电压数据,显示在屏幕上,可以读取AD转换后的原始数据和经过处理后实际的电压值

 🌾stm32的ADC是12位的,所以AD结果最大值是4095,也就是2^12-1,对应的电压是3.3v

对于单片机的普通GPIO来说,只能读取引脚的高低电平,要么是高电平,要么是低电平,只有两个值,而使用了ADC之后,我们就可以对高电平和低电平之间的任意电压进行量化,最终用一个变量来表示,读取这个变量就可以知道这个引脚的具体电压到底是多少了,所以ADC其实就是一个电压表,把引脚的电压测出来放在一个变量里,这就是ADC的作用。

2.🚢逐次逼近型ADC芯片ADC0809

下图为逐次逼近型adc的内部结构,了解这个结构对你学习stm32的adc有很大帮助,因为stm32的adc原理和这个是一样的,但是是他们32只画了一个框表示adc,并没有描述内部结构,所以先介绍一下这个结构,这样再理解stm32的adc就会简单一些,下图为adc0809的内部结构图。

 ADC0809是一个独立的8位逐次逼近型ADC芯片。它拥有IN0~IN7,8个输入通道,通过地址锁存器和译码器电路实现对通道的选择,且每一次转换通道选择开关只能转换一个通道的信号(输入通道选择这部分相当于一个可以通过模拟信号的数据选择器)。ADC转换的速度非常快,从信号转换开始到结束只需要几个us的时间,如果想转换多路信号,不必设计多个ADC,只需要在每一次转换前通过多路选择开关选择要转换的通路即可。 STM32的ADC拥有18个输入通道,与这里的输入通道选择部分8个输入通道的结构相对应。

 接下来如何知道这个电压对应的编码数据是多少呢:就需要用逐次逼近的方法一一比较了。 电压比较器可以判断两个输入信号电压的大小关系,输出一个高低电平指示谁大谁小,两个输入端一个是待测电压另一个是DAC的电压输出端,给dac一个数据它就可以输出数据对应的电压,若dac输出的电压比较大就调小dac数据,若dac输出电压比较小就增大dac数据,直到dac输出电压和外部通道输入的电压近似相等,这样dac输入的数据就是外部电压的编码数据了,这就是dac的实现原理,这个电压调节的过程就是逐次逼近SAR来完成的。ADC内部拥有一个DAC模块,其内部是通过加权电阻网络实现数模转换,可以将逐次逼近寄存器SAR的值转换为对应的模拟电压值,将其电压值再与待测电压相比较,比较结果控制SAR中存储的值,直到DAC输出的电压与外部通道输入的电压近似相等,DAC输入的数据就是外部电压的编码数据了。为了最快找到未知编码的电压,通常使用二分法进行查找。且使用二分法查找未知电压的编码的好处在于:每次选择比较的值(2^n)恰好为对应二进制数字的每一位的权数,判断过程相当于,从高位到底位依次判断为1还是为0的过程,这就是逐次逼近型名字的来源。要找到未知编码的电压,8位ADC需要判断8次,12位ADC需要判断12次,这就是逐次逼近的过程。转换结束后,dac的输入数据就是未知电压的编码,通过8位数字输出端口(D0~D7)进行输出。

结构图上方的EOC(End Of Convert)是转换结束信号。该芯片通过START端口控制转换开始(给一个输入脉冲,开始转换),CLOCK是adc时钟(因为adc内部是一步一步进行判断的所以需要时钟来推进这个过程)控制ADC内部的转换工作频率。V ref ( + )   和V ref ( − )  是DAC的参考电压,定义数据对应的电压范围(比如255对应3.3V还是5V),这个dac的参考电压也决定了adc的输入范围,所以它也是adc参考电压。最后左边vcc和gnd是整个芯片的供电,通常参考电压的正极和VCC是一样的,会接在一起,参考电压的负极和gnd是一样的,也接在一起,所以一般情况下,adc输入电压的范围和adc的供电是一样的。

3.🚢STM32的逐次逼近型ADC

STM32的ADC框图

一般在手册里,每个外设的最前面都有一个整体的结构图,这个结构图还是非常重要的,需要多花时间看看。

STM32中ADC的结构框图如上图所示。总共有18个输入通道包括16个gpio口和2个内部通道(内部温度传感器和内部参考电压)。模拟多路开关可以指定我们想要的通道,右边是多路开关的输出,进入到模数转换器(这里模数转换器就是执行刚讲的逐次比较的过程),转换结果会直接放在数据寄存器里,读取寄存器就能知道adc转换的结构了。

对于普通的adc,多路开关一般都是只选中一个(就是选中一个通道、开始转换、等待转换完成、读取结果,这是普通的流程)。而stm32的多路开关就比较高级,可以同时选中多个,而且在转换的时候还分成了两个组(规则组和注入组),其中规则组可以一次性最多选中16个通道,注入组最多可以选中4个通道。

其“模拟至数字转换器”模块的工作模式与ADC0809在原理上完全相同。不同点有以下几点:

  • 🦄普通的ADC多路开关一般只选中一个,STM32的ADC可以同时选中多个通道进行转换,规则组最多同时选中16个通道,注入组一次最多可以选中4个通道。(以餐厅点菜模型为例,普通模式为每次点一个菜,做好菜后上菜;STM32可以做到每次列出一个菜单,规则组一次最多可以列16个菜,注入组一次最多可以列4个菜,做好后依次上菜)
  • 🦄STM32中的ADC的转换结果会被存储在对应的数据寄存器中。对于规则组通道,其只有一个数据寄存器(餐桌上只能摆一个菜),后转换的数据会将之前转换的数据覆盖,之前转换的数据就会丢失。对于规则组通道,要想实现同时转换的功能,最好配合DMA来将转换后的数据及时转运,DMA可以在每上一个菜之后,把这个菜挪到其它地方去,防止被覆盖,就可以保证转换的数据不会丢失了。对于注入组通道,它拥有4个数据寄存器(餐厅的VIP坐席,餐桌上一次可以摆四个菜)。对于注入组而言,就不用担心数据覆盖的问题了。一般情况下,使用规则组和DMA就可以满足大部分的使用需求。(所以接下来主要讲规则组,注入组涉及的不多,可以看手册自行了解)

  • 🦄结构图的左下角为触发转换信号,对应ADC0809的START信号。STM32的触发转换信号来源有两种:软件触发和硬件触发软件触发就是在程序中手动调用一条代码就可以启动转换了。硬件触发信号可以来自于定时器的各个通道、定时器TRGO定时器主模式的输出,外部中断EXTI
  • 🦄在STM32中,V R E F ( + )  一般和V  DDA ​  (ADC模块的正极供电引脚)接在一起,V R E F ( − )  一般和V SSA ​  ADC模块的负极供电引脚)接在一起。本课程使用的芯片没有单独的V  REF(+) ​  和V  REF(−) ​  的引脚,它在芯片内部就已经和对应引脚连接在一起了。V  DDA ​  和V  SSA ​  是STM32模拟部分的电源,例如ADC、RC振荡器、锁相环等,在套件中的最小系统板中已经将V  DDA ​  与3.3V、V S S A 与GND相连接了)。

  • 🦄这里ADC的时钟ADCCLK是来自于RCC的APB2时钟。由原理图可得,ADCCLK最大为14MHz,所以ADC预分频器只能选择6分频(得到12MHz)和8分频(得到9MHz)两个值

  • 🦄ADC可以通过DMA请求信号触发DMA转运数据。

  • 🦄模拟看门狗的功能是监测指定的通道。可以设置模拟看门狗的阈值高限(12位)、阈值底限(12位)和指定“看门”的通道。只要通道的电压值超过阈值范围,模拟看门狗就会“乱叫”,申请一个模拟看门狗的中断,之后通向NVIC。

  • 🦄EOC规则组的完成信号JEOC注入组完成信号,这两个信号会在状态寄存器里置一个标志位,读取这个标志位就能知道是不是转换结束了,同时这两个标志位也可以去到NVIC申请中断,如果开启了NVIC对应的通道就会触发中断。

定时器可以通向DAC、ADC这些外设用于触发转换,因为ADC经常需要过一个固定时间段转换一次,比如每隔1ms转换一次(正常思路就是用定时器每隔1ms申请一次中断,在中断里手动开始一次转换)但是频繁进中断对我们的程序是由一定影响的,比如你有很多中断都需要频繁进入,那肯定会影响主程序的执行并且不同中断之间由于优先级的不同也会导致某些中断不能及时得到响应,如果触发ADC的中断不能及时响应那adc的转换频率就肯定会产生影响,所以对于这种需要频繁进中断,并且在中断里只完成了简单工作的情况,一般都会有硬件支持(比如可以给tim3定个1ms的时间并且把tim3的更新事件选择为TRGO输出,然后在ADC选择开始触发信号为tim3的TRGO,这样tim3的更新事件就能通过硬件自动触发adc转换了,整个过程不需进中断,节省了中断资源,这就是定时器触发的作用)。

STM32的ADC框图的详细介绍

在这里左边是ADC的输入通道,包括十六个GPIO口,IN0到IN15和两个内部的通道:一个是内部温度传感器,另一个是VREFINT(V Reference Internal)内部参考电压,总共是十八个输入通道。

然后到达这里,这是一个模拟多路开关,可以指定我们想要选择的通道。

右边是多路开关的输出,进入到模数转换器。

这里模数转换器就是执行逐次比较的过程。转换结果会直接放在这个数据寄存器里,我们读取寄存器就能知道ADC转换的结果了。

然后在这里对于普通的ADC,多路开关一般都是只选中一个的,就是选中某个通道开始转换,等待转换完成取出结果,这是普通的流程。

但是这里就比较高级,它可以同时选中多个,而且在转换的时候还分成了两个组,规则通道组和注入通道组。

其中规则组可以一次性最多选十六个通道注入组最多可以选中四个通道

这有什么用

举个例子,这就像是去餐厅点菜,普通的ADC是你指定个菜,老板给做,然后做好了送给你。

而这里就是指定一个菜单,这个菜单最多可以填十六个菜,然后直接递个菜单给老板,老板就按照菜单的顺序依次做好,一次性给端上来,这样的话就可以大大提高效率。

当然你的菜单也可以只写一个菜,这样这个菜单就简化成了普通的模式了。

对于这个菜单,也有两种:

一种是规则组菜单,可以同时上十六个菜,但是它有个尴尬的地方,就是在这里这个规则组只有一个数据寄存器,就是这个桌子比较小,最多只能放一个菜。如果上十六个菜,前十五个菜都会被挤掉,只能得到第十六个菜。所以对于规则组转换来说,如果使用这个菜单的话,最好配合DMA来实现,DAM是一个数据转运小帮手,它可以在每上一个菜之后,把这个菜挪到其它地方去,防止被覆盖(被挤掉)。

🐟️🐟️因此,这个规则组虽然可以同时转换十六个通道,但是数据寄存器只能存一个结果。如果不想之前的结果被覆盖,在转换完成之后,就要尽快把结果拿走。

接着我们看一下注入组。

这个组比较高级,它相当于是餐厅的vip座位,在这个座位上,一次性最多可以点四个菜。并且这里数据寄存器有四个,是可以同时上四个菜的。对于注入组而言就不用担心数据覆盖的问题了。

这就是规则组和注入组的介绍。

一般情况下我们使用规则组就完全足够了。如果要使用规则组的菜单,就再配合DMA转运数据,这样就不用担心数据覆盖的问题了。

所以接下来只讲规则组的操作。

模数转换器外围线路

我们接着继续看这个模数转换器外围的一些线路。

首先左下角这里是触发转换的部

也就是这里的start信号开始转换。

对于STM32的ADC,触发ADC开始转换的信号有两种:

🌵一种是软件触发,就是在程序中手动调用一条代码就可以启动了。

🌵另一种是硬件触发就是这里的这些触发源。上面这些是注入组的触发源,下面这些是规则组的触发源。

 

这些触发源主要是来自于定时器,有定时器的各个通道,还有TRGO定时器主模式的输出。

这个之前讲定时器的时候也介绍过,定时器可以通向ADC/DAC这些外设用于触发转换。因为ADC经常需要过一个固定时间段转换一次,比如每隔一毫秒转换一次,正常的思路就是用定时器每隔一毫秒申请一次中断,在中断里手动开启一次转换,这样也是可以的。但是频繁进中断对我们的程序是有一定影响的。比如有很多中断都需要频繁进入,肯定会影响主程序的执行,并且不同中断之间,由于优先级的不同,也会导致某些中断不能及时得到响应。如果触发ADC的中断不能及时响应,那么ADC的转化频率就肯定会产生影响了。

所以对于这种需要频繁进中断,并且在中断里只完成了简单工作的情况,一般都会有硬件的支持。

比如这里就可以给TIM3定一个一毫秒的时间。并且把TIM3的更新事件选择为TRGO输出。然后在ADC这里选择开始触发信号为TIM3的TRGO。这样TIM3的更新事件就能通过硬件自动触发ADC转换了。

整个过程不需要进中断,节省了中断资源,这就是这里定时器触发的作用。

当然这里还可以选择外部中断引脚来触发转换,都可以在程序中配置。

这就是触发转换的部分。

然后接着看左上角

vref+,vref-是ADC的参考电压,决定了ADC输入电压的范围。VDDA和VSSA是ADC的的共电引脚。

一般情况下,vref+要接VDDA,vref-要接VSSA。在我们这个芯片上,没有vref+和vref-的引脚。它在内部就已经和VDDA和VSSA接在一起了。

VDDA和VSSA在这个引脚定义里也可以看到,VDDA和VSSA是内部模拟部分的电源,比如ADC、RC振荡器,锁相环等。

 

在这里VDDA接3.3V,VSSA接GND,所以ADC的输入电压范围就是0到3.3V。

右边这里是ADC CLK是ADC的时钟 

也就是这里的clock

是用于驱动内部逐次比较的时钟,它是来自ADC预分频器,

 

这个ADC预分频器是来源于RCC,在定时器中断那节我们所讲过的RCC时钟树框图里的这里

 

APB2时钟72MHz,然后通过ADC预分频器进行分频,得到ADC CLK,ADC CLK最大是14MHz。

 

这个预分频器选择二四六八分频。如果选择二分频,七十二兆除以二等于三十六兆,超出允许范围了。四分频之后是十八兆也超了。所以对于ADC分频器只能选择六分频,结果是十二兆八分结果是九兆这两个值这个在程序里要注意一下。

继续看上面这里是DMA请求,

这个就是用于触发DMA进行数据转运的,我们下节再讲。

然后是两个数据寄存器用于存放转换结果的。

 

上面这里还有模拟看门狗,它里面可以存一个阈值高限和阈值低限。

 

如果启动了模拟看门狗,并且指定了看门的通道,这个看门狗就会关注它看门的通道。一旦超过这个阈值范围了,它就会乱叫,就会在上面申请一个模拟看门狗的中断,最后通向NVIC。

 

对于规则组和注入组而言,它们转换完成之后,也会有一个EOC转换完成的信号。在这里EOC是规则组的完成信号。JEOC是注入组完成的信号。

 

这两个信号会在状态寄存器里置一个标志位我们读取这个标志位就能知道是不是转换结束了。同时,这两个标志位也可以去到NVIC,如果开启了NVIC对应的通道,它们就会触发中断。 

 有关ADC的这个框图就介绍完了。

 

STM32的ADC基本结构总结

如下图,左边是输入通道,16个gpio口外加两个内部通道,然后进行AD转换器,ad转换器里有两个组,一个是规则组、一个是注入组,规则组最多可以选中16个通道。注入组最多可以选择4个通道,然后转换的结果可以存放在AD数据寄存器里,其中规则组有1个数据寄存器,注入组有4个,然后有触发控制提供了开始转换的START信号,触发控制可以选择软件触发和硬件触发硬件触发主要来自定时器,也可以选择外部中断引脚,然后还有ADC时钟CLOCK来自RCC,adc逐次比较的过程就是由这个时钟推动的,然后可以布置一个模拟看门狗用于检测转换结果的范围,如果超出设定的阈值就通过中断输出控制向NVIC申请中断,另外规则组和注入组转换完成后会有个EOC信号会置一个标志位,当然也可以通向NVIC,最后还有个右下角有个开关控制,在库函数中就是ADC_Cmd函数用于给ADC上电,以上就是STM32 ADC的内部结构了

 STM32的ADC输入通道和引脚的关系

由ADC的内部结构可知,STM32的ADC对应16个输入通道。这16个输入通道对应的GPIO端口如下表所示:

上表展示了ADC通道和引脚复用之间的连接关系,这个对应关系也可以参考引脚定义表。可以看到,只有ADC1拥有温度传感器和内部参考电压的采样通道。ADC1和ADC2的引脚完全相同,ADC3有些是存在变化的。本节课程使用的STM32F103C8T6没有PC0到PC5的引脚,故也就不存在通道10到通道15。

参考下面引脚定义表可以看到,STM32的ADC1和ADC2的引脚是相同的。这样的设计是为双ADC模式服务的。关于双ADC模式的内容比较复杂,这里仅作简单了解即可。双ADC模式,即ADC1和ADC2同时工作,二者可以配合为同步模式、交叉模式等多种不同的工作模式。以交叉模式为例,ADC1和ADC2交叉对同一个通道进行采样,这样就可以进一步提高采样率(交叉模式就像你打拳一样,左手打一拳、右手打一拳快速交叉地打拳,那打击的频率肯定比一个拳头打得快)。当然ADC1和ADC2也是可以分开使用的,可以分别对不同的引脚进行采样,这样也是可以的

注:引脚定义表中例如ADC12_IN0,的意思是ADC1和ADC2的IN0都是在PA0上。

STM32的ADC规则组的四种转换模式

 STM32中的ADC规则组的转换模式有以下四种:

🌵单次转换  非扫描模式

🌵单次转换  扫描模式

🌵连续转换  非扫描模式

🌵连续转换  扫描模式 

精华提取: 

🦄单次转换:每触发一次,转换结束就会停下来,下次转换就得再触发才能开始。

🦄连续转换: 一次转换完成后不会停止,而是立刻开始下一轮的转换,并持续下去。

🦄非扫描模式:只对存放在序列1的通道起作用

🦄扫描模式:用到“菜单”列表,可以在菜单里点菜,每个菜单列表位置是通道几是可以任意指定的并且可以重复,然后初始化结构体有个通道数目的参数(表明用了几个通道)

🦄扫描模式下转换到数据寄存器的过程中,用DMA防止数据被覆盖,DMA进行数据及时转移

🦄在扫描模式的情况下,还可以使用间断模式。它的作用是在扫描的过程中,每隔几次转换就暂停,需要再次触发才能继续。该模式仅作了解即可。

  • 单次转换非扫描模式

  如下列表就是规则组的菜单,有16个空位,分别是序列1~16,你可以在列表点菜就是写入你要转换的通道,在非扫描的模式下,这个菜单就只有一个序列1的位置有效,这时菜单同时选中一组的方式就退化为简单地选中一个的方式了,可以在序列1的位置指定我们想转换的通道,比如通道2写到这个位置,然后就可以触发转换,adc就会对通道2进行模数转换,过一小段时间后,转换完成,转换结果放在数据寄存器里,同时给EOC标志位置1,整个转换过程就结束了,然后判断EOC标志位,如果转换完了就可以在数据寄存器里读取结果了,若想再启动一次转换就需要再触发一次,转换结束,置EOC标志位,读结果,若想换一个通道转换,那就在转换之前把第一个位置的通道2改成其它通道,然后再启动转换就行了,以上就是单次转换非扫描模式 ,没有用到菜单列表是比较简单地一种模式。

  • 连续转换非扫描模式

首先连续转换非扫描模式是非扫描模式,所以菜单列表只用第一个,与上一种单次转换非扫描模式不同的是,它在一次转换结束后不会停止,而是立刻开始下一轮的转换,然后一直持续下去,这样就只需要最开始触发一次,之后就可以一直转换了,这个模式的好处是开始转换之后就不需等待一段时间,因为它一直都在转换,所以不需手动开始转换了也不用判断是否结束,想读ad值的时候直接从数据寄存器读取,以上就是连续转换非扫描模式

  • 单次转换扫描模式

每触发一次,转换结束就会停下来,下次转换就得再触发才能开始。扫描模式用到“菜单”列表,可以在菜单里点菜,每个菜单列表位置是通道几是可以任意指定的并且可以重复,然后初始化结构体有个通道数目的参数(表明用了几个通道)

每次触发之后,就会依次对前7(通道数目)个位置进行AD转换,转换结果都放在数据寄存器里,为了防止数据被覆盖,就需要用DMA及时将数据挪走7个通道转换完成后产生EOC信号,转换结束,然后再触发下一次,就又开始新一轮的转换,以上就是单次转换扫描模式。

  •  连续转换扫描模式

连续转换扫描模式与单次转换扫描模式不同之处就是一次转换完成后,立刻进行下一次的转换

STM32的ADC规则组的触发源

规则组的触发源如下表所示

有来自定时器的信号、来自引脚或定时器的信号(具体是引脚还是定时器需要用AFIO重映射来确定)、软件控制位(就是软件触发)

触发信号的选择可以通过设置寄存器来完成EXTSEL[2:0],当然使用库函数的话直接给一个参数就行了

数据对齐

STM32中的ADC是12位的,但是数据寄存器拥有16位,故存在数据对齐的问题。数据右对齐,即作为转换结果的12位数据向右靠,高位补0;数据左对齐,即作为转换结果的12位数据向左靠,低位补0。在使用时通常使用数据右对齐,这样在读取时直接读取寄存器即可。如果选择左对齐直接读取,得到的数据会比实际的数据大16倍。当对分辨率的要求不高时(对电压仅作大概的判断即可)可以采用左对齐,将数据寄存器的高8位取出,就相当于舍弃了转换结果的4位的精度,12位的ADC退化位为8位的ADC。

注:二进制中,数据左移一次,就等效于把这个数据乘2,左移4次就相当于把结果乘16

AD转换时间

AD的转换时间是一个很短的时间,如果不需要极高的转换频率,那么转换时间是可以忽略的。那么转换时间具体是多少呢?
  AD转换的步骤分别是:采样、保持、量化、编码。其中采样和保持可以看作一个过程,量化和编码可以看作一个过程。量化和编码实际上就是ADC逐次比较的过程,一般ADC的位数越多,所花费的时间就越长。采样和保持是为了保证在量化和编码的过程中输入电压的变化不会过大。在量化和编码之前,需要添加采样-保持电路,即需要设置一个采样开关,打开开关一段时间来收集电压(可以用一个小容量的电容来存储这个电压),存储完成之后断开开关,再进行之后的AD转换。这样就可以保证在量化和编码器件始终保持电压基本不变。这个采样时间是比较长的。ADC的采样时间可以在程序中进行配置。之后花费12个ADC周期进行量化和编码,多余的0.5个周期完成了其他的工作。

  所以AD转换所花费时间为:

采样-保持电路的采样时间 + 量化和编码花费的时间(12.5个ADC周期)。

即STM32 ADC总转换时间 = 采样时间 + 12.5个ADC周期

ADC周期就是从RCC分频过来的ADCCLK,ADCCLK最大是14MHz

最短的转换时间:当ADCCLK = 14MHz,采样时间为1.5个ADC周期时:ADC总转换时间为1us

这就是最快1us时间的来源,如果采样周期再长些就达不到1us了。当然,可以通过设置将ADC的转换频率超过14MHz,这样ADC就会工作在超频状态下。超频时转换时间可能会更短,不过电路的稳定性将无法保证。

ADC校准

ADC有一个固定的内置自校准模式。校准可大幅减小因内部电容器组的变化而造成的准精度误差。校准期间,在每个电容器上都会计算出一个误差修正码(数字值),这个码用于消除在随后的转换中每个电容器上产生的误差。建议在每次上电后执行依次校准,且启动校准前,ADC必须处于关电状态超过至少两个ADC周期。(不需要理解,这个校准过程是固定的,只需要在ADC初始化的最后加几条代码就行了,至于如何计算如何校准,不需管)

ADC的外围电路

第一个是电位器产生可调电压的电路。电位器产生一个可调电压,这里电位器的两个固定端,一端接3.3v一端接gnd,这样中间的滑动就可以输出一个0~3.3v可调的电压输出,可以接adc的输入通道比如PA0口,当滑动端往上滑时,电压增大,往下滑时电压减小,注意电阻的阻值不能给太小因为电阻两端也是直接跨接在电源正负极的,如果阻值太小电阻就会比较费电,再小就有可能发热冒烟 ,一般至少接kΩ级的电阻,比如这里接的是10k电阻.

第二个是分压方法来输出传感器阻值的电路。一般来说像光敏电阻、热敏电阻、红外接收管、麦克风等都可以等效为可变电阻N1,电阻值无法直接测量,所以就可以通过和一个固定电阻串联分压来得到一个反应电阻值的电压的电路。传感器N1阻值变小时,下拉作用变强,输出端PA1电压就下降;传感器N1阻值变大时,下拉作用变弱,输出端PA1受上拉电阻的作用,电压就会升高。固定电阻R1一般可以选择和传感器N1阻值相近的电阻,这样可以得到一个位于中间电压区域比较好的输出,当然这里的固定电阻R1和传感器N1的位置也可以缓过来,这样输出电压的极性就反过来了。

第三个是简单的电压转换电路。比如你想测一个0-5v的VIN电压,但是ADC只能接受0-3.3v的电压,那就可以使用这样的简易转换电路,还是使用电阻进行分压,上面电阻r1阻值17k,下面阻值r2是33k,一共是50k,根据分压公式,中间的电压就是VIN/50K * 33k最后得到的电压范围就是0-3.3v,就可以进入adc转换了,若想采集5v、10v这些电压的话就可以使用这个电路,但是若电压再高些就不建议使用这个电路了可能会比较危险,高电压采集最好使用一些专用的采集芯片,比如隔离放大器等,做好高低电压的隔离,保证电路的安全


http://www.mrgr.cn/news/58562.html

相关文章:

  • CTF-RE 从0到N:汇编层函数调用
  • 【python】OpenCV—Sort the Point Set from Top Left to Bottom Right
  • 分页列表缓存
  • 赫夫曼树算法:原理、应用与深入解析
  • 全面指南:在 Vue 中优雅封装 HTML <dialog> 组件
  • 理解 `super(...)` 和 `this(...)` 的区别
  • Isaac Sim Docker 部署并使用过程记录
  • 【数据结构和算法】二、python中的常用数据结构(数组、链表、堆栈、递归、二叉树、哈夫曼树等数据结构的基本原理讲解与实战演练)
  • 尼日利亚CRIA解析
  • c++实现boost搜索引擎功能扩展 介绍+代码(日志,处理暂停词,增加数据源,引入广告竞价,增加用户管理,连接mysql)
  • Nestjs请求处理顺序
  • 【信息系统管理工程师】与【信息系统项目管理师】傻傻分不清楚?一文说清楚
  • 谷歌开发者账号,为什么新号老是因为高风险被封?
  • 如何将原本打开Edge呈现出的360浏览器,更换成原本的Edge页面或者百度等其他页面
  • uniapp开发Web页面之动态菜单配置攻略
  • LEG引擎装备升级脚本,BLUE引擎传奇添加升级装备的NPC示例
  • 卷积神经网络评价指标
  • 客服的沟通技巧与策略
  • Sei 生态迎首个 MMORPG 游戏伙伴 Final Glory,开启新篇章
  • [Java进阶] 并发编程之进程、线程和协程
  • 23种设计模式
  • Vue3 + TypeScript 实现 iframe 嵌入与通信的完整指南以及全屏弹窗方案
  • 动态规划-子序列问题——376.摆动序列
  • 青训营 X 豆包MarsCode 技术训练营--最大矩形面积问题
  • MATLAB锂电概率分布模型
  • 微积分复习笔记 Calculus Volume 1 - 3.7 Derivatives of Inverse Functions