目录
一、ADC简介
STM32F103系列有3个ADC,精度为12位,每个ADC最多有16个外部通道。其中ADC1和ADC2都有16个外部通道,ADC3根据CPU引脚的不同通道数也不同,一般都有8个外部通道。ADC的模式非常多,功能非常强大。
二、ADC功能
1.电压输入范围
ADC输入范围为:VREF- ≤ VIN ≤ VREF+,具体电压由VREF-、VREF+、VDDA、VssA这4个外部引脚决定。
在设计原理图的时候,一般把VssA和VREF-接地,把VREF+和VDDA接3V3,得到ADC的输入电压范围为0~3.3V。
如果想让 输入的电压范围变宽,达到可以测试负电压或者更高的正电压,则可以在外部加一个电压调理电路,把需要转换的电压抬升或者降压到 0~3.3V,这样ADC就可以测量。
2.输入通道
确定好ADC的输入电压之后,电压通过通道输入到ADC。STM32的ADC有18个通道,其中外部的16个通道就是框图中的ADCx_IN0~ADCx_IN15,这16个通道对应着不同的 lO口。ADC1/2/3还有内部通道:ADC1的通道16连接到了芯片内部的温度传感器,Vrefint连接到了通道17;ADC2的模拟通道16和17连接到了内部的VSS;ADC3的模拟通道9、14、15、16和17连接到了内部的VSS。
外部的16个通道在转换的时候又分为规则通道和注入通道,其中规则通道最多有16路,注入通道最多有4路。
(1) 规则通道:我们用到的都是这个通道。
(2) 注入通道:是一种在规则通道转换的时候强行插入要转换的一种通道。如果在规则通道转换过程中有注入通道插队,那么就要先转换完注入通道,等注入通道转换完成后,再回到规则通道的转换流程。所以,注入通道只有在规则通道存在时才会出现。
3. 转换顺序
(1)规则序列
规则序列寄存器有3个(SQR3、SQR2、 SQR1)。SQR3控制着规则序列中的第1~6个转换,对应的位为:SQ1[4:0] ~ SQ6[4:0],第一次转换的是位4:0 SQ1[4:0]。SQR2控制着规则序列中的第7~12个转换,对应的位为:SQ7[4:0] ~ SQ12[4:0]。SQR1控制着规则序列中的第13~16个转换,对应位为:SQ13[4:0] ~ SQ16[4:0]。
具体使用多少个通道,由SQR1的位L[3:0]决定,最多16个通道。
(2) 注入序列
注入序列寄存器JSQR只有一个,最多支持4个通道,具体多少个由JSQR的JL[2:0]决定。如果JL的值小于4,则JSQR与SQR决定转换顺序的设置不一样,第一次转换的不是JSQR1[4:0],而是JCQRx[4:0],x=(4-JL),与SQR相反。如果JL=00(1个转换),那么转换的顺序从JSQR4[4:0]开始,而不是从JSQR1[4:0]开始。当JL等于4时,与SQR一样。
4.触发源
通道选好了,转换的顺序也设置好了,接下来开始转换。ADC可以由ADC控制寄存器2 (ADC_CR2) 的ADON位来控制,写1的时候开始转换,写0的时候停止转换( 开启ADC转换最简单的控制方式 )。
除此之外,ADC还支持触发转换,这个触发包括内部定时器触发和外部IO触发。触发源有很多,具体选择哪一种触发源,由ADC控制寄存器2 (ADC_CR2) 的EXTSEL[2:0]和JEXTSEL[2:0]位控制。EXTSEL[2:0]用于选择规则通道的触发源,JEXTSEL[2:0]用于选择注入通道的触发源。选定好触发源之后,触发源是否要激活,则由ADC控制寄存器2 (ADC_CR2)的EXTTRIG和JEXTTRIG位来激活。
5. 转换时间
(1) ADC时钟
ADC输入时钟ADC_CLK由PCLK2经过分频产生,最大是14MHz。分频因子由RCC时钟配置寄存器RCC_CFGR的位15:14 ADCPRE[1:0]设置,可以是2、4、6、8分频。
注:没有1分频。一般设置 PCLK2=HCLK=72MHz。
(2) 采样时间
ADC使用若干个ADC_CLK周期对输入的电压进行采样,采样的周期数可通过ADC采样时间寄存器ADC_SMPR1和ADC_SMPR2中的SMP[2:0]位设置,ADC_SMPR2控制的是通道0~9,ADC_SMPR1控制的是通道10~17。每个通道可以分别用不同的时间采样。其中采样周期最小是1.5个(如果要达到最快的采样可以设置采样周期为1.5周期)。
这里说的 周期就是 1 / ADC_CLK。
ADC的转换时间与ADC的输入时钟和采样时间有关,公式为:Tconv = 采样时间 + 12.5个周期。
ADCLK=14MHz(最高),采样时间设置为1.5周期(最快),那么总的转换时间 (最短)Tconv = 1.5周期 + 12.5周期 = 14周期 = 1𝛍s。
一般设置 PCLK2=72MHz,经过ADC预分频器能分频到的最大时钟只能是12MHz,采样周期设置为 1.5周期,算出 最短的转换时间为 1.17𝛍s,这个才是最常用的。
6. 数据寄存器
ADC转换后的数据根据转换组的不同,规则组的数据放在ADC_DR寄存器中,注入组的数据放在JDRx中。
(1) 规则数据寄存器
ADC规则组数据寄存器ADC_DR只有一个,是一个32位的寄存器,低16位在单ADC时使用,高16位用于在ADC1的双模式下保存ADC2转换的规则数据(双模式就是ADC1和ADC2同时使用)。
在单模式下,ADC1/2/3都不使用高16位。因为ADC的精度是12位,无论ADC_DR的高16或者低16位都放不满,只能左对齐或者右对齐,具体以哪一种方式存放,由ADC_CR2的第11位ALIGN设置。
规则通道可以有 16个之多,可规则数据寄存器只有一个,如果使用多通道转换,那转换的数据就全部都挤在了 DR里面,前一个时间点转换的通道数据,就会被下一个时间点的另外一个通道转换的数据覆盖掉。所以当通道转换完成后就应该把 数据取走,或者开启DMA模式,把数据传输到内存里面,不然就会造成数据的覆盖。最常用的做法就是开启DMA传输。
(2)注入数据寄存器
ADC注入组最多有4个通道,注入数据寄存器也有4个,每个通道对应着自己的寄存器,不会像规则寄存器那样产生 数据覆盖的问题。
ADC_JDRx是32位的,低16位有效,高16位保留,数据同样分为左对齐和右对齐,具体以哪一种方式存放,由ADC_CR2的第11位ALIGN设置。
7. 中断
数据转换结束后,可以产生中断。中断分为3种:规则通道转换结束中断、注入转换通道转换结束中断、模拟看门狗中断
(1)转换结束中断
与平时的中断一样,有相应的中断标志位和中断使能位,还可以根据中断类型写相应配套的中断服务程序。
(2) 模拟看门狗中断
当被ADC转换的模拟电压低于低阈值或者高于高阈值时,就会产生中断,前提是开启了模拟看门狗中断,其中低阈值和高阈值由ADC_LTR和ADC_HTR设置。
e.g. 如果设置高阈值是2.5V,那么当模拟电压超过2.5V的时候,就会产生模拟看门狗中断,反之低阈值也一样。
(3)DMA请求
规则和注入通道转换结束后,除了产生中断外,还可以产生DMA请求,把转换好的数据直接存储在内存里面。一般在使用ADC的时候都会开启DMA传输。
注:只有 ADC1 和 ADC3可以产生 DMA请求。
8. 电压转换
模拟电压经过ADC转换后,变成一个12位的数字值,如果通过串口以十六进制数输出,可读性比较差,因此有时候就需要把数字电压转换成模拟电压。
一般在设计原理图的时候会把ADC的输入电压范围设定在 0~3.3V,因为ADC是12位的,那么12位满量程对应的就是3.3V,12位满量程对应的数字值是:2^12。数值0对应的就是0V。如果转换后的数值为X,X对应的模拟电压为Y,那么会有以下等式成立:
2^12 / 3.3=X / Y ⇨ Y=(3.3X) / 2^12
三、ADC配置步骤(单通道ADC采集,DMA读取)
1. 初始化DMA:HAL_DMA_Init()
2. 将DMA和ADC句柄联系起来:__HALLINKDMA()
3. 配置ADC工作参数、ADC校准:HAL_ADC_Init()、 HAL_ADCEx_Calibration_Start()
4. ADC MSP初始化:HAL_ADC_Msplnit() ( 配置NVIC、CLOCK、GPIO等)
5. 配置ADC相应通道相关参数:HAL_ADC_ConfigChannel()
6. 使能DMA数据流传输完成中断:HAL_NVIC_SetPriority()、 HAL_NVIC_EnablelRQ()
7. 编写DMA数据流中断服务函数:DMAx_Channely_IRQHandler()
8. 启动DMA,开启传输完成中断:HAL_DMA_Start_IT()
9. 触发ADC转换,DMA传输数据:HAL_ADC_Start_DMA()
可以参考这篇文章:
嵌入式——模拟/数字转换器(ADC)