STM32—ADC模数转换器

1. ADC简介

  • ADC(Analog-Digital Converter)  模拟-数字转换器
  • ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁
  • 12位逐次逼近型ADC,1us转换时间
  • 输入电压范围:0~3.3V,转换结果范围:0~4095(2的12方-1)
  • 18个输入通道,可测量16个外部和2个内部信号源
    • 外部信号源就是16个GPIO口,在引脚上直接接模拟信号就行了,不需要任何额外的电路,引脚就直接能测电压
    • 2个内部信号源是内部温度传感器和内部参考电压,温度传感器可以测量CPU的温度,比如你电脑可以显示一个CPU温度,就可以用ADC读取这个温度传感器来测量,内部参考电压是一个1.2V左右的基准电压,这个基准电压是不随外部供电电压变化而变化的,所以如果你芯片的供电不是标准的3.3V,那测量外部引脚的电压可能就不对,这时就可以读取这个基准电屈进行校准,这样就能得到正确的电压值了
  • 规则组和注入组两个转换单元
    • STMB2 ADC的增强功能了,普通的AD转换流程是,启动一次转换、读一次值, 然后再启动、再读值,这样的流程,但是STM32的ADC就比较高级,可以列一个组,一次性启动一个组,连续转换多个值,并且有两个组,一个是用于常规使用的规则组,一个是用于突发事件的注入组
  • 模拟看门狗自动监测输入电压范围
    • 一般可以用于测量光线强度、温度这些值,并且经常会有个需求,就是如果光线高于某个阀值、低于某个阀值,或者温度高于某个阀值、低于某个阈值时,执行一些操作,这个高于某个阈值、低于某个阀值的判断,就可以用模拟看门狗来自动执行
    • 模拟看门狗可以监测指定的某些通道,当AD值高于它设定的上阈值或者低于下阈值时,它就会申请中断,你就可以在中断函数里执行相应的操作,这样你就不用不断地手动读值,再用if进行判断了
  • STM32F103C8T6 ADC资源:ADC1、ADC2,10个外部输入通道

2. 逐次逼近型ADC

ADC0809的内部结构图,官是一个独立的8位逐次逼近型ADC芯片,在以前的时候,单片机的性能还不是很强,所以需要外挂一个ADC芯片才能进行AD转换,这个ADC0809就是一款比较经典的ADC芯片,那现在单片机的性能和集成度都有很大的提升,很多单片机内部就已经集成了ADC外设,这样就不用外挂芯片了,引脚可以直接测电压,使用还是非常方便的

首先左边这里IN0~IN7,是8路输入通道,通过通道选择开关,选中一路,输入到这个点进行转换,下面这里是地址锁存和译码,就是你想选中哪个通道,就把通道号放在这三个脚上(ADDA,ADDB,ADDC),然后给一个锁存信号(ALE),上面这里对应的通路开关就可以自动拨好了,这部分就相当于一个可以通过模拟信号的数据选择器,因为ADC转换是一个很快的过程,你给个开始信号,过几个us就转换完成了

所以说如果你想转换多路信号,那不必设计多个AD转换器,只需要一个AD转换器,然后加一个多路选择开关,想转换哪一路,就先拨一下开关,选中对应通道,然后再开始转换就行了,这就是这个输入通道选择的部分,这个ADC0809只有8个输入通道,我们STM32内部的ADC是有18个输入通道的,所以对应这里,就是一个18路输入的多路开关

那然后输入信号选好了,到这里来,怎么才能知道这个电压对应的编码数据是多少呢,这就需要我们用逐次逼近的方法来--比较了,首先这是一个电压比较器,它可以判断两个输入信号电压的大小关系,它的两个输入端,一个是待测的电压,另一个是这里DAC的电压输出端,给DAC一个数据,它就可以输出数据对应的电压,DAC内部是使用加权电阻网络来实现的转换

