当前位置: 首页 > news >正文

(51单片机)第五章-A/D和D/A工作原理-A/D

5.1 模拟量与数字量概述

        模拟量 数字量 模/数转换(A/D, Analog to Digital)数/模转换(D / A, Digital to Analog)

5.2 A/D转换原理及参数指标

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

1. 采样定理

       为正确无误地用采样信号vs表示模拟信号vI,必须满足采样定理:

$ f_s\ge 2f_{i\_\max} $

式中, $ f_s $为采样频率, $ f_{i\_\max} $为输入信号vI的最高频率分量的频率。

        在满足采样定理的条件下,可以用一个低通滤波器将信号vs还原为vI,这个低通滤波器的电压传输系数$ \left| A\left( f \right) \right| $ 在低于$ f_{i\_\max} $ 的范围内应保持不变,而在$ f-f_{i\_\max} $ 以前应迅速下降为零。因此,采样定理规定了AD 转换的频率下限。

 

因此,AD转换器工作时的采样频率至少满足$ f_s\ge 2f_{i\_\max} $ 。采样频率提高以后,留给 AD 转换器每次进行转换的时间也相应缩短了,则要求转换电路必须具备更快的工作速度。因此,不能无限制地提高采样频率,通常取$ f_s=\left( 3~5 \right) f_{i\_\max} $ 已经能够满足要求。因为每次把采样电压转换为相应的数字量都需要一定的时间,所以在每次采样以后,必须把采样电压保持一段时间。可见,进行 AD 转换时所用的输入电压,实际上是每次采样结束时的vI值。

        有关信号采样相关的理论分析详见《信号与系统》一书第七章内容() 

2. 量化与编码

         量化 量化误差 用不同的划分方法可以得到不同的量化误差

 补充知识:采样电路

(1)电路组成及工作原理:(N沟道MOS管T作为采样开关)

