目录
AD/DA介绍
AD(Analog to Digital):模拟-数字转换,将模拟信号转换为计算机可操作的数字信号。有时候我们也把AD叫做ADC(C是转换器converter的缩写)。比如说模拟电压,单片机是数字信号,数字信号是只有0V和5V两种状态,如果说输入个2.5V时,那我们怎么读它呢?它是属于高电平还是低电平呢?这时候,我们要读它就需要用一个AD转换器,将2.5V转换为一个数字存储在空间里。这就是AD转换的一个作用。
DA(Digital to Analog):数字-模拟转换,将计算机输出的数字信号转换为模拟信号。有时候我们也把DA叫做DAC(C是转换器converter的缩写)。DA是反过来的,它是数字到模拟转化。比如说单片机只能输出高电平和低电平(5V和0V),我们怎么输出1V,2V和3V呢?我们要输出一个数据,然后通过DA把这个数据转化为一个电压。这就是DA的作用。
AD/DA转换打开了计算机与模拟信号的大门,极大的提高了计算机系统的应用范围,也为模拟信号数字化处理提供了可能。

上面第一张图是光敏电阻,阻值会随着光线的变化而变化。

第二张图是热敏电阻,阻值会随着温度的变化而变化。如果我们把上图的光敏电阻换成热敏电阻,也就可以获取热敏电阻这一点的电压,从而可以知道温度的高低。
第三张图是麦克风,也可以通过这种电阻分压的形式,将人说话的声音信号转换为一个电压信号,然后通过电压采集,那数字系统就可以采集到这个声音信号了。
第四张图是一个扬声器(麦克风),像我们电脑里存的数字音乐就是数字信号,怎么才能将它输出到扬声器进行播放呢?就需要DA将这个数字信号代表的电压转换成实际的电压,形成一个连续的电压波形,再送给麦克风,这样就可以听到数字信号储存的音乐了。
AD/DA在开发板的这里

硬件电路模型

PS:模拟量和数字量是成正比的,比如说模拟量是0V,则数字量就是0;如果模拟量是5V,则数字量就是255;如果模拟量是2.5V,则数字量就是255/2;
DA的应用一般可以用PWM来代替,所以DA的使用没有AD广泛。
AD转换通常有多个输入通道,用多路选择开关连接至AD转换器,以实现AD多路复用的目的,提高硬件利用率
AD/DA与单片机数据传送可使用并口(速度快、原理简单),也可使用串口(接线少、使用方便)
可将AD/DA模块直接集成在单片机内,这样直接写入/读出寄存器就可进行AD/DA转换,单片机的IO口可直接复用为AD/DA的通道
硬件电路
我们开发板上的原理图上的AD芯片:

原理图上的DA芯片:

但是我们这一篇主要介绍ADC0809和DA0832,这两个芯片是比较老旧的,但是它比较经典。所以我们主要了解它们的原理,实际应用的话还是可以用现在新的一些开发板上的AD、DA芯片。
ADC0809:

DA0832:

先看ADC0809的内部框图和实际芯片

再看DA0832的芯片引脚图和内部框图:

在介绍AD/DA的原理之前先介绍一下运算放大器
运算放大器
运算放大器(简称"运放")是具有很高放大倍数的放大电路单元。内部集成了差分放大器、电压放大器、功率放大器三级放大电路,是一个性能完备、功能强大的通用放大电路单元,由于其应用十分广泛,现已作为基本的电路元件出现在电路图中
运算放大器可构成的电路有:电压比较器、反相放大器、同相放大器、电压跟随器、加法器、积分器、微分器等
运算放大器电路的分析方法:虚短、虚断(负反馈条件下)

其实对于运放的初学者,只需要记住下面这一张图基本可以解决很多问题了。

首先这是电路中运放的符号,主体是一个三角形,上面有5个引脚

这两个是电源

上正下负,分别可以接5V和-5V

也可以分别接5V和地,一般来说这种接法是比较多的

这两个是输入

这个是输出

这是运放的传输特性图

运放的内部工作我们可以认为里面是一个开关,这个开关可以打到VCC即5V的一边,也可以打到GND即0V的一边。

那这个开关什么时候打到VCC这边或GND的一边呢?
这取决于Up和Un的差值。
当Up>Un时,(开关打到VCC)则输出电压就接近于正电源电压Uout=5V
当Up<Un时,(开关打到GND)则输出电压就接近于负电源电压Uout=0V