那现在,我们有了一个外部通道输入的,未知编码的电压,和一个DAC输出的,已知编码的电压,它俩同时输入到电屈比较器,进行大小判断,如果DAC输出的电屈比较大,我就调小DAC数据,如果DAC输出的电压比较小,我就增大DAG数据,直到DAC输出的电压和外部通道输入的电压近视相等,这样DAC输入的数据就是外部电屈的编码数据了,这就是DAC的实现原理,这个电压调节的过程就是这个逐次逼近SAR来完成的,为了最快找到末知电压的编码,通常我们会使用二分法进行寻找

那然后,AD转换结束后,DAC的输入数据,就是未知电压的编码,通过这里进行输出,8位就有8根线,12位就有12根线。

  • EOC是End Of Convert,转换结束信号
  • START是开始转换,给一个输入脉冲,开始转换 
  • CLOCK是ADC时钟,因为ADC内部是一步一步进行判断的,所以需要时钟来推动这个过程
  • WREF+和VREF-是DAC的参考电压, 比如你给一个数据255,是对应5V还是3.3V呢,就由这个参考电压决定,这个DAC的参考电压也决定了ADC的输入范围,所以它也是ADC参考电压
  • 参考电屈的正极和VCC是一样的,会接在一起
  • 参考电压的负极和GND也是一样的,也接在一起

般情况下,ADC输入电压的范围就和ADC的供电是一样的

3. STM32 ADC框图

 

[7-1] ADC模数转换器_哔哩哔哩_bilibili

规则通道,同时读取16个通道的信号,但是这个规则组只有一个数据寄存器,也就是只能读取到最后一个通道的信号,其他的都会被挤掉,所以通常配合DMA使用,DMA是一个数据转运小帮手,每读取到一个数据,都会把寄存器里的值转存到其他位置

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

对于注入组而言,就不用担心数据覆盖的问题,具有4个通道和4个数据寄存器

也就是这里的START信号,开始转换,触发ADC开始转换的借号有两种,一种是软件触发,就是你在程序中手动调用一条代码,就可以启动转换了,另一种是硬件触发,就是这里的这些触发源,上面这些是注入组的触发源,下面这些是规则组的触发源

这些触发源主要是来自于定时器,有定时器的各个通道,还有TRGO定时器主模式的输出,对于这种需要频繁进中断,并且在中断里只完成了简单工作的情况,一般就有硬件的支持,比如这里,就可以给TIM3定个1ms的时间,并且把TM3的更新事件选择为TRGO输出,然后在ADC这里,选择开始触发信号为TIMB的TRGO,这样TIM3的更新事件就能通过硬件自动触发ADC转换了,整个过程不需要进中断,节省了中断资源,这就是这里定时器触发的作用

左上角这里是WREF+、VREF-、VDDA和VSSA,上面两个是ADC的参考电压决定了ADC输入电压的范围,下面两个是ADC的供电引脚,一般情况下,INREF+要接VDDA,VREF-要接VSSA,在我们这个芯片上,没有REF+和VREF-的引脚,它在内部就已经和VDDA和VSSA接在一起了

WDDA和VSSA是内部模拟部分的电源,比如ADC、RC振荡器、锁相环等,在这里VDDA接3.3V,WSSA接GND,所以ADC的输入电压范围就是0~3.3

然后继续看燃右边这里是ADCCLK是ADC的时钟,也就是这里的CLOCK,是用于驱动内部逐次比较的时钟,这个是来自ADC预分频器,这个ADG预分频器是来源于RCC的

再上面这里是DMA请求,这个就是用手触发回MA进行数据转运的

然后是两个数据寄存器,用于存放转换结果的,上面这里,还有模拟看门狗,它里面可以存一个阀值高限和阈值低限,如果启动了模拟看门狗,并指定了看门的通道,那这个看门狗就会关注它看门的通道,一但超过这个阈值范围了,它就会乱叫,就会在上面,申请一个模拟看门狗的中断,最后通向NVIC

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

4. ADC基本结构

左边是输入通道,16个GPIO口,外加两个内部的通道,AD转换器里有两个组,一个是规则组,一个是注入组,规则组最多可以选中16个通道,注入组最多可以选择4个通道,然后转换的结果可以存放在AD数据寄存器里,其中规则组只有1个数据寄存器,注入组有4个,

