07 STM32ADC

AD单通道和AD多通道

使用ADC可以对高电平和低电平之间的任意电压进行量化,最终用一个变量来表示,读取这个变量。所以ADC就是一个电压表,把引脚电压值测出来,放在一个变量里。

在这里插入图片描述
数字到模拟的桥梁,PWM来控制电机的速度,LED灯的亮度。这是DAC的功能,同时PWM只有完全导通和完全断开两种状态,两种状态上都没有功率损耗,所以在直流电机调速这种大功率的应用场景,使用PWM来等效模拟量,是比DAC更好的选择,并且PWM电路更加简单,更加常用,所以可以看出PWM还是挤占了DAC的很多应用空间。
目前DAC的主要应用是在波形生成这些领域,比如信号发生器、音频解码芯片等。这些领域PWM还是不好替代的。
一般12位AD值,它的表示范围就是0-212-1。这里涉及到ADC的两个关键参数了,第一个是分辨率,一般用多少位来表示,12位AD值,量化结果的范围就是0-4095,位数越高,量化结果就越精细,对应分辨率就越高。
第二个是转换时间,就是转换频率,AD转换是需要花一小段时间的,这里的1us就表示从AD转换开始,到产生结果,需要花1us的时间,对应AD转换的频率就是1MHz,这个就是STM32 ADC的最快转换频率。如果需要转换一个频率非常高的信号,那就要考虑一下这个转换频率是不是够用,如果你的信号频率比较低,那这个最大1MHz的转换频率也完全够用了。
输入电压范围,一般要求都是在芯片供电的负极和正极之间变化的,最低电压就是负极0V,最高电压就是正极3.3V,经过ADC转换之后,最小值就是0,最大值是4095,0V对应0,3.3V对应4095,中间都是一一对应的线性关系。
外部信号就是16个GPIO口,在引脚上直接接模拟信号就行了,不需要任何额外的电路,引脚就直接能测电压,2个内部信号时内部温度传感器和内部参考电压,温度传感器可以测量CPU的温度,比如电脑可以显示一个CPU温度,内部参考电压是一个1.2V左右的基准电压,这个基准电压是不随外部供电电压变化而变化的,所以如果芯片的供电不是标准的3.3V,那测量外部引脚的电压可能就不对,这时可以读取这个基准电压进行校准,这样就可以得到正确的电压值了。
规则组和注入组两个转换单元,就是STM32ADC的增强功能了,普通的AD转换流程是,启动一次转换,读一次值,然后再启动,再读值,这样的流程,但是STM32的ADC就比较高级,可以列一个组,一次性启动一个组,连续转换多个值,并且有两个组,一个是用于常规使用的规则组,一个是用于突发事件的注入组。
ADC一般可以用于测量光线强度,温度这些值,可以用模拟看门狗来自动执行若高于某个阈值进行一些操作。模拟看门狗可以检测指定的某些通道,当AD值高于它设定的上阈值或者低于下阈值时,他就会申请中断,你就可以在中断函数里执行相应的操作。这样就不用不断地手动读值,再用if进行判断了。

在这里插入图片描述
这是逐次逼近性ADC的内部结构,了解这个结构对学习STM32的ADC帮助很大。
这个图是ADC0809的内部结构图,它是一个独立8位逐次逼近型ADC芯片,在以前单片机性能还不是很强的时候,需要外挂一个ADC芯片才能进行AD转换,这个ADC0809是一款比较经典的ADC芯片,现在单片机的性能和集成度都有很大的提升,,很多单片机内部就集成了ADC外设,这样就不用外挂芯片了,引脚可以直接测电压,使用还是非常方便的。
左边IN0-IN7,是8路输入通道,通过通道选择开关,选中一路,输入到一点进行转换。
下面是地址锁存和译码,就是你想选中哪个通道,就把通道号放在这三个脚上,然后给一个锁存信号,上面这里对应的通路开关就可以自动拨好了,这部分就相当于一个可以通过模拟信号的数据选择器,因为ADC转换是一个很快的过程,给个开始信号,过几个us就转换完成了,所以说想要转换多路信号,那不必设计多个AD转换器,只需要一个AD转换器,然后加一个多路选择开关,想转换哪一路,就先拨一下开关,选中对应通道,然后再开始转换就行了,这就是输入通道选择的部分,这个ADC0809只有8个输入通道。然后输入信号选好,到比较器。怎样才能知道这个电压对应的编码数据是多少呢,这就需要我们用逐次逼近的方法来一一比较了。
首先是一个电压比较器,可以判断两个输入信号电压的大小关系,输出一个高电平指示谁大谁小,它的两个输入端,一个是待测电压,另一个是DAC的电压输出端,DAC内部使用加权电阻网络来实现的转换,现在有了一个外部通道输入的,未知编码的电压,和DAC输出的已知编码的电压,同时到电压比较器,进行大小判断,如果DAC输出的电压比较大,我就调小DAC数据,如果比较小,就增大DAC数据,直到DAC输出的电压和外部通道输入的电压近似相等。这样DAC输入的数据就是外部电压的编码数据了,这就是DAC的实现原理。电压调节的过程就是逐次逼近SAR来完成的,为了最快找到未知电压的编码,通常我们会使用二分法进行寻找,会发现128,64,32这些数据,正好是二进制每一位的位权,判断过程就是二进制从高位到低位依次判断是1还是0的过程。这就是逐次逼近型名字的由来。对于8位ADC,从高位到低位依次判断8次就能找到未知电压的编码了。AD转换后,DAC的输入数据,就是未知电压的编码,
EOC End Of Convert 转换结束信号
START 开始转换,给一个输入脉冲,开始转换。
CLOCK 是ADC的时钟,因为ADC内部是一步一步进行判断的。 需要时钟来推动这个过程。
VREF+和VREF-是DAC的参考电压,比如给一个数据255,是对应5V还是3.3V,这个DAC的参考电压也决定了ADC的输入范围,所以它也是ADC参考电压,最后左边是整个芯片电路的供电,VCC和GND,通常低要求时,参考电压的正极和VCC是一样的,接到一起。参考电压的负极和GND也是一样的,也接在一起。
所以一般情况下,ADC输入电压的范围和ADC的供电是一样的。