当Up和Un差不多大时,则输出电压=A(Up-Un)+2.5
A是运放的放大倍率,运放的固有参数,我们一开始并不需要太关注这个参数,只需要知道一般来说A都非常大,可以达到几十万,也就是说这根线会非常陡峭,或者说这部分的宽度非常窄。Up和Un相差几十微伏或者更小时,才会进入这个区间。

以上就是运放的初级理论知识,下面开始看运放的第一个实际应用。
运放作为一个电压比较器来使用
我们来看这是一颗非常常见的运放LM358,价格相当便宜,只要几毛钱。

而且里面还集成了两个运放

我们只需要用到其中一个就可以了

给它接好电源和地,然后Up这边用信号发生器给它输入一个正弦波,Un这边通过这个可调电阻,让它从0V到5V开始变化。

Un电压从0V上升到5V的过程中,输出电压分别会是什么样子的波形?

显然当Un电压在正弦波下面时,Up都是大于Un的,所以输出为高电平

当Un电压处于正弦波中间时,下面这部分对应输出低电平,上面这部分对应输出高电平

显然当Un电压在正弦波上面时,输出就为低电平

在实际使用的时候,正弦波的输入可以替换为一些传感器电压的输入

比如说这样一个电路

给光敏电阻光照时,Un>Up,运放就输出低电平

没有光照时,Un<Up,运放就输出高电平

那么运放作为一个电压比较器来使用时,我们发现这个实际应用中我们主要用到的是运放的这两个区间:

也就是运放的非线性区或者叫饱和区
而运放真正的核心其实是在这一个狭窄的区间里,也就是线性区

但是这个区间实在是太狭窄了,为了能够用到这个区间,需要引入一个概念:负反馈。
可以这么说,有了负反馈,运算放大器才能被称为是运算放大器,否则只能被称为放大器。
下面我们来看一下这张图

将Un和输出接在一起,问Un电压是多少?
此时Un大概等于Un=2.9999x
因为只要Un和Up不相等,或者说差的很多,那么输出电压就一定会变成5V或者0V,进而通过这个路径反馈回来,不断修正Un的电压,直到它和Up电压差不多为止。

也就是会对应到这条线上的某一个点,这就是所谓的负反馈。

负反馈的过程:
因为当Up>Un时,Uout要从Un上升到5V,上升到3.1V左右时,此时 Uout=Un>Up,Uout又要下降到0,但在下降到2.9V时,Uout=Un<Up,于是Uout又要上升。所以Uout会在 Up 附近震荡,且越来越接近Up。
如果初学者想不明白负反馈的过程也没关系,我们只需要记住一个非常重要的结论:
当给运放引入负反馈,也就是把输出和Un接在一起时,Un就约等于Up。同时又因为Up和Un差的实在太少了,只相差几十微伏不到,所以我们就认为Up等于Un了。

这里的负反馈不一定是完全短接,通过一个电阻电容连接都是可以的。然后在这些电路中输入输出的关系分别是这样子的(如图中的关系式),你会发现第一个电路实现了比例的运算,第二个电路实现了加法的运算,而这个电路实现了积分的运算。

所以所谓的运算放大器,它是真的可以用来做运算的
不过在这些图中,初学者用的最多的是这张图:

那它有什么用呢?
我们可以这样子把它接入一个系统

其中Rs是一颗阻值非常小的采样电阻,用来检测系统的电流,比如说10毫欧姆。
假如说流过负载的电流有1A,那么此时Rs这一端大概会产生一个10mV的电压。
这个电压实在太小了,以至于我们没有办法很好的测量到,所以此时运放的这部分电路就派上用处了。假设此时R1是49千欧姆,R2是1千欧姆,那么这个运放就可以把Rs上的电压放大50倍输出。这样我们就可以很方便的通过测量输出电压。反推负载上的电流了。

以上就介绍完了初学者需要掌握的运放的两个主要应用场景。
一个作为比较器,另外一个是作为比例放大器来使用

以上电压放大器是一种同向放大器。
同向放大器只要稍微变化一下就可以做一个电压跟随器
电压跟随器(Uin=Uout)。虽然没有电压放大的特性,但是它有功率放大的特性。它可以提高输入信号的驱动能力,因为它内部有功率放大器。比如说输入信号没有驱动能力时,通过这个电路时,可以输出一个一模一样的信号,同时它有了驱动能力。