然后下面这里有触发控制,提供了开始转换这个START信号,触发控制可以选择软件触发和硬件触发,硬件触发主要是来自于定时器,当然也可以选择外部中断的引脚,右边这里是来自于RCC的ADC时钟CLOCK,ADC逐次比较的过程就是由这个时钟推动的,

然后上面,可以布置一个模拟看门狗用于监测转换结果的范围,如果超出设定的阈值,就通过中断输出控制,向NVIC申请中断,另外,规则组和注入组转换完成后会有个EOC信号,官会置一个标志位,当然也可以通向NVIC

最后右下角这里还有个开关控制,在库函数中,就是ADC Cmd函数,用于给ADC上电

5. 输入通道

ADC通道和引脚复用的关系,这个ADC12IN0的意思是,ADC1和ADC2的IN0都是在PA0上的,然后正面全都是ADC12,这说明ADC1和ADC2的引脚全都是相同的

既然都相同,那要ADC2还有啥用呢?这个就要再说一个ADC的高级功能了,双ADC模式,这个模式比较复杂,双ADC模式就是ADC1和ADC2一起工作,它俩可以配合组成同步模式、交叉模式等等模式,比如交叉模式,ADC1和ADC2交又地对一个通道进行采样,这样可以进一步提高采样率

6. 转换模式

6.1 单次转换,非扫描模式

有16个空位,分别是序列1到序列16,就你可以在这里“点菜”,是写入你要转换的通道,在非扫描的模式下,这个菜单就只有第一个列1的位置有效,这时,菜单同时选中一组的方式就退化为简单地选中一个的方式了,在这里我们可以在序列1的位置指定我们想转换的通道,比如通道2,写到这个位置,然后,我们就可以触发转换,ADC就会对这个通道2进行模数转换,过一小段时间后,转换完成,转换结果放在数据寄存器里,同时给EOC标志位置1,整个转换过程就结束了,我们判断这个EOC标志位,如果转换完了,那我们就可以在数据寄存器里读取结果了,

如果我们想再启动一次转换,那就需要再触发一次,转换结束,置EC标志位,读结果,如果想换一个通道,那在转换之前,把第一个位置的通道2改成其他通道,然后在启动中断就行了,这就是单次转换,非扫描的转换模式

6.2 连续转换,非扫描模式

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

6.3 单次转换,扫描模式

这个模式也是单次转换,所以每触发一次,转换结束后,就会停下来,下次转换必须再触发才行,然后它是扫描模式,这就会用到这个菜单列表了,你可以在这个菜单里点菜,比如第一个菜是通道2,第二个菜是通道5,等等等等,这里每个位置是通道几可以任意指定,并且也是可以重复的,

然后初始化结构体里还会有个参数,就是通道数目,因为这16个位置你可以不用完,只用前几个,那你就需要再给一个通道数目的参数,告诉它,我有几个通道,比如这里指定通道数目为7,那它就只看前7个位置,然后每次触发之后,它就依次对这前7个位置进行AD转换,转换结果都放在数据寄存器里,这里为了防止数据被覆盖,就需要用DMA及时将数据挪走,那7个通道转换完成之后,产生EOC信号,转换结束。

6.4 连续转换,扫描模式

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

7. 触发控制

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

8. 数据对齐

我们这个ADC是12位的,它的转换结果就是一个12位的数据,但是这个数据寄存器是16位的,所以就存在一个数据对亲的问题,这里第一种是数据右对齐,就是12位的数据向右靠,高位多出来的几位补0,在这里我们一般使用的都是第一种右对齐,这样读取这个16位寄存器,直接就是转换结果,如果选择左对齐,直接读的话,得到的数据会比实际的大,因为数据左对齐实际上就是把数据左移了4次,直接读的话会比实际值大16倍

左对齐用途就是,如果你不想要这么高的分辨率,你觉得0~4095数大大了,我就做个简单的判断,不需要这么高分辨率,那你就可以选择左对齐,然后再把这个数据的高8位取出来,这样就舍弃掉了后面4位的精度,这个12位的ADC就退化成了8位的ADC了