(2)改进电路及工作原理(LE198

3. 直接A/D转换器

        直接A/D转换器能把输入的模拟电压直接转换成输出的数字量而不需要经过中间变量,常用的电路主要有并行比较型和反馈比较型。

(1)并行比较型A/D转换器

        三位并行比较型 A/D 转换原理电路如图所示,它由电压比较器、寄存器和代码转换器三部分组成。电压比较器中量化电平的划分采用之前所述的方式,用电阻链把参考电压 VREF分压,得到从1/15VREF~13/15VREF之间7个比较电平,量化单位△=2/15VREF。然后,把这7个比较电平分别接到7个比较器~C,的输入端作为比较基准。同时将要输入的模拟电压同时加到每个比较器的另一个输入端上,与这7个比较基准进行比较。

        单片集成并行比较型 AD转换器的产品较多,如AD公司的AD9012(8位)、AD9002(8位)AD9020(10位)等。

并行 AD 转换器特点:

由于转换是并行的,其转换时间只受比较器、触发器和编码电路延迟时间限制,因此转换速度快

随着分辨率的提高,元件数目(电压比较器和触发器等)要按几何级数增加。一个n位转换器,所用的比较器个数为 2n-1,如8位的并行 AD 转换器就需要 28-1=255 个比较器。由于位数愈多,电路愈复杂,因此制成分辨率较高的集成并行 AD 转换器是比较困难的;

使用这种含有寄存器的并行 A/D 转换电路时,可以不用附加采样-保持电路,因为比较器和寄存器这两部分也兼有采样-保持功能,这也是该电路的一个优点。

(2)反馈比较型A/D转换器

        原理:取一个数字量加到 D/A 转换器上,得到一个对应的输出模拟电压,将这个模拟电压和输入的模拟电压信号比较,如果两者不相等,则调整所取的数字量,直到两个模拟电压相等为止,最后所取的这个数字量就是所求的转换结果。

        在反馈比较型 A/D 转换器中经常采用的有计数型逐次比较型两种方案。

(a)计数型 A/D 转换器

        下图为计数型 A/D 转换器原理框图。转换电路由比较器C、D/A 转换器、计数器、脉冲源、控制门G 以及输出寄存器等几部分组成:

        转换开始前先用复位信号将计数器置0,而且转换控制信号应停留在vL=0的状态,这时门G被封锁,计数器不工作。计数器加给 D/A 转换器的是全0信号,所以 D/A 转换器输出的模拟电压vo=0。如果为正电压信号,转换控制信号vL=1,比较器的输出电压为1,则计数器开始计数工作,DAC输出的逐渐升高直至等于(或大于)vI,比较器的输出电压为0,比较完成D/A的全部位数。

        因为在转换过程中计数器中的数字不停地变化,所以不宜将计数器的状态直接作为输出信号,为此在输出端设置了输出寄存器,在每次转换完成以后,用转换控制信号的下降沿将计数器输出的数字置入输出寄存器中,而以寄存器的状态作为最终的输出信号。这个方案的明显问题是转换时间长,当输出为n位二进制数码时,最长的转换时间可达到2n-1倍的时钟信号周期,因此这种方法只能用在对转换速度要求不高的场合。然而由于它的电路非常简单,所以在对转换速度没有严格要求时仍是一种可取的方案。

(b)逐次比较型A/D转换器

        逐次逼近型A/D转换器的工作原理可以用如下所示的框图来说明。这种转换器的电路包含比较器C、D/A转换器、寄存器、时钟脉冲源和控制逻辑等5个组成部分。

        转换开始前先将寄存器清零,所以加给D/A转换器的数字量也是全0。转换控制信号变为高电平时开始转换,时钟信号首先将寄存器的最高位置成1,使寄存器的输出为100…00。这个数字量被D/A转换器转换成相应的模拟电压vo,并送到比较器与输入信号,进行比较。如果vo>vI,说明数字过大了,则这个1应去掉;如果vo<vI,说明数字还不够大,这个1应予保留。然后,再按同样的方法将次高位置1,并比较“与”的大小以确定这一位的1是否应当保留这样逐位比较下去,直到最低位比较完为止。这时寄存器里所存的数码就是所求的输出数字量。

        三位逐次比较型A/D转换器的逻辑电路:

        对于n位输出的A/D转换器,完成一次转换所需时间为n+2个时钟信号周期。因此其转换速度要比并联比较型A/D转换器低,然而在输出位数较多时,逐次逼近型A/D转换器的电路规模要比并联比较型小很多。

        目前逐次逼近型A/D转换器产品的输出多为8至12位,转换时间多在几至几十微秒的范围内。个别高速产品的转换时间甚至能缩短至1ms以内。例如,12位逐次逼近型A/D转换器AD7472的最高取样速率可达1.75MSPS,完成一次转换的时间不到1s。

        其他集成逐次比较型 AD 转换器有 ADC0804/0808/0809系列(8)位、AD575(10位)、AD574A(12位)等。

(3)间接A/D转换器

        目前使用的间接 AD转换器多半都属于电压-时间变换型(V-T 变换型)和电压-频率变换型(V-F 变换型)两类。

        在 V-T变换型 AD 转换器中,首先把输入的模拟电压信号转换成与之成正比的时间宽度信号,然后在这个时间宽度里对固定频率的时钟脉冲计数,计数的结果就是正比于输入模拟电压的数字信号。

        在 V-F 变换型 AD 转换器中,则首先把输入的模拟电压信号转换成与之成正比的频率信号,然后在一个固定的时间间隔里对得到的频率信号计数,所得到的结果就是正比于输入模拟电压的数字量。

        下面首先展示的是V-T变换型 A/D转换器结构框图:

        下面首先展示的是V-F变换型 A/D转换器结构框图:

(4)A/D转换器的参数指标

分辨率——说明A/D转换器对输入信号的分辨能力

        AD 转换器的分辨率以输出二进制数的位数表示。从理论上讲,n位输出的 AD 转换器能区分 2n个不同等级的输入模拟电压,能区分输入电压的最小值为满量程输入的1/2n。在最大输入电压一定时,输出位数愈多,量化单位愈小,分辨率愈高。常用的有8、10、12、16、24、32 位等。假设第一位用来表示正负号,则其余位数表示信号的幅值。

转换误差——表示A/D转换器实际输出的数字量与理论输出数字量之间的差别

        在理想情况下,输入模拟信号所有转换点应当在一条直线上,但实际的特性不能做到输入模拟信号所有转换点在一条直线上。转换误差是指实际的转换点偏离理想特性的误差,般用最低有效位来表示。例如,给出相对误差≤±LSB/2,这就表明实际输出的数字量和理论上应得到的输出数字量之间的误差小于最低位的一半。注意,在实际使用中当使用环境发生变化时,转换误差也将发生变化。

③转换精度——A/D转换的最大量化误差和模拟部分精度的共同体现

        具有某种分辨率的转换器在量化过程中由于采用了四舍五入的方法,因此最大量化误差应为分辨率数值的一半AD 转换器数字转换的精度由最大量化误差决定。实际上,许多转换器末位数字并不可靠,实际精度还要低一些。

        由于含有 AD 转换器的模/数转换模块通常包括有模拟处理和数字转换两部分,因此整个转换器的精度还应考虑模拟处理部分(如积分器、比较器等)的误差。一般转换器的模拟处理误差与数字转换误差应尽量处在同一数量级,总误差则是这些误差的累加和

④转换时间——指A/D转换器从转换控制信号到来开始,到输出端得到稳定的数字信号所经过的时间

        不同类型的转换器转换速度相差甚远。其中并行比较A/D转换器转换速度最高,8位二进制输出的单片集成 A/D 转换器转换时间可达 50ns 以内。逐次比较型 A/D 转换器次之,它们多数转换时间在 10~50us之间,也有达几百纳秒的。间接 A/D 转换器的速度最慢,如双积分 A/D转换器的转换时间大都在几十毫秒至几百毫秒之间。

        在实际应用中,应从系统数据总的位数、精度要求、输入模拟信号的范围及输入信号极性等方面综合考虑 A/D 转换器的选用。

小结:

① 不同的 AD 转换方式具有各自的特点,在要求转换速度高的场合,选用并行 AD 转换器;在要求精度高的情况下,可采用双积分AD 转换器,当然也可选高分辨率的其他形式A/D 转换器,但会增加成本。由于逐次比较型 AD 转换器在一定程度上兼有以上两种转换器的优点,因此得到普遍应用。

②AD 转换器和 D/A 转换器的主要技术参数是转换精度和转换速度,在与系统连接后转换器的这两项指标决定了系统的精度与速度。

5.3 ADC0804工作原理及其实现方法

        集成 A/D 转换器品种繁多,选用时应综合考虑各种因素选取集成芯片。一般逐次比较型AD 转换器用得较多,ADC0804 就是这类单片集成 AD 转换器。它采用 CMOS 工艺 20 引脚集成芯片,分辨率为8位,转换时间为100μs,输入电压范围为0~5V。芯片内具有三态输出数据锁存器,可直接连接在数据总线上。下图左图为 ADC0804 双列直插式封装引脚分布图,右两图为ADC0804 芯片实物图:

1. 引脚说明:

        (1)VIN(+)、VIN(-)—两模拟信号输入端,用以接收单极性。双极性和差模输入信号;

        (2)DB7~DB0—具有三态特性数字信号输出口;

        (3)AGBD—模拟信号地;

        (4)DGND—数字信号地;

        注:在用到 A/D和 D/A时,一般这些芯片都提供独立的模拟地(AGND)和数字地(DGND)引脚,为了达到精度高,稳定性好的目的,最好将所有器件的模拟地和数字地分别连接,最后将模拟地与数字地仅在一点相连!

        (5)CLK—时钟信号输入端;

        (6)CLKR—内部时钟发生器外接电阻端,与CLK端装配可由芯片自身产生时钟脉冲,频率为1/(1.1RC);

        (7) $ \overline{\mathbf{CS}} $—片选信号输入端,低电平有效,$ \overline{\mathbf{CS}} $ 有效表示A/D转换器被选中,启动工作;

        (8) $ \overline{\mathbf{WR}} $—写信号输入,低电平启动A/D转换;

        (9) $ \overline{\mathbf{RD}} $—读信号输入,低电平输出端有效;

        (10) $ \overline{\mathbf{INTR}} $A/D转换结束信号,低电平表示本次转换已经完成;

        (11)VREF/2—参考电平输入,决定量化单位;

        (12)VCC—芯片电源5V输入。

2. 电路分析

        在ADC0804的芯片手册中,其典型的接法如下图所示:

        TX-1C 实验板上 ADC0804 外围电路及与单片机的连接是参照上图设计的,如下图所示:

        TX-1C上A/D外围电路如下图所示:

        A/D 右边的电位器 Re2 就是用来给 A/D 输入模拟电压的。做实验时,首先要将 AD 左边的插针 ADIN 用短路帽短路,这样电位器才与 AD 芯片连接上。设计这个插针的目的是,考虑可能会用 AD 采集实验板外面的模拟信号,这时直接与该插针连接就可以。编译代码下载程序后,可看到数码管前三位显示一个十进制数字,当拧动电位器时数字也跟着变化,变化范围为0~255。

3. 时序分析

        数字芯片在操作时首先要分析它的操作时序图,下图是ADC0804的启动转换时序图:

         分析上图可知, $ \overline{\mathbf{CS}} $先为低电平, $ \overline{\mathbf{WR}} $随后置低,经过至少tW($ \overline{\mathbf{WR}} $ )L时间后,$ \overline{\mathbf{WR}} $拉高,随后 A/D 转换器被启动,并且在经过(1~8个A/D 时钟周期+内部TC)时间后,模/数完成转换,转换结果存入数据锁存器,同时 $ \overline{\mathbf{INTR}} $自动变为低电平,通知单片机本次转换已结束。关于几个时间的大小在芯片手册中都有说明。

        对于TX-1C,下图是ADC0804 读取数据时序图:

 

        写单片机程序启动 AD 转换时就要遵循上面的时序,由于 TX-1C 实验板未用中断读取 AD 数据,因此在启动 AD 转换后,稍等一会时间,然后直接读取 AD 的数字输出口即可。读取结束后再启动一次 A/D 转换,如此循环下去。

        分析上图可知,当$ \overline{\mathbf{INTR}} $变为低电平后,将$ \overline{\mathbf{CS}} $ 先置低,接着再将$ \overline{\mathbf{RD}} $置低,在$ \overline{\mathbf{RD}} $ 置低至少经过 tAcc 时间后,数字输出口上的数据达到稳定状态,此时直接读取数字输出端口数据便可得到转换后的数字信号,读走数据后,马上将$ \overline{\mathbf{RD}} $ 拉高,然后再将 $ \overline{\mathbf{CS}} $拉高, $ \overline{\mathbf{INTR}} $是自动变化的,当RD 置低时间后, $ \overline{\mathbf{INTR}} $自动拉高,我们不必人为去干涉。上两图分别是启动一次和读取一次数据的时序图,当我们要连续转换并且连续读取数据时,就没有必要每次都把 $ \overline{\mathbf{CS}} $置低再拉高因为 $ \overline{\mathbf{CS}} $是片选信号,置低表示该芯片可被操作或处于能够正常工作状态,所以在写程序时只要一开始将 $ \overline{\mathbf{CS}} $置低,以后当要启动转换和读取数据时只需操作 $ \overline{\mathbf{WR}} $$ \overline{\mathbf{RD}} $即可。

4. 程序中面临的实际问题若干:

(1)根据A/D转换器的时序图,在程序中需要用到机器周期延时函数_nop_(),需要引用#include<intrins.h>库函数:

       应用举例:

(2)进入主程序后,首先将 U2锁存器的输出口的最高位置低电平,目的是将与之相连的 ADC0804 的CS片选端置低选中,因为本例程专门操作 AD芯片,所以一次选中,以后再不用管它:

        同时要注意,以后凡是操作U2锁存器的地方都不要再改变 AD 的CS端,在数码管显示程序中,送出位选信号时,我们始终保持U2锁存器的最高位为低电平,于是将数码管显示段选部分修改为:

uchar code wela_table[]=  //片选数码库
{0xdf/*最低位*/,0xef,0xf7,0x7b,0x7d,0x7e/*最高位*/	//从右向左数第一到六位/*特别地,这里最高位为0x7bde而非0xfbde是由于段选公用U2锁存器,而AD的CS端需要一直保持低电平不变*/
};

否则,即使后续程序正确数码管将始终显示255锁死不会变!

(3)主程序分析:注意分为三次采样P1口的数值以保证稳定

5. 示例 

        用单片机控制 ADC0804 进行模数转换,当拧动实验板上 A/D 旁边的电位器Re2 时,在数码管的前三位以十进制方式动态显示出 AD 转换后的数字量(8位 AD 转换后数值在 0~255 变化)。

        自己改进后的代码:

#include<reg52.h>
#include<intrins.h> //用到的机器周期延时函数_nop_()需要用到此库 
#define uchar unsigned char
#define uint unsigned intsbit dula=P2^6; //声明锁存器U1的锁存端
sbit wela=P2^7; //声明锁存器U2的锁存端
sbit adwr=P3^6; //定义A/D的WR端口
sbit adrd=P3^7; //定义A/D的RD端口uchar code dula_table[]={ //段选数码库0x3f,0x06,0x5b,0x4f, // 0,1,2,30x66,0x6d,0x7d,0x07, //4,5,6,70x7f,0x6f,0x77,0x7c, //8,9,10,110x39,0x5e,0x79,0x71  //12,13,14,15
};uchar code wela_table[]=  //片选数码库
{0xdf/*最低位*/,0xef,0xf7,0x7b,0x7d,0x7e/*最高位*/	//从右向左数第一到六位/*特别地,这里最高位为0x7bde而非0xfbde是由于段选公用U2锁存器,而AD的CS端需要一直保持低电平不变*/
};void main()
{uchar ge,shi,bai,adval1,adval2,adval3; //avoid init_AD(); //AD转换器初始化函数void delayxms(uint xms); //延时函数 ms为单位void display(uchar num_bai,uchar num_shi,uchar num_ge); //数码管显示函数 init_AD(); //AD转换器初始化while(1){P1=0Xff; //读取P1口前先给其全写1adwr=1;	//关闭A/D转换_nop_();adwr=0; //启动A/D转换_nop_();adwr=1;adrd=1; //选通ADCS_nop_();adrd=0; //AD读使能_nop_();adval1=P1; //读取赋予P1口的AD数据delayxms(2);adval2=P1;delayxms(2);adval3=P1;adrd=1;if((adval1==adval2)&&(adval2==adval3)){ //计算数字bai=adval3/100;//百位shi=adval3%100/10;//十位ge=adval3%10;//个位 display(bai,shi,ge);		}		}
}void init_AD() //AD转换器初始化
{wela=1;P0=0x7f; //置CSAD为0,选通ADCS以后不必再管ADCSwela=0;delayxms(50);	
}void delayxms(uint xms) //延时函数 ms为单位
{uint x,y;for(x=xms;x>0;x--)for(y=31;y>0;y--); //改进延时为0.5毫秒	
} void display(uchar num_bai,uchar num_shi,uchar num_ge) //数码管显示函数 
{uint wei; //位选数字void wedu(uchar dula_num,uchar wela_num); //数码管位选段选函数for(wei=3;wei<6;wei++){switch(wei){case 3: wedu(num_ge,wei);break;case 4: wedu(num_shi,wei);break;case 5: wedu(num_bai,wei);break;}dula=1; //打开U1锁存端P0=0x00; //防止最高位数码管过亮dula=0; //关闭U1锁存端	}
}void wedu(uchar dula_num,uchar wela_num) //数码管位选段选函数
{wela=1; //打开U2锁存端P0=wela_table[wela_num]; //送入U2锁存端wela=0; //关闭U2锁存端P0=0xc0; //消影,防止P0残留电位信号干扰段选dula=1; //打开U1锁存端P0=dula_table[dula_num]; //送入段选信号dula=0; //关闭U1锁存端P0=0xff; //消影,防止P0残留电位信号干扰片选delayxms(10);
}

         效果:

         原书程序主程序部分以及可能面临的问题:

 