我们再补充一下它作为一个反向放大器的实际运用:
反向放大器(输入的电压和输出的电压是反向的)

这种放大器必须接双电源,就是接VCC和GND。

再补充两个知识点:
虚短状态:负反馈状态下负极输入的电压和正极输入的电压是基本相等的。
虚断状态:由于输入阻抗比较大,电流既不从负极输入端流入也不流出。
那我们利用这两个知识来分析一下反向放大器的电路:
首先负反馈条件下,负极输入端和正极输入端处于虚短状态,由于正极输入接了GND,则负极输入端=正极输入端=0V。
我们假设负极输入一个0.1V的电压,这时就产生一个电流0.1V/R1,由于输入阻抗非常大,这里处于虚断状态,所以这个电流既不会从输入端流出也不流入,所以电流往R2所在的支路流,,这时候R2所在的支路就产生压降****(电流流过电阻会产生电压下降,**** 简称压降 ) ,压降=0.1V/R1(电流)*R2,那么输出端的电压就等于0V-压降,即0V-(0.1V/R1)*R2= -(Uin/R1)*R2。( R2/R1 就是我们可以灵活调节的放大倍数 )

同理,同向放大器的电路(输入的电压和输出的电压是同向的)也可以利用这两个知识点来分析:
首先负反馈条件下,负极输入端和正极输入端处于虚短状态,则负极输入端=正极输入端=Uin。
经过R1电流是Uin/R1。由于输入阻抗非常大,负极输入这里处于虚断状态,所以没有电流从输入端流入,有一个大小和方向一样的电流从R2所在的支路流向R1所在支路。这时候R2所在的支路就产生压降,压降=(Uin/R1)*R2,那么输出端的电压就等于Uin+压降,即Uin+(Uin/R1)*R2=(1+R2/R1)*Uin。((1+R2/R1)就是我们可以灵活调节的放大倍数)

其他运放应用电路的分析同理。
了解了电压放大器之后,我们就可以开始分析AD/DA的工作原理了!
DA原理
T型电阻网络DA转换器

上图是前面讲过的这个芯片的内部结构

解析:

看了上图的解析,我们知道了当Rfb=R时的输出电压,那么如果Rfb不等于R呢?电压的表达式怎么来的呢?
我们知道这其实是一个我们前面讲过的反向放大器模型。
如果我们能算出这一点的电流,那么电流通过反馈电阻分压,就可以得出输出电压了。

我们看图就知道这一点的电流是上面的模拟开关拨到1时,上面的所有支路上下来的电流的总和。

首先电阻网络部分下来的总电流I如何确定呢?

这么多电阻并联有串联,最终总阻值等于R,则总电流I=Vref/R

那每一支路的电流是多少呢?
每一个并联支路的电流的2倍就等于相应干路上的电流。
最终总电流I就等于2倍的I7:I=2I7

这样实现的是下面8位二进制数据的每一个的位权。比如D1就是D0的2倍,D2就是D1的2倍。

最终I7就等于多少呢?如果以I0为一个单位的话,I7=128*I0
那么I=2I7=2*128*I0=256*I0
I0=I/256=(Vref/R)/256
这样其他的支路电流就都可以计算出来了。
I7=128*I0,I6=64*I0,I5=32*I0,I4=16*I0,I3=8*I0,I2=4*I0,I1=2*I0
从模拟开关上下来的支流电流汇集在一起是多少个I0呢,就取决于下面8位数据量表示的数值。如果这个数据量表示128,二进制数是1000 0000,则只有第一个模拟开关拨到了1,那么只有I7下来,则从模拟开关上下来的支流电流汇集在一起是128个I0。

则输出电压的表达式可以出来了

PS:总电流I=Vref/R ,汇集下来多少份电流= (D7~D0)/256*总电流;
汇集下来多少份电流就是流过Rfb的电流,则输出电压=0V - 汇集下来多少份电流 *Rfb
当然我们常用的是Rfb=R的情况,所以输出电压表达式是:

以上这种T型电阻网络DA转换器的缺点是比较占用IO口。
我们开发板上的应用的是PWM型DA转换器,这种模型的好处就是比较节省IO口(一个口输出PWM信号,一个输出端),并且输出的电压精度比较高(只要占空比比较精细)。缺点是比较消耗单片机资源,因为得输出PWM波形,而且如果低通滤波器的性能不好的话,输出的电压还会有一定的纹波。
我们来看一下这种PWM型DA转换器:
PWM型DA转换器