8. 转换时间

转换时间这个蚕食,我们一般不太敏感,因为一般AD转换都很快,如果不需要非常高速的转换频率,那转换时间就可以忽略了,之前我们说了,AD转换是需要一小段时间的,那AD转换的时候都有哪些步骤需要花时间呢,其中采样保持可以放在一起,量化编码可以放在一起,总共是这两大步,

量化编码好理解,就是我们之前讲过的,ADC逐次比较的过程,这个是要花一段时间的,一般位数越多,花的时间就越长,

那采样保持是干啥的呢,为什么需要采样保持呢,这是因为,我们的AD转换,就是后面的量化编码,是需要一小段时间的,如果在这一小段时间里,输入的电压还在不断变化,那就没法定位输入电压到底在哪了是吧,所以在量化编码之前,我们需要设置一个采样开关,先打开采样开关,收集一下外部的电,比如可以用一个小容量的电容存储一下这个电压,存储好了之后,断开采样开关,再进行后面的AD转换,这样在量化编码的期间,电压始终保持不变,这样才能精确地定位未知电压的位置

那采样保持的过程,需要闭合采样开关,过一段时间再断开,这里就会产生一个采样时间        

STM32 ADC的总转换时间为TCONVE采样时间+12.5个ADC周期,采样时间是采样保持花费的时间,这个可以在程序中进行配置,采样时间越大,越能避免一些毛刺信号的干扰,不过转换时间也会相应延长,12.5个ADC周期是量化编码花费的时间,因为是12位的ADC,所以需要花费12个周期,这里多了半个周期,可能是做其他一些东西花的时间,ADC周期就是从RCC分频过来的ADCCLK,这个ADCCLK最大是14MHZ

所以下面有个例子,这里就是最快的转换时间,当ADCCLK=14MHZ,采样时间为1.5个ADC周期,TCONV=1.5+12.5=14个ADC周期,在14MHZADCCLK的情况下就=1us,这就是最快1us时间的来源

另外你也可以把ADCCLK的时钟设置超过14MHZ,这样的话ADC就是在超频了,那转换时间可以比1us还短,不过这样稳定性就没法保证了

9. 校准

  • ADC有一个内置自校准模式。校准可大幅减小因内部电容器组的变化而造成的准精度误差。校准期间,在每个电容器上都会计算出一个误差修正码(数字值),这个码用于消除在随后的转换中每个电容器上产生的误差
  • 建议在每次上电后执行一次校准
  • 启动校准前,ADC必须处于关电状态超过至少两个ADC时钟周期

10. 硬件电路

对于ADC的外围电路,我们应该怎么设计呢,第一个是一个电位器产生一个可调的电压,这里电位器的两个固定端,一端接3.3V,另一端接GND,这样中间的滑动端就可以输出一个0~3.3V可调的电压输出了,我们这里可以接ADC的输入通道,比如PA0口,当滑动端往上滑时,电压增大,往下滑时,电压减小,另外注意一下这个电阻的阻值不要给太小,因为这个电阻两端也是直接跨接在电源正负极的,如果阻值太小,那这个电阻就会比较费电,再小就有可能发热冒烟了,一般至少要接KQ级的电阻,比如这里接的是10K的电阻,这是电位器产生可调电压的电路

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

最后这个电路这是一个简单的电屈转换电路,比如你想测一个0~5V的VIN电压,但是ADC只能接收0~3.3V的电压,那就可以搭建一个这样的简易转换电路,在这里还是使用电阻进行分屈,上面阻值17K,下面阻值33K,加一起是50K,所以根据分压公式,中间的电压就是VIN/50Kx33K,最后得到的电压范围就是0~3.3V,就可以进入ADC转换了,这就是这个简单的电压转换电路,如果你想采集5V,10V这些电压的话,可以使用这个电路,但是如果你电压再高一些,就不建议使用这个电路了,那可能会比较危险,高电压采集最好使用一些专用的采集芯片,比如隔离放大器等等,做好高低电压的隔离,保证电路的安全

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值