1.stm32-ADC概述
ADC简介
ADC的概念:
Analog-to-Digital Converter的缩写。指模/数转换器或者模拟/数字转换器。是指将连续变化的模拟信号转换为离散的数字信号的期间。
ADC的作用:
采集传感器数据,测量输入电压,检查电池电量剩余,监测温湿度等。
典型的模拟数字转换器将模拟信号转换为表示一定比例电压值的数字信号,具体的方法如下图所示。
我们都知道,模拟信号是连续信号,数字信号是离散信号,模数转换的基本做法就是将连续的模拟信号抓换成离散的数字信号。一般而言,我们在开发过程中都是将传感器的模拟信号,通过stm32的ADC,将模拟的信号转换成用一定数值表示的数字信号。
我们在采集模拟信号的过程中,由于每个采集点之间的时间的不同,所以导致用数字信号拟合到的模拟信号也是不同的,当采集点越密,拟合的模拟信号也就越准确,这也就有了下面分辨率的概念。
ADC的性能指标:
- 量程:能测量的电压范围,在stm32中,量程的范围一般是0~3.3V
- 分辨率:ADC的分辨率通常以输出二进制数的位数来表示,位数越多,分辨率越高,一般来说,分辨率越高,转化时间越长。当我们分辨率变高的时候,我们的采集点也会变得很密集,因为每个采集点进行采集都需要一定的时间,所以分辨率变高,每次完整采集的时间也就会变长。
- 转化时间:模拟输入电压在允许的最大变化范围内,从转换开始到获得稳定的数字量输出所需要的时间称为转换时间。
stm32f103的ADC特性:
- stm32f103的ADC是一种逐次逼近型的模拟数字转换器,多达18个通道,可测量16个外部通道和2个内部的信号源,各通道的A/D转化可以单次、连续、扫描或者间断模式执行,ADC的结果可以左对齐或者右对齐的方式存放在16位数据寄存器中。
- ADC的输入时钟不得超过14MHZ,它是由PCLK2经过分频产生。
- stm32f103的ADC只能配置为12位的分辨率。
2.ADC的功能框图
以上就是ADC的功能框图,stm32的ADC转换功能就是通过以上框图完成的。这个框图大概分为7的部分,第一部分是电压输入范围,第二部分是输入通道,第三部分是转换顺序,第四部分是转换时钟来源,第五部分是相关数据寄存器,第六部分是相关标志位和相应中断使能位,第七部分是触发源选择,下面我们来一个部分一个部分讲解。
2.1.电压输入范围
- ADC输入范围为:VREF- <= VIN <=VREF+。ADC的电压输入范围由VREF-、VREF+、VDDA、VSSA这四个外部引脚决定。
- 我们在设计原理图的时候一般吧VSSA和VREF-接地,把VREF+和VDDA接3.3V,得到ADC的输入电压范围为:0~3.3V。设计原理图的工作一般都是硬件工程师的工作,所以我们只需要大概了解即可。
- 如果我们想让输入的电压范围变宽,去到可以测试负电压或者更高的正电压,我们就可以在外部加一个电压调理电路,把需要转换的电压抬升或者降压到0~3.3V,这样ADC就可以测量了。
2.2.输入通道
每个ADC有16的外部通道,另外还有两个内部ADC源挂载到ADC1上
上面的图片是3个ADC不同的通道对应的不同的引脚,ADC1除了这16路ADC通道以外,还有两个ADC通道,一路为内部温度传感器,另一路为内部参照电压,这些电路构成了整个ADC的通道结构。
2.3.转换顺序
第三部分主要是用来配置转换顺序的
我们可以很清楚的看到,第三个部分分为注入通道组合规则通道组
- 规则通道组,我们一般使用的就是这个通道组,规则通道组最多可以接收ADC上的16个通道,可以通过规则通道组来配置转换顺序,但是我们可以看到规则通道组的数据寄存器,一次只能存放一个通道的结果,所以,很尴尬的就是,我们可以通过规则通道组顺序转换16个通道的数据,但是我们的规则通道数据寄存器只能存放一次的结果,所以,我们每个通道转换结束以后,就需要及时取走数据,否则就会被后面的数据覆盖。
- 注入通道组,注入通道组可以理解为插入通道组,一般来讲,它相当于是中断,注入通道组最多可以转换四路通道的数据,并且其数据寄存器也可以一次性存放四组数据,但是我们平常进行ADC转换的时候并不常用这个通道组来进行配置转换顺序,我们在这个地方进行简单的了解即可。
2.4.转换时钟来源
ADC时钟:
ADC的时钟来源是由PCLK2经过分频产生的,stm32f103系列的时钟最大可以配置为14MHZ,但是PCLK2的时钟是72MHZ,所以我们一般要进行6分频来进行对ADC时钟的配置。
ADC的总转换时间:
ADC使用若干个ADC_CLK周期对输入电压进行采样,采样周期数目可以通过ADC_SMPR1和ADC_SMPR2寄存器中的SMP[2:0]位进行更改。每个通道可以分别用不同的时间采样。
总转换时间如下计算:
Tconv = 采样时间+12.5个周期
例如当ADCCLK=14MHZ的时候,采样时间为1.5周期
Tconv = 1.5+12.5 = 14周期 = 1us
2.5.相关数据寄存器
由于我们最主要使用的是规则通道组,因此我们这个地方就只介绍规则数据寄存器
规则数据寄存器ADC_DR:
ADC_DR只有一个,是一个32位的寄存器,只有低16位有效并且只是用于独立模式存放转换完成的数据。因为stm32f103的ADC的精度是12位,ADC_DR是16位有效,这样就会产生数据存放过程中左对齐或者右对齐的情况存在。我们在使用ADC转换的时候,一般都是使用右对齐,因为这样可以让12位的数据存放在DR的低12位中,方便我们读取。如果要是设置为左对齐,这样取出数据后还要进行一定的转换,不利于我们对数据的处理。
由于规则通道组只有一个数据寄存器,因此,对于多个规则通道的转换,使用DMA非常有帮助。这样可以避免丢失在下一次写入之前还未被读出的ADC_DR寄存器中的数据。在使能DMA模式的情况下,每次完成规则通道组中的一个通道转换后,都会生成一个DMA请求。
2.6.相关标志位和中断
第六个部分主要就是进行相关标志位的读写操作并且对相关标志位进行使能。
- EOC 转换结束标志位,注入通道组合规则通道组数据转换结束后,都会将EOC标志位置位,当使能转换结束中断以后,转换结束后就会触发相应中断,EOC标志位由软件清除或者读取ADC_DR时清除。
- JEOC 注入通道转换结束标志位,当注入通道组转换完成后,会将JEOC进行置位,如果开启中断标志位,那么就会产生相应中断,JEOC标志位由软件清除。
- AWD 模拟看门狗标志位,该位由硬件在转换的电压超出上限值或者低于下限值的时候置位,如果开启中断,那么将产生中断,AWD标志位由软件清除。
2.7.触发源
- 软件触发
ADC转换可以由ADC控制寄存器2:ADC_CR2的ADON这个位来控制,写1的时候开始转换,写0的时候停止转换。 - 外部事件触发
触发包括内部定时器触发和外部IO触发。触发源有很多,具体选择哪一种触发源,由ADC控制寄存器ADC_CR2的EXTSEL[2:0]和JEXTSEL[2:0]位来控制。
但是我们平常主要是使用软件触发源来进行ADC的触发转换。
3.ADC的工作模式
3.1.单次转换非扫描模式
单次转化非扫描模式是最简单的一种模式,我们每次都只会转换一条通道,并且当这条通道转换完成后也不会去扫描是否有下一条通道开启了转换,当转换完成后就直接将标志位EOC进行置位,通知我们转换完成。
3.2.连续转换非扫描模式
连续转换非扫描模式也比较简单,这个模式也是只能进行一条通道的转换,当开启转换后,会一直持续转换这一条通道的值,每次转换结束会将EOC置位,并且接着进行下一次的转换。当我们需要读取转换结果的时候,就直接从DR寄存器里面读取就好了。
3.3.单次转换扫描模式
单次转换扫描模式也是开启转换后需要只进行一次转换,但是这次转换并不只是转换一个通道,而是配置扫描模式的所有通道进行转换,如上图,转换开启后,先进行通道2的转换,然后依次为通道5、通道4…最后到通道6转换结束,EOC置位,当无转换开始信号的时候,不自动开启下一轮的转换。
当然,我们还需要配置通道数目,当我们配置为7个通道数目的时候,可以将上面的通道全部转换,但是只配置6个通道数目的时候,就只能转换到通道3,这也就是配置通道数目的作用。
但是当我们设置扫描模式的时候,需要及时将数据读走,否则每个通道的转换都会将输入存入DR寄存器,这样如果不及时读走数据,那么数据就会被覆盖。
3.4.连续转换扫描模式
连续转换扫描模式就是在扫描模式的基础上加上连续转换,当所配置的所有通道依次转换完成后,转换不会停止,而是继续新一轮的转换。
总的来说,扫描模式就是依次扫描配置的通道进行转换,连续模式就是指ADC转换完成后不停止,继续下一次的转换,这两种模式的组合就构成了上述的4种模式。
4.单通道采集实例
实验要求:利用ADC1采集模拟量并转换成数字量。
4.1.cubemx具体配置
USART1的配置和其他配置和原来相同。
4.2.具体代码实现
4.2.1.轮询方式
HAL_ADC_Start( &hadc1); //开启ADC
if(HAL_ADC_PollForConversion(&hadc1, 100)==HAL_OK ) //如果转换结果完成
{
printf("the adc value is %d\r\n",HAL_ADC_GetValue(&hadc1));//读取打印结果并用串口打印出来结果
}
HAL_Delay(1000); //延时1s,防止采样过快
我用的是光敏传感器来进行采样的,采样结果如下:
当无遮挡的时候,采样结果大概在900左右;当遮挡住以后,采样结果大概在2500左右。
4.2.2.中断方式
用中断方式来进行ADC的转换我们需要进行两个部分的代码的书写
首先是main.c中的ADC中断开启函数,然后就是ADC中断的回调函数。
下面就是两段代码
main.c中的代码
HAL_ADC_Start_IT(&hadc1); //开启ADC转换中断
HAL_Delay(1000);//延时1s
adc.c中的ADC的回调函数
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) //进入ADC中断
{
if(hadc->Instance==ADC1) //判断是否为ADC1的中断
{
printf("the ADC value is %d\r\n",HAL_ADC_GetValue(&hadc1));//打印相关内容
}
}
转换结果如下:
当我用手将传感器全部捂住以后,显示结果在3500左右,当有一定缝隙的时候,结果在2500左右,当完全暴露的时候,结果在900左右。
5.多通道采集实例
多通道采集的过程中,因为规则转换组只有一个数据寄存器,因此我们需要每转换完一次,都要及时运走数据,否则就会被覆盖。
我尝试了两种方法来进行数据及时搬运。
一种是通过读取DR寄存器,当DR寄存器不等于0的时候,就立马读走数据。
另一种方法是我设置两个通道的转换时间相同,可以触发半次转换完成中断和转换完成中断,这两个分别来读取数据。
但是这两种方法都无法将两个通道的数据及时读出来,因此,我们还是在下一章学习了DMA以后,再进行多通道数据的采集吧。
如果有人不使用DMA将两个数据的通道都读出来了,欢迎评论和我交流。
6.ADC相关寄存器
ADC的相关寄存器包括以下几个:
- ADC状态寄存器(ADC_SR)
- ADC控制寄存器1(ADC_CR1)
- ADC控制寄存器2(ADC_CR2)
- ADC采样时间寄存器1(ADC_SMPR1)
- ADC采样时间寄存器2(ADC_SMPR2)
- ADC注入通道数据偏移寄存器x(ADC_JOFRx)
- ADC看门狗高阈值寄存器(ADC_HTR)
- ADC看门狗低阈值寄存器(ADC_LTR)
- ADC规则序列寄存器1(ADC_SQR1)
- ADC规则序列寄存器2(ADC_SQR2)
- ADC规则序列寄存器3(ADC_SQR3)
- ADC注入序列寄存器(ADC_JSQR)
- ADC注入数据寄存器x(ADC_JDRx)
- ADC规则数据寄存器(ADC_DR)
6.1.ADC状态寄存器(ADC_SR)
状态寄存器主要是用低5位,其余位置保留,这里主要是用来表示ADC的相关状态,包括规则通道转换开始标志位,注入通道转换开始标志位,注入通道转换完成标志位、通道转换完成标志位、模拟看门狗标志位等。
6.2.ADC控制寄存器1(ADC_CR1)
控制寄存器主要是用来控制相关配置的,但是有很多的位不太重要,我们下面找几个比较重要的位来说一下。
位5-位8是比较重要的位,位5是允许产生EOC中断,位6是允许模拟看门狗中断,位7是允许产生注入通道转换结束中断,位8是设置扫描模式(扫描模式下,设置了EOCIE或者JEOCIE位,只有最后一个通道转换完毕后才能产生EOC或者JEOC中断。)
6.3.ADC控制寄存器2(ADC_CR2)
这个寄存器我们也主要介绍比较重要的位。
位0控制ADC转换的启动
位1控制连续转换或者单次转换
位8控制是否启动DMA
位11控制对齐方式
6.4.ADC采样时间寄存器
这两个寄存器分别配置17个通道的采样周期,寄存器2配置前9个通道的采样周期,寄存器1配置剩下的采样周期。
6.5.ADC看门狗寄存器
ADC的看门狗寄存器可以用于配置阈值上限和阈值下限
超过阈值上限或者低于阈值下限就会产生相应的事件。
6.6.ADC数据寄存器
ADC的数据寄存器包括注入数据寄存器和规则数据寄存器
其中,注入数据寄存器有四个,可以分别保存注入4个注入通道组的转换数据;规则数据寄存器只有一个,用于保存规则通道组中的转换数据。
以上就是关于相关ADC的知识,欢迎大家批评指正!!!