新闻资讯

信息技术:单片机A/D采样和转换的原理
2020-06-17 08:59:46来源:100唯尔

  单片机A/D采样的原理 是信息专业学生专业课。

  自己学习的单片机也有一段时间了,刚开始接触单片机的时候,就总是强调AD,单片机自带AD不,等一些说法,但是自己从来没有仔细想过AD的过程,只是知道是将模拟量转化为数字量,但是不知道这个采集过来的电压是2.5V,为什么在数码管上显示为2.5V就是转化成数字量了,现在来说一下自己的理解,只是自己的主观理解,不一定准确!

  A/D转换器中,因为输入的模拟信号在时间上式连续的,而输出的数字信号代码是离散的。所以A/D转换器在进行转换时,必须在一系列选定的瞬间(时间轴上的一些规定点上)对输入的模拟信号采样保持,然后再把这些采样值转换为数字量。因此,一般的A/D转换过程是通过采样保持、量化和编码这三个步骤完成的,即首先对输入的模拟电压采样保持,采样结束后进入保持时间,在这段时间内将采样的电压量转化为数字量,并按一定的编码形式给出转换结果,然后开始下一次采样。下图给出模拟量到数字量转换过程图:   

  

  采样定理

  可以证明,为了正确无误的用5.2.2图中所示的采样信号Vs表示模拟信号V1,必须满足:

  

  因此,A/D转换器工作时采样频率必须高于上式所规定的频率。采样频率提高后,留给A/D转换器每次转换时间缩短。

  

  

  

  所谓模拟量很好理解就是模拟量是指变量在一定范围连续变化的量;也就是在一定范围(定义域)内可以取任意值(在值域内)。数字量是分立量,而不是连续变化量,只能取几个分立值,如三位进制数字变量只能取7个整数值0.1.2.3.4.5.6.7。

  而不是经过AD通道的话,经过的是普通的IO口,那么模拟信号只会在引脚上出现两种数字结果,一个是1一个是0,而不能比较准确的描述出模拟量的数值,模拟量信号是一种变量信号,比如果0V--10V,或50MA到100MA,开关信号是一种通断信号,比如家里的灯开关,数字信号是一种连续的开关信号或高低电平信号,比如1101----高高低高。一连串的信号代表数字信号。

  再继续说一下AD精度的问题,8位AD精度的话就是将这个满电压值分成2^8=256份,比方说51单片机采集的电压范围是0-5v那么0v对应的是0 5v对应的是255.

  现在再来讲解一下逐次逼近型ADC的原理。

  一、逐次逼近式AD转换器与计数式A/D转换类似,只是数字量由“逐次逼近寄存器SAR”产生。SAR使用“对分搜索法”产生数字量,以8位数字量为例,SAR首先产生8位数字量的一半,即10000000B,试探模拟量Vi的大小,若Vo>Vi,清除最高位,若Vo

  

  单片机会读到什么值?

  单片机读值看一个特性,就是几位的ADC,在手册上就会给出,例如,STM32的 ADC是 12位的。另外,还有8位,10位,16位,24位等。

  我先告诉你答案:STM32读到的 ADC值,是从0到4095,当你把 ADC引脚接了GND,读到的就是 0,当你把 ADC引脚接了 VDD,读到的就是 4095。

  接下来告诉你为什么:前面提到,STM32的ADC是 12位的,我们知道,8位的值是从 0 ~ 255;16位的值,是从 0 ~ 65535。这两个位的最大值,是我们最为熟悉的。

  (怎么算出来的?这问题就又降低到另一个层面了,这里我们说的几位的值,每个位只能是 0或者 1,比如 2位的值,可以表示为 00 01 10 11四种不同的值,这是以 2进制表示的,转换成十进制就是 0 1 2 3,所以得出结论,2位的值可以表示从0 ~ 3。同理,3位的值,可以表示十进制的 0 ~ 9,你可以展开计算一下。4位的值,可以表示0~16,5位的值,可以表示从 0 ~ 31,同理,你可以得出任意位的值可以表示的范围。)

  所以,12位的值,可以表示从 0 ~ 4095(2^12),这就是先在感性上,认识了为什么 12位的 ADC的值,是从 0 ~ 4095.

  读到的值怎么换算成实际的电压值?

  前面提到了,我们输入GND,读到的值是0,输入VDD,得到的值是4095,那么,当你读到2035的时候,你知道输入电压多少V吗?这个问题,归根接地,就到了数学 XY坐标,已知两点坐标值(0, 0)(3.3, 4095),给出任意X坐标值,求Y值的问题了吧?简单不简单?

  ADC测电压示意图:

  参考电压是什么?

  讨论这个问题之前,你先拿万用表量一下你的 VDDA的实际电压是多大?是不是标准的 3.300V?应该不是吧?或许是 2.296V,或许是 3.312V。然后你把 VDD连接到ADC引脚之后,得到的是 4095,也就是,实际上,当你读出4095这个数据的时候,实际的电压值不是你想象中的 3.300V。有些初学者,觉得几毫伏的电压差无所谓,但实际应用中,几毫伏就可能代表很大的实际工况,例如,在一个量程为 50克的电子称上。

  所以,这时候,芯片厂商就想了一个办法,给 ADC模块中引入参考电压,由非常标准的参考电压芯片来接入参考电压引脚。标准的电压芯片,我们一般叫做参考电压芯片,或者叫做基准电压芯片。例如 REF3133(输出 3.300V) REF3025(输出 2.500V)等等。

  注意:STM32 的 100脚以上(含 100脚)有参考电压引脚。在没有参考电压引脚的单片机上,可以把基准电压芯片接入 VDDA,但是 VDDA和 VDD的电压差不能超过 0.3V,例如,VDD是 3.3V的话,可以给 VDDA接入一个 3.3V的参考电压芯片或者 3.0V的参考电压芯片,但是不能接入 2.5V的参考电压芯片,后果就是芯片不能工作。

  ADC引脚的输入电压范围是多大?

  一般情况下,ADC引脚的输入电压,是从0 ~ VDD,如果有REF引脚,一般是0 ~ Vref,也有0 ~ 2Vref 的情况。

  如果被测的电压大于ADC的输入电压,例如,要用STM32测量 0 ~ 5V的电压的话,可以在输入ADC引脚之前,加入电阻分压和放大器电路。

  注意:如果用内部基准电压作为参考基准,公式就跟用外部芯片供电电压测量有点不同

  #define REF_VOLTAGE 1224UL // 基准电压千倍

  #define VOLTAGE 3300UL // 电压千倍

  #define ADC_DIP(X) (X) // ADC分辨率

  一般我们用外部芯片供电电压为参考基准就用下面那个公式,也就是上面说的XY比例

  ADC_value = (uint32_t)(ADC_value*VOLTAGE >> ADC_DIP(12)); // 换算成千倍的电压值

  若用内部基准电压作为参考则用以下公式

  VDD_value = (uint32_t)((REF_VOLTAGE << ADC_DIP(12)) / VDD_value); // 换算成千倍的电压值

  内置的参照电压看芯片的datasheet;外部芯片供电电压最好用万用表测一下