这其实就是我们开发板上用的这种PWM型的DAC,只不过我们开发板上的原理图比较复杂一点。

解析:

那为什么PWM信号加低通滤波器就能变成一个稳定的直流电压信号呢?
是因为0~5V的PWM信号占空比50%,它其实是有一个直流分量和一个交流分量在里面的。加一个低通滤波器,截止频率很低,它可以把交流分量给过滤掉,剩下的就是直流分量****(这个直流分量最终就是DA输出)****,也就是直流分量就是PWM信号的平均值。那这个平均值是多少呢?如果占空比是50%,那平均值就是2.5V,如果高电平的时间长一点,那很明显平均值就会上升。如果全是高电平的话,平均值就是5V。如果全是低电平的话,平均值就是0V。

当然后面的结构驱动能力是很弱的,如果接负载,就会影响滤波性能。为了隔离后面的输出电路,一般会跟一个电压跟随器(输入电压=输出电压,驱动能力很强)

这整个模型的关系式:

PS:VH是高电平
通过上面的分析,其实我们可以将我们开发板上的原理图简化成这样:

AD原理
逐次逼近型AD转换器

这个就是我们前面说的这个芯片的内部图

它的工作原理就是,比如输入一个信号,比如说是2.5V,但是我们还不知道是多少V,我们用DAC输出一个电压和这个未知的电压进行比较,如果DAC的比未知电压小,就把DAC的电压调高,反之则调小。最终让这两个电压接近相等,那DAC的电压就可以表示未知的这个电压了。间接地把模拟的电压量转换成数字量的了。

比较的结果就是高低电平,这个结果就会控制DAC输出,如果DAC输出高了,就把DAC的降一下,如果输出低了,就把DAC的升一下,一位一位地试,当把8位DAC精度试完之后,就可以把DAC的8位数据当做未知模拟电压值,然后再加定时和控制,EOC(是否转换完)这些标志位,另外DAC还需要参考电压。
最后用一个输出缓存器就可以把这个数字量输出了。


其实以上的工作原理是利用的二分法查找这种方法
比如,输入一个在0V~5V范围的模拟电压,我们首先让DAC产生一个2.5V的中间值和这个未知电压进行比较,如果这个未知电压比2.5V小的话,我们就把DAC调成(0+2.5)/2=1.25V再进行对比,如果比未知电压大的话,我们就把ADC调成(1.25+2.5)/2的电压和它对比,如此循环,最终8次对比就可以和未知电压的值接近了。
根据这个例子,我们其实是将DAC的8位数据从左往右,就是将第一位置1,第二位置1......这样开始和未知电压进行对比。那么比如首先把DAC的2.5V,即1000 0000(也即128)和未知电压进行对比,如果未知量比这个数小,那么我们把第一位置0,第二位置1,即0100 0000(表示64,也即1.25V),如果未知量比这个数大,那么这个1就保留,再把第三个置1,即0110 0000(表示96,也即(1.25+2.5)/2)再比较......依次判断8位,最终这8位数据取出来就是表示我们的未知电压。

AD/DA性能指标
分辨率:指AD/DA数字量的精细程度,通常用位数表示。例如,对于5V电源系统来说,8位的AD可将5V等分为256份,即数字量变化最小一个单位时,模拟量变化5V/256=0.01953125V,所以,8位AD的电压分辨率为0.01953125V,AD/DA的位数越高,分辨率就越高。
转换速度:表示AD/DA的最大采样/建立频率,通常用转换频率或者转换时间来表示,对于采样/输出高速信号,应注意AD/DA的转换速度。
通过以上介绍我们了解了逐步逼近型AD转换器的原理,那么我们来看一款逼近型AD转换器芯片:
XPT2046

XPT2046时序


比如下图,三个设备共用那三根线,每个芯片都有单独的CS片选,如果主机要和设备1进行通信,那就把第一个CS选中,其他设备不影响通信。

注:有时候DIN也叫MISO(主设备输入从设备输出),DOUT也叫MOSI(主设备输出从设备输入)
解析图:

再看我们开发板上原理图:

以上就是本篇全部内容,下一节开始代码演示!