STM32的ADC和这个ADC0809有什么区别呢,看一下ADC框图

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

左边是ADC的输入通道,包括16个GPIO口,IN0-IN15
另一个是VREFINT (V Reference Internal),内部参考电压
总共18个通道,到一个模拟多路开关,指定我们想要选择的通道。

右边是多路开关的输出,进入到模数转换器,这里的模数转换器就是执行刚才讲的逐次比较的过程。转换结果会直接放在这个数据寄存器里,我们读取寄存器就能知道ADC转换的结果了。
对于普通的ADC,多路开关一般都是只选中一个的,就是选中某一个通道,开始转换、等待转换完成、取出结果。但是这里比较高级,可以同时选中多个,而且在转换是,还分成了两个组,规则通道组和注入通道组,其中规则组一次性最多选中16个通道,注入组最多可以选中4个通道。
举个例子:就像是去餐厅点菜,普通的ADC是指定一个菜,老板给你做,然后做好了送给你,这里就是指定一个菜单,这个菜单最多可以填16个菜,直接把菜单寄给老板,老板就按照菜单的顺序依次做好,一次性给你端上菜,这样的话可以大大提高效率,这样这个菜单就简化成普通的模式了。那对于这个菜单也有两种,一种规则组菜单,可以同时上16个菜,有个尴尬的地方,就是这个规则组只有一个数据寄存器,就是这个桌子比较小,最多只能放一个菜,如果要上16个菜,那不好意思,前15个菜都会被挤掉,只能得到第16个菜,所以对于规则组转换来说,如果使用这个菜单的话,最好配合DMA来实现,DMA是一个数据转运小帮手,它可以在每上一个菜之后,把这个菜挪到其他地方去,防止被覆盖。

规则组虽然可以同时转换16个通道,但是数据寄存器只能存一个结果,如果不想之前的结果被覆盖,那在转换之后,就要尽快把结果拿走。
注入组就比较高级了,相当于餐厅的VIP座,在这个座位上,一次性最多可以点4个菜,并且这里数据寄存器有4个,是可以同时上4个菜的,对于注入组而言,就不用担心数据覆盖的问题了,一般情况下,使用规则组就完全足够了。如果要使用规则组的菜单,那就再配合DMA转运数据,就不用担心数据覆盖的问题。