参考资料: 

[1] 郭天祥. 新概念51单片机C语言教程:入门、提高、开发、拓展全攻略[M]. 北京: 电子工业出版社, 2009.

相关文章:

  • 中小型生产企业工业数据采集分析平台 规划生产流程
  • 买瓜(dfs+剪枝)
  • 安卓Java面试题 51-60
  • OxyPlot图表曲线图学习笔记(winform)
  • python基础及网络爬虫
  • C语言第三十七弹---文件操作(下)
  • 【新手适用】手把手教你从零开始实现一个基于Pytorch的卷积神经网络CNN一: 创建model模块和加载数据集
  • MySQL 函数
  • Java后端八股------消息中间件篇
  • 微信小程序云开发教程——墨刀原型工具入门(素材面板)
  • 记录一个编译的LLVM 含clang 和 PTX 来支持 HIPIFY 的构建配置
  • Java的控制流语句详解
  • 网络通信另个角度的认识(进程间通信),端口号(为什么要有,和pid的关系,如何封装,和进程的定位原理+对应关系)客户端如何拿到服务端的port
  • 数据结构奇妙旅程之二叉平衡树进阶---AVL树
  • scrapy的基本使用介绍
  • #Java异常处理
  • Angular 4.x 动态创建组件
  • C学习-枚举(九)
  • iOS | NSProxy
  • Java的Interrupt与线程中断
  • Linux中的硬链接与软链接
  • mysql中InnoDB引擎中页的概念
  • PHP的Ev教程三(Periodic watcher)
  • Python学习笔记 字符串拼接
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 开源SQL-on-Hadoop系统一览
  • 前端存储 - localStorage
  • 使用iElevator.js模拟segmentfault的文章标题导航
  • 事件委托的小应用
  • 试着探索高并发下的系统架构面貌
  • 我有几个粽子,和一个故事
  • 用Canvas画一棵二叉树
  • zabbix3.2监控linux磁盘IO
  • 通过调用文摘列表API获取文摘
  • ​MPV,汽车产品里一个特殊品类的进化过程
  • ​如何在iOS手机上查看应用日志
  • #{}和${}的区别?
  • (动手学习深度学习)第13章 计算机视觉---图像增广与微调
  • (附源码)spring boot建达集团公司平台 毕业设计 141538
  • (附源码)ssm户外用品商城 毕业设计 112346
  • (附源码)ssm考生评分系统 毕业设计 071114
  • (附源码)计算机毕业设计SSM智能化管理的仓库管理
  • (含react-draggable库以及相关BUG如何解决)固定在左上方某盒子内(如按钮)添加可拖动功能,使用react hook语法实现
  • (原創) 人會胖會瘦,都是自我要求的結果 (日記)
  • (转)全文检索技术学习(三)——Lucene支持中文分词
  • .jks文件(JAVA KeyStore)
  • .NET Core 中插件式开发实现
  • .net framwork4.6操作MySQL报错Character set ‘utf8mb3‘ is not supported 解决方法
  • .net生成的类,跨工程调用显示注释
  • .NET应用架构设计:原则、模式与实践 目录预览
  • /dev/sda2 is mounted; will not make a filesystem here!
  • @Bean, @Component, @Configuration简析
  • []Telit UC864E 拨号上网
  • [android] 练习PopupWindow实现对话框