单片机学习!
目录
[1.1 ADC名称](#1.1 ADC名称)
[1.2 ADC功能](#1.2 ADC功能)
[1.3 分辨率与转换时间](#1.3 分辨率与转换时间)
[1.4 输入电压与转换范围](#1.4 输入电压与转换范围)
[1.5 输入通道](#1.5 输入通道)
[1.6 增强功能](#1.6 增强功能)
[1.7 自动监测输入电压范围](#1.7 自动监测输入电压范围)
[1.8 STM32F103C8T6 ADC资源](#1.8 STM32F103C8T6 ADC资源)
[2.1 ADC内部结构原理图](#2.1 ADC内部结构原理图)
[2.2 输入通道选择](#2.2 输入通道选择)
[2.3 电压比较](#2.3 电压比较)
[2.4 输出](#2.4 输出)
[2.5 逐次逼近型ADC总结](#2.5 逐次逼近型ADC总结)
[3.1 ADC输入](#3.1 ADC输入)
[3.2 触发转换](#3.2 触发转换)
[3.3 ADC外围电路](#3.3 ADC外围电路)
[6.1 单次转换,非扫描模式](#6.1 单次转换,非扫描模式)
[6.2 连续转换,非扫描模式](#6.2 连续转换,非扫描模式)
[6.3 单次转换,扫描模式](#6.3 单次转换,扫描模式)
[6.4 连续转换,扫描模式](#6.4 连续转换,扫描模式)
[8.1 数据右对齐](#8.1 数据右对齐)
[8.2 数据左对齐](#8.2 数据左对齐)
[8.3 数据左右对齐作用](#8.3 数据左右对齐作用)
前言
GPIO只能读取引脚的高低电平,只有两个值:高电平或低电平。而ADC可以对高电平和低电平之间的任意电压进行量化,最终用一个变量来表示。读取这个变量就可以知道引脚的具体电压是多少。ADC好比一个电压表,可以把引脚的电压值测出来,放在一个变量里。
一、ADC简介
- ADC(Analog-Digital Converter)模拟-数字转换器
- ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量,建立模拟电路到数字电路的桥梁
- 12位逐次逼近型ADC,1us转换时间
- 输入电压范围:0~3.3V,转换结果范围:0~4095
- 18个输入通道,可测量16个外部和2个内部信号源
- 规则组和注入组两个转换单元
- 模拟看门狗自动监测输入电压范围
- STM32F103C8T6 ADC资源:ADC1、ADC2,10个外部输入通道
1.1 ADC名称
ADC模拟到数字转换器,简称模数转换器或者AD转换器。
- AD(Analog to Digital):模拟-数字转换,将模拟信号转换为计算机可操作的数字信号。
- DA(Digital to Analog):数字-模拟转换,将计算机输出的数字信号转换为模拟信号。
1.2 ADC功能
ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量。建立模拟电路到数字电路的桥梁。
STM32主要是数字电路,数字电路只有高低电平,没有几伏电压的概念。要想读取电压值,就需要借助ADC模拟转换器来实现了。ADC读取引脚上的模拟电压,转换为一个数据,存在寄存器里,再把这个数据读取到变量里来就可以进行显示、判断、记录等操作了。
ADC是模拟到数字的桥梁,DAC是数字到模拟的桥梁。DAC数字模拟转换器,使用DAC就可以将数字变量转换为模拟电压。DAC主要应用在波形生产这些领域,如信号发生器、音频解码芯片等。
还有一个数字到模拟的桥梁是PWM,PWM可以控制LED的亮度、电机的速度等。PMW只有完全导通和完全断开两种状态,这两种状态都没有功率损耗,所以在直流电机调速这种大功率的应用场景使用PWM来等效模拟量是比DAC等好的选择,并且PWM电路更加简单,更加常用,所以PWM的应用空间比DAC更广。
1.3 分辨率与转换时间
STM32的ADC是12位逐次逼近型ADC,1us转换时间。
逐次逼近型是ADC的工作模式,下文展开描述。
12位和1us转换时间涉及到ADC的两个关键参数。
第一个是分辨率,一般用多少位来表示,12位AD值,它的表示范围就是0到2的12次方减1,就是量化结果的范围是0~4095,位数越高量化结果就越精细,对应分辨率就越高。
第二个是转换时间,就是转换频率,AD转换是需要花一小段时间的,这里1us就表示从AD转换开始到产生结果,需要花1us的时间,对应AD转换的频率就是1MHz。1MHz就是STM32 ADC的最快转换频率。如果需要转换一个频率非常高的信号,就需要考虑一下这个转换频率是不是够用;如果信号频率比较低那最大1MHz的转换频率也完全够用。
1.4 输入电压与转换范围
输入电压范围:0~3.3V,转换结果范围:0~4095。
ADC的输入电压一般要求都是要在芯片供电的负极和正极之间变化的。
- 最低电压就是负极0V,最高电压是正极3.3V。
- 经过ADC转换之后,最小值就是0,最大值是4095.
0V对应0,3.3V对应4095,中间都是一一对应的线性关系,计算起来比较简单,可直接乘除一个系数就行了。
1.5 输入通道
ADC有18个输入通道,可测量16个外部和2个内部信号源。
外部信号源就是16个GPIO口,在引脚上直接接模拟信号就行了,不需要任何额外的电路,引脚就直接能测电压。
2个内部信号源是内部温度传感器和内部参考电压。温度传感器可以测量CPU的温度,如电脑可以显示一个CPU温度,就可以用ADC读取这个温度传感器来测量。内部参考电压是一个1.2V左右的基准电压,这个基准电压是不随外部供电电压变化而变化的。如果芯片的供电不是标准的3.3V,那测量外部引脚的电压可能就不对。这时就可以读取这个基准电压进行校准,校准后可得到正确的电压值了。
1.6 增强功能
规则组和注入组两个转换单元,这个是STM32 ADC的增强功能,普通的AD转换流程是,启动一次转换、读一次值,然后再启动、再读值,这样的流程。而STM32的ADC就比较高级,可以列一个组,一次性启动一个组,连续转换多个值。并且有两个组可以启动,一个是用于常规使用的规则组;一个是用于突发事件的注入组。
1.7 自动监测输入电压范围
模拟看门狗自动监测输入电压范围。
ADC一般可以用于测量光线强度、温度这些值。并且经常会有个需求:如果光线高于某个阈值或低于某个阈值;温度高于某个阈值或低于某个阈值时。需要执行一些操作。高于某个阈值、低于某个阈值的判断,就可以用模拟看门狗来自动执行。
模拟看门狗可以监测指定的某些通道,当AD值高于它设定的上阈值或者下阈值时,就会申请中断,可以在中断函数里执行相应的操作。执行这个操作可以不用不断手动读值,再用if进行判断了。
1.8 STM32F103C8T6 ADC资源
STM32F103C8T6 ADC资源:ADC1、ADC2,10个外部输入通道。
STM32F103C8T6 ADC资源有ADC1、ADC2 共两个ADC外设。10个外部输入通道也就是它最多只能测量10个外部引脚的模拟信号。上文所说ADC有16个外部信号源,这是这个系列最多有16个外部信号源,但是STM32F103C8T6芯片引脚比较少,有很多引脚没有引出来,所以只有16个外部信号源。
二、逐次逼近型ADC
2.1 ADC内部结构原理图
了解逐次逼近型ADC如何测电压,需要先了解逐次逼近型ADC的内部结构,以下结构图和STM32的ADC原理是一样的,它是ADC0809的内部结构图。ADC0809是一个独立的8位逐次逼近型ADC芯片。在单片机性能还不够强的时候,需要外挂一个ADC芯片才能进行AD换, ADC0809就是一款比较经典的ADC芯片。现在单片机的性能和集成度都有很大的提升,很多单片机内部就已经集成了ADC外设,不用外挂芯片,引脚可以直接测电压。
2.2 输入通道选择
(1 )IN0~IN7是8路输入通道。通过(2)通道选择开关,选中输入通道其中一路输入进行转换。(3)地址锁存和译码可以将选中通道的通道号放在(4)ADDA、ADDB、ADDC三个引脚上,然后给一个锁存信号(5)ALE,对应选中的输入通道通路开关就可以自动拨好了。ADDA、ADDB、ADDC三个引脚就是用来控制通道选择开关选择哪一路通道输入的。
这部分就相当于一个可以通过模拟信号的数据选择器。因为ADC转换是一个很快的过程,给个开始信号,过几个us就能转换完成。所以如果要转换多路信号,不用设计多个AD转换器,只需要一个AD转换器再加一个多路选择开关。需要转换哪一路就拨一下多路选择开关选中对应通道,然后再开始转换。
以上就是输入通道选择的部分,ADC0809芯片只有8个输入通道,STM32内部的ADC有18个输入通道,对应通道选择开关就是一个18路输入的多路开关。
2.3 电压比较
输入信号选好后怎么能得出电压对应的编码数据是多少呢?这里需要用逐次逼近的方法来一一比较。(6)电压比较器可以判断两个输入电压的大小关系。输出一个高低电平指示谁大谁小,电压比较器的两个输入端,一个是选中输入通道的带测电压,另一个是DAC的电压输出端。DAC是数模转换器,给DAC一个数据,DAC就可以输出数据对应的电压。DAC内部是使用加权电阻网络来实现的转换。
有一个外部通道输入的未知编码的电压,还有一个DAC输出的已知编码的电压。将两个电压同时输入到电压比较器,进行大小判断。
- 如果DAC输出的电压比较大,就相应调小DAC数据;
- 如果DAC输出的电压比较小,就相应调大DAC数据。
直到DAC输出的电压和外部通道输入的电压近似相等。这样DAC输入的数据就是外部电压的编码数据了,这就是DAC实现的原理,电压调节的过程就是(7)逐次逼近SAR来完成的。
为了最快找到未知电压的编码,通常会使用二分法进行查找。这里ADC0809芯片是8位的ADC,那编码就是从0~255.举例一个未知电压在0~5V之间。
- 第一次比较:用5/2V的电压和未知电压比较,DAC输入电压编码也为255/2也就是128来比较。转换为二进制就是1000 0000.
若未知电压比5/2V的电压小
- 第二次比较:用5/4V的电压和未知电压比较,DAC输入电压编码也为128/2也就是64来比较。转换为二进制就是0100 0000.
若未知电压比5/4V的电压大
- 第三次比较:用(5/4+5/8)V的电压和未知电压比较,DAC输入电压编码也为64+(64/2)也就是96来比较。转换为二进制就是0110 0000.
............
一直进行到第八次比较后,得出与未知电压近似的电压值。
分析发现,在对电压编码进行二等分的时候,就是转化为二进制的数值1000 0000从左到右依次判断:
- 若第一次判断未知电压小于电压编码第一次二等分的值,则二进制数值第一位置0:0100 0000,再用这个值进行第二次判断;
- 若第一次判断未知电压大于电压编码第一次二等分的值,则二进制数值保留第一位置1:1100 0000,再用这个值进行第二次判断。
二进制的8位数值每一位依次判断完后,得到的数值就是未知电压的近似编码电压。
AD转换结束后,(8)DAC的输入数据就是未知电压的编码。
2.4 输出
通过(9)8位三态锁存缓冲器进行输出,8位就有8根线,12位就有12根线。
- EOC:是End Of Convert,转换结束信号。
- START:是开始转换,给一个输入脉冲,开始转换。
- CLOCK:是ADC时钟。因为ADC内部是一步一步进行判断的,所以需要时钟来推动这个过程。
- VREF+和VREF-:是DAC的参考电压。如给一个数据255,是对应5V还是3.3V就取决于参考电压。DAC的参考电压也决定了ADC的输入范围,所以它也是ADC参考电压。
- VCC和GND:整个芯片电路的供电。通常参考电压的正极和VCC是一样的,会接在一起;参考电压的负极和GND也是一样的,会接在一起。一般情况下,ADC输入电压的范围就和ADC的供电是一样的。
2.5 逐次逼近型ADC总结
输入一个未知电压,再用DAC输出一个已知电压和输入的未知电压比较。如果未知电压大,就将DAC输出调高;如果未知电压小,就将DAC输出调低。多次调节后DAC调节得到一个和未知电压接近相等的已知电压,最终得到的已知的DAC电压值就可以表示为未知电压的值。
三、ADC框图
3.1 ADC输入
ADC输入通道共18个,包括了16个GPIO口(ADCx_IN0 ~ ADCx_IN15)和两个内部的通道(一个是内部温度传感器,另一个是VREFINT < V Reference Interna l> ,内部参考电压)。
信号经过输入通道后到达模拟多路开关,模拟多路开关可以指定需要选择的通道。模拟多路开关右边是多路开关的输出,信号从多路开关进入到数模转换器(模拟至数字转换器)。这里数字模拟转换器执行的就是上文中电压逐次比较的过程。
转换结果会直接放在数据寄存器里,读取数据寄存器就知道ADC转换的结果了。
- 在模拟多路开关这里对于普通ADC多路开关一般都是只选中一个,普通流程具体就是:选中某一个通道 -> 开始转换 -> 等待转换完成 -> 取出结果。
- 模拟多路开关这里对于STM32的ADC比较高级,可以同时选中多个通道,而且在转换的时候还分成两个组,规则通道组和注入通道组。其中规则组可以一次性最多选中16个通道,注入组最多可以选中4个通道。
这就像是去餐厅点菜。
普通的ADC是,客人指定一个菜,厨师给你做,然后做好了端给客人;
高级的ADC规则通道就是,客人指定一个菜单,这个菜单最多可以点16个菜,然后客人可以直接把菜单给厨师,厨师就按照菜单的顺序依次做好,一次性给客人端上桌。这样可以很大的提升效率。当然菜单也可以只写一个菜,这样菜单就简化成普通的模式了。对于菜单也分为两种:
- 一种是规则组菜单,可以同时上16个菜,但是规则组的数据只能存放于一个数据寄存器,就好比上菜的桌子比较小,最多只能放一个菜,如果点了16个菜,菜按顺序端上桌的时候,前15个菜都会被挤掉,客人只能得到第16个菜。所以对于规则组来说,如果使用这个菜单最好配合DMA来实现,DMA是一个数据转运小帮手,它可以在每上一个菜之后,把菜挪到其它地方去,防止被覆盖。
- 另一种是注入组菜单,这个组相比于规则组更为高级,相当于餐厅的VIP座位,客人在这个座位上一次性最多可以点4个菜,并且注入组的数据寄存器有4个,好比上菜的桌子比较大,最多可以放4个菜。客人可以点4个菜后同时上4个菜。
总结:
规则组虽然可以同时转换16个通道,但是规则组的数据寄存器只能存一个结果,如果不想之前的结果被覆盖,那在转换完成之后,就要尽快把结果拿走。
注入组可以同时转换4个通道,注入组的寄存器有4个,对于注入组来说不用担心数据覆盖的问题。
一般情况下使用规则组就足够了,如果要使用多个通道,就再配合DMA转运数据,解决数据覆盖的问题。下文主要介绍规则组的操作。
3.2 触发转换
触发转换的这部分也就是上文2.4中的START信号,开始转换。STM32的ADC,触发ADC开始转换的信号有两种。
- 一种是软件触发,就是在程序中手动调用一条代码,就可以启动转换了。
- 另一种是硬件触发,就是图中所示的这些触发源。上面是注入组的触发源,下面是规则组的触发源。
硬件触发的触发源主要是来自于定时器。触发源有定时器的各个通道,还有TRGO定时器主模式的输出。定时器可以通向ADC、DAC这些外设,用于触发转换。
因为ADC经常需要过一个固定时间段转换一次。比如每隔1ms转换一次,一般的思路就是,用定时器,每隔1ms申请一次中断。在中断里手动开始一次转换,但是频繁进中断对程序是有一定影响的。中断频繁进入肯定会对主程序的执行有影响。并且不同中断之间由于优先级的不同也会导致某些中断不能及时得到相应。如果触发ADC的中断不能及时响应,那ADC的转换频率就肯定会受到影响了。
对于ADC转换这种需要频繁进中断,并且在中断里只完成了简单工作的情况一般都会有硬件的支持。在ADC触发转换的这里,就可以给TIM3定个1ms的时间,并且把TIM3的更新事件选择为TRGO输出,然后再ADC这里选择开始触发信号为TIM3的TRGO,这样TIM3的更新事件就能通过硬件自动触发ADC转换了。整个过程不需要进中断,节省了中断资源。这就是定时器触发的作用。
当然在EXTI_11这里还可以选择外部中断引脚来触发转换,都可以在程序中配置。
3.3 ADC外围电路
1.VREF+和VREF-是ADC的参考电压,决定了ADC输入电压的范围。VDDA和VSSA是ADC的供电引脚。一般情况下VREF+要接VDDA,VREF-要接VSSA。在STM32F103C8T6芯片上没有VREF+和VREF-的引脚,它们在芯片内部就已经和VDDA、VSSA接在一起了。VDDA和VSSA在引脚定义表也可以找到:
VDDA和VSSA是内部模拟部分的电源,如ADC、RC振荡器、锁相环等。VDDA接3.3V,VSSA接GND,所以ADC的输入电压范围就是0~3.3V.
2.ADCCLK是ADC的时钟,也就是上文2.2中的CLOCK,用于驱动内部逐次比较的时钟。ADCCLK来自于ADC预分频器,这个ADC预分频器又来源于RCC。
APB2时钟72MHz,通过ADC预分频器进行分频,得到ADCCLK,ADCCLK最大是14MHz,所以ADC预分频器的选择需要注意,ADC预分频器可以选择2、4、6、8分频。如果选择2分频,72M / 2 = 36M,超出允许范围了;选择4分频之后是18M,也超了;选择6分频,结果是12M,没超;8分频,结果是9M,也没超。所以对于ADC预分频器只能选择6分频和8分频这两个值。这一点在程序中需要注意。
3.DMA请求,是用于触发DMA进行数据转运的。
4.注入通道数据寄存器和规则通道数据寄存器,这两个数据寄存器,用于存放转换结果的。
5.模拟看门狗,这里面可以存一个阈值高限和阈值低限。如果启动了模拟看门狗,并指定了看门的通道,那看门狗就会关注它看门的通道,一旦超过这个阈值范围了,看门狗就会乱叫,就是在这里申请一个模拟看门狗的中断,最后通向NVIC。
6.对于规则组和注入组而言,它们转换完成之后,也会有一个EOC转换完成的信号。EOC是规则组的完成信号;JEOC是注入组的完成信号。这两个组会在状态寄存器里置一个标志位,读取这个标志位就可以知道是不是转换结束了。同时这两个标志位也可以去到NVIC申请中断。如果开启了NVIC对应的通道,就会触发中断。
四、ADC基本结构
最左边是输入通道,16个GPIO口,外加两个内部的通道。然后进入AD转换器,AD转换器里有两个组,一个是规则组,一个是注入组。规则组最多可以选择16个通道;注入组最多可以选择4个通道。转换的结果可以存放在AD数据寄存器里,其中规则组只有一个数据寄存器,注入组有4个数据寄存器。
AD转换器左下方有触发控制,提供了开始转换START信号。触发控制可以选择软件触发和硬件触发。硬件触发主要是来自于定时器,也可以选择外部中断的引脚。AD转换器右下方是来自于RCC的ADC时钟CLOCK,ADC逐次比较的过程就是由这个时钟推动的。
布置模拟看门狗可以用于监测转换结果的范围,如果超出设定的阈值,就通过中断输出控制,向NVIC申请中断。
规则组和注入组转换完成后会有个EOC信号,EOC信号会置一个标志位,也可以通向NVIC.
右下角的开关控制在库函数中就是ADC_Cmd函数,用于给ADC上电的。
五、输入通道
输入通道表里总共有18个通道,通道0~通道17。通道16对应ADC1的温度传感器;通道17对应ADC1的内部参考电压。注意只有ADC1有通道16和17,ADC2和ADC3是没有的。通道0~通道15对应GPIO的引脚,ADC1和ADC2的引脚是完全相同的,ADC3的引脚会有些变化。
ADC有16个外部通道,外部通道对应的GPIO口可以通过上表查询,上表就是ADC通道和引脚复用的关系,这个对应的关系也可以通过引脚定义表看出来。
这里可以看到:只有IN0~IN9,总共10个通道。这个芯片只能有十个外部输入通道。
- ADC12_IN0对应的是PA0引脚;
- ADC12_IN1对应的是PA1引脚;
- ADC12_IN2对应的是PA2引脚;
- ADC12_IN3对应的是PA3引脚;
- ADC12_IN4对应的是PA4引脚;
- ADC12_IN5对应的是PA5引脚;
- ADC12_IN6对应的是PA6引脚;
- ADC12_IN7对应的是PA7引脚;
- ADC12_IN8对应的是PB0引脚;
- ADC12_IN9对应的是PB1引脚。
ADC12_IN0的意思是,ADC1和ADC2的IN0都是在PA0上的。IN0~IN9都是ADC12_INx,这表示ADC1和ADC2的引脚全都是相同的。
ADC有一个高级功能:双ADC模式。双ADC模式就是ADC1和ADC2一起工作,它俩可以配合组成同步模式、交叉模式等等模式。交叉模式就是ADC1和ADC2交叉对一个通道进行采样,这样可以进一步提高采样频率。
ADC1和ADC2也是可以分开使用的,可以分别对不同引脚进行采样。
六、转换模式
在ADC初始化的结构体里,会有两个参数:
- 一个是选择单次转换还是连续转换的。
- 一个是选择扫描模式还是非扫描模式的。
这两个参数组合起来,就有4种转换方式:
- 单次转换,非扫描模式
- 连续转换,非扫描模式
- 单次转换,扫描模式
- 连续转换,扫描模式
6.1 单次转换,非扫描模式
图中的列表就表示规则组里的菜单,有16个空位,分别是序列1到序列16.可以在菜单里点菜,就是写入需要转换的通道。在非扫描的模式下,这个菜单就只有第一序列1的位置有效,这时菜单同时选中一组的方式就退化为简单地选中一个的方式了。
可以在序列1的位置指定需要转换的通道,如图中以通道2举例,将通道2写入到序列1的位置,就可以触发转换,ADC就会对通道2进行模数转换。过一小段时间后,转换完成,转换结果放在数据寄存器里,同时给EOC标志位置1,整个转换过程就结束了。
判断EOC标志位,如果转换完了,就可以在数据寄存器里读取结果了。如果想在启动一次转换,那就需要再触发一次。转换结束,置EOC标志位,读取结果。
如果想换一个通道转换,那在转换之前,把第一个位置的通道2改成其他通道,然后再启动转换,这样就行了。
单次转换非扫描的模式,没有用到菜单列表,也是比较简单的一种模式。
6.2 连续转换,非扫描模式
因为还是非扫描模式,所以菜单列表就只用第一个。这种模式与上一种单次转换不同的是,它在一次转换结束后不会停止,而是立刻开始下一轮的转换,然后一直持续下去。这样就可以最开始触发一次,之后就可以一直转换了。
这个模式的好处就是,开始转换之后不需要等待一段时间,因为它一直都在转换,所以不需要手动开始转换,也不需要判断是否结束,想要读取AD值的时候,直接从数据寄存器取就可以。
6.3 单次转换,扫描模式
这个模式也是单次转换,所以每触发一次,转换结束后,就会停下来,下次转换就得再触发才能开始。因为它是扫描模式,这就会用到菜单列表。可以在菜单里点多个菜,如图中示例,将通道2写入序列1;通道5写入序列2;通道4写入序列3;通道1写入序列4......这里每个序列位是通道几可以任意指定,并且可以重复指定。
在程序中可以用一个结构体来配置转换模式,初始化结构体里还会有个参数,就是通道数目。因为一共16个通道可以不全都用完,只用前几个,这样就需要再给一个通道数目,告诉程序有几个通道。
如图中所示指定通道数目为7,转换时就只看前7个位置,每次触发之后,就依次对前7个位置进行AD转换。转换结果都放在数据寄存器里,这里为了防止数据被覆盖,就需要用DMA及时将数据挪走。7个通道转换完成之后,产生EOC信号,转换结束。然后再触发下一次,就又开始新一轮的转换。这就是单次转换,扫描模式的工作流程。
6.4 连续转换,扫描模式
连续转换,扫描模式就是在单次转换,扫描模式的基础上变了一点。连续转换,扫描模式就是一次转换完成后,立刻开始下一次的转换。
在扫描模式的情况下,还可以有一种模式,叫间断模式。间断模式的作用是在扫描的过程中,每隔几个转换就暂停一次。需要再次触发才能继续。
七、触发控制
上表就是规则组的触发源,也就是下图ADC框图中框起来的部分。
在触发控制的表里:
- 有来自定时器的信号;
- 还有来自引脚或定时器的信号,具体是引脚还是定时器,需要用AFIO重映射来确定;
- 最后还有软件控制位,也就是软件触发。
以上触发信号的选择可以通过设置右边这个寄存器来完成。若使用库函数的话,直接给一个参数就行了。
八、数据对齐
ADC是12位的,它的转换结果也是一个12位的数据。但是数据寄存器是16位的,所以就存在一个数据对齐的问题。
8.1 数据右对齐
数据右对齐就是12位的数据向右靠,高位多出来的几位就补0.
8.2 数据左对齐
数据左对齐是12位的数据向左靠,低位多出来的几位补0.
8.3 数据左右对齐作用
一般使用的都是数据右对齐,使用右对齐读取16位寄存器,直接就是转换结果。如果选择左对齐直接读的话,得到的数据会比实际的大。因为数据左对齐实际上就是把数据左移了4次。二进制有个特点,就是数据左移一次,就等效于把这个数据乘2.数据左对齐就是左移了4次,就相当于把结果乘16了,所以直接读的话会比实际值大16倍。
数据左对齐可以用于不那么高的分辨率,只做个简单的判断。数据左对齐后再把数据的高8位取出来,这样就舍弃掉了后面4位的精度。这样12位的ADC就退化成了8位的ADC了。
九、转换时间
AD转换的步骤:采样,保持,量化,编码。
STM32 ADC的总转换时间为:TCONV = 采样时间 + 12.5个ADC周期
转换时间这个参数,一般都不会太敏感,因为AD转换时间很快。如果不需要非常高速的转换频率,那转换时间就可以忽略。
AD转换是需要一小段时间的。AD转换的时候有一些步骤需要花时间,有4步,分别是:采样,保持,量化,编码。其中采样保持可以放在一起,量化编码可以放在一起,这样总共是两大步。
量化编码,就是ADC逐次比较的过程,需要花一段时间,一般位数越多,花的时间就越长。
采样保持,AD转换后面的量化编码是需要一小段时间的,如果在这一小段时间里,输入的电压还在不断变化,那就没法定位输入电压到底是在哪了。所以在量化编码之前,需要设置一个采样开关,先打开采样开关,收集一下外部电压,比如可以用一个小容量的电容存储一下要收集的电压,存储好了之后,断开采样开关,再进行后面的AD转换。这样在量化编码的期间,电压时钟保持不变,才能精确的定位未知电压的位置。
采样保持的过程,需要闭合采样开关,过一段时间再断开,这里就会产生一个采样时间。也就是上文公式:
STM32 ADC的总转换时间为:TCONV = 采样时间 + 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周期 = 1μs
以上例子就是最快的转换时间。在14MHz ADCCLK的情况下就等于1us。如果采样时间再长些就达不到1us了。如果把ADCCLK的时钟设置超过14MHz的话,ADC就是在超频了,那转换时间可以比1us还短,但是这样稳定性就没法保证了。
十、校准
- ADC有一个内置自校准模式。校准可大幅减小因内部电容器组的变化而造成的准精度误差。校准期间,在每个电容器上都会计算出一个误差修正码(数字值),这个码用于消除在随后的转换中每个电容器上产生的误差。
- 建议在每次上电后执行一次校准。
- 启动校准前, ADC必须处于关电状态超过至少两个ADC时钟周期。
这个校准过程是固定的,使用时只需要在ADC初始化的最后,加几条代码就行。
总结
以上就是今天要讲的内容,本文仅仅简单介绍了STM32的ADC数模转换器的原理于内部电路结构。