注入组的操作:涉及的不多,可以看手册自行了解。
规则组的操作:先看模数转换器外围的一些线路,首先左下角是触发转换的部分,也就是ADC0809的START信号,开始转换。
对于STM32的ADC,触发ADC开始转换的信号有两种,一种是软件触发,就是在程序中手动调用一条代码,就可以启动转换了;另一种是硬件触发,就是这里的这些触发源。上面是注入组的触发源,下面是规则组的触发源。这些触发源主要是来自于定时器,,有定时器的各个通道,还有TRGO定时器主模式的输出,定时器可以通向ADC、DAC这些外设,用于触发转换,因为ADC经常需要过一个固定时间段转换一次,比如每隔1ms转换一次。正常的思路就是用定时器,每隔1ms申请一次中断,在中断里手动开始一次转换,这样也是可以的。但是频繁进中断对我们的程序是由一定影响的。
比如有很多中断都需要频繁进入,那肯定会影响主程序的执行,并且不同中断之间,由于优先级的不同,也会导致某些中断不能及时得到响应。那我们ADC的转换频率就肯定会产生影响了,所以对于这种需要频繁进中断,并且在中断里只完成了简单工作的情况,一般都会有硬件的支持。
比如这里给TIM3定1ms的时间,并且把TIM3的更新事件选择为TRGO输出,然后在ADC这里,选择开始触发信号为TIM3的TRGO,这样TIM3的更新事件就能通过硬件自动触发ADC转换了,整个过程不需要进中断,节省了中断资源。这就是这里定时器的触发作用。
当然这里还可以选择外部中断引脚来触发转换,都可以在程序中配置,VREF+和VREF-是ADC的参考电压,决定了ADC输入电压的范围,一般情况下(简单情况)VREF+接VDDA,VREF-接VSSA,在这个芯片上,没有VREF+和VREF-的引脚,它在内部就已经和VDDA和VSSA接在一起了。 VDDA和VSSA是内部模拟部分的电源,比如ADC,RC振荡器、锁相环等。在这里VDDA接3.3V,VSSA接GND,所以ADC的输入电压范围就是0-3.3V。
右边的ADCCLK是ADC的时钟,也就是0809的CLOCK,是用于驱动内部逐次比较的时钟。这个ADC预分频器是来源于RCC的。
DMA的请求:是用于触发DMA进行数据转运的,DMA章节再讲。
两个数据寄存器,是用于存放转换结果的。
模拟看门狗,里面可以存一个阈值高限和阈值低限,如果启动了模拟看门狗,并指定了看门的通道,那这个看门狗就会关注它看门的通道,一旦超过这个阈值范围了,它就会乱叫,就会在上面,申请一个模拟看门狗的中断,最后通向NVIC。然后对于规则组和注入组而言,它们转换完成之后,也会有一个EOC规则组转换完成的信号,JEOC是注入组完成的信号,这两个信号会在状态寄存器里置一个标志位,我们读取这个标志位,就能知道是不是转换结束了,同时这两个标志位也可以去NVIC,申请中断,如果开启了NVIC对应的通道,它们就会触发中断,。

ADC基本结构图
在这里插入图片描述
左边是输出通道,16个GPIO口,外加两个内部的通道,然后进入AD转换器(有两个组,一个规则组,一个注入组),规则组最多可以选中16个通道,注入组最多可以选择4个通道,然后转换的结果可以存放在AD数据寄存器里,其中规则组只有1个数据寄存器,注入组有4个,触发控制提供了开始转换这个START信号,触发控制可以选择软件触发和硬件触发。硬件触发主要是来自于定时器,当然也可以选择外部中断的引脚,右边这里是来自于RCC的ADC时钟CLOCK,ADC的逐次比较的过程就是由这个时钟推动的。然后上面可以布置一个模拟看门狗用于监测转换结果的范围。

最后右下角还有一个开关控制,在库函数中,就是ADC_Cmd函数,用于给ADC上电的,这些就是STM32 ADC的内部结构了。

接下来是一些细节问题:
在这里插入图片描述
16个通道对应的都是哪些GPIO口呢,
ADC通道和引脚复用的关系,可以从数据手册看出来。
ADC12_IN0的意思是,ADC1和ADC2的IN0都是在PA0上的,
再说一个ADC的高级功能,就是双ADC模式,这个模式比较复杂,只需要简单了解一下,暂时不需要掌握。
双ADC模式就是ADC1和ADC2一起工作,它俩可以配合组成同步模式、交叉模式等等模式,比如交叉模式:ADC1和ADC2交叉地对一个通道进行采样,就可以进一步提高采样率。
当然ADC1和ADC2可以分开使用。可以分别对不同的引脚进行采样。

规则组的4种转换模式:
在ADC初始化的结构体里,会有两个参数:一个是选择单词转换还是连续转换的,另一个是选择非扫描模式还是扫描模式,这两个参数组合起来,就有4种转换方式。

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

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

在这里插入图片描述
单次转换,每触发一次,转换结束后,就会停下来,下次转换得再触发才能开始。
然后扫描模式就用到这个菜单列表了,可以在这个菜单里点菜,比如第一个菜是通道2,第二个菜是通道5,等等,这里每个位置是通道几可以任意指定,并且也是可以重复的,。然后初始化结构体有个参数,就是通道数目,因为这16个通道可以不用玩,只用前几个,那就需要再给他一个通道数目的参数,告诉它,我有几个通道,比如这里指定通道数目为7,那它就只看前7个位置,,然后每次触发之后,它就一次对这前7个位置进行AD转换,转换结构都放在数据寄存器里,这里为了防止数据被覆盖,就需要用DMA及时将数据挪走,那7个通道转换完成之后,产生EOC信号,转换结束,然后再触发下一次,就开始新一轮的转换,这就是单次转换,扫描模式的工作流程。

在这里插入图片描述
一次转换完成后,立刻开始下一次的转换。和上面的非扫描模式的单次和连续是一个套路。

当然在扫描模式的情况下,还可以有一种模式,叫间断模式,它的作用是,在扫描的过程中,每隔几个转换,就暂停一次。需要再次触发,才能继续,
这个模式没有列出来,不然要列出来的太多了。

在这里插入图片描述
这个表是规则组的触发源:有来自定时器的信号,还有来自引脚或定时器的信号,具体是引脚还是定时器,需要用AFIO重映射来确定。。
软件控制位也就是我们之前说的软件触发。这些触发信号怎么选择,可以通过设置右边的寄存器来完成,,当然使用库函数的话,直接给一个参数就行了。这就是触发控制,

在这里插入图片描述
我们这个ADC是12位的,它的转换结果就是一个12位的数据,但是这个寄存器是16位的,所以就存在一个数据对齐的问题,就是12位的数据向右靠,高位多出来几位就补0,是12位的数据向左靠,低位多出来的几位补0,在这里我们一般使用的都是第一种右对齐,这样读取这个16位寄存器,直接就是转换结果,如果直接选择左对齐,直接读的话,得到的数据会比实际的大,因为数据左对齐实际上就是把数据左移了4次,二进制有一个特点,就是数据左移一次,等效于把这个数据乘2,这个用途就是,如果你不需要这么高的分辨率,觉得0-4095太大了,就做个简单的判断,不需要这么高分辨率,那就可以选择左对齐,然后再把这个数据的高8位取出来,这样就舍弃了后4位的精度,这个12位的ADC就退化成了8位的ADC了,如果需要裁剪一些分辨率,大不了先把12位都取出来,再做处理,这也是可以的,只是多算一步而已。

在这里插入图片描述
一般不敏感,因为一般AD转换都很快,如果不需要非常高速的转换频率,那转换时间就可以忽略了,AD转换需要一小段时间,就像厨子做菜一样,也需要等待一会才能上菜的。
采样保持可以放在一起,量化编码可以放在一起,总共是这两大步。量化编码就是之前讲的ADC逐次比较的过程。这个需要花一段时间,一般位数越多,花的时间就越长。
采样保持是因为 AD转换后面的量化编码,是需要一小段时间的,如果在这一小段时间里,输入电压还在不断变化,那就没法定位输入电压到底在哪里了,所以在量化编码之前,需要设置一个采样开关,比如可以用一个小容量的电容存储一下这个电压,存储好了之后,断开采样开关,在进行后面的AD转换。这样在量化编码的过程中,电压始终保持不变,这就是采样保持电路。
那采样保持的过程,需要闭合采样开关,过一段时间再断开,这里就会产生一个采样时间,那回到这里这里,我们就得到了第二条。
采样时间就是采样保持花费的时间,这个可以在程序中进行配置,采样时间越大,越能避免一些毛刺信号的干扰,不过转换时间也会相应延长,12.5个ADC周期是量化编码花费的时间,因为是12位的ADC,所以需要花费12个周期,这里多了半个周期,可能是做其他一些东西画的时间。ADC周期就是从RCC分频过来的ADCCLK,这个ADCCLK最大是14MHz,所以下面有个例子,这里就是最快的转换时间。

如果采样周期再长些,它就达不到1us了,另外也可以把ADCCLK的时钟设置超过14MHz,这样就是在超频了,那转换时间可以比1us还短,不过这样稳定性就没办法保证了

在这里插入图片描述
听起来很复杂,但是这个校准我们暂时不需要理解,因为校准过程是固定的,我们只需要在ADC初始化最后,加几条代码就行了,至于怎么计算,怎么校准的,我们不需要管,所以了解一下就行了

在这里插入图片描述
ADC的外围电路
第一个是电位器产生一个可调的电压,电阻阻值不能给的太小,
第二个是传感器输出电压的电路,一般来说,像光敏电阻,热敏电阻,红外接收管,麦克风等等,都可以等效为一个可变电阻,所以这里就可以通过和一个固定电阻串联分压,这个福鼎电阻一般可以选择和传感器阻值相近的电阻。这样可以得到一个位于中间电压区域比较好的输出。
第三个是电压转换电路,使用电阻进行分压,但是如果是高电压采集最好使用一些专用的采集芯片,比如隔离放大器等等,做好高低电压的隔离,保证电路的安全

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值