第四章AD及DA与温度显示.docx
《第四章AD及DA与温度显示.docx》由会员分享,可在线阅读,更多相关《第四章AD及DA与温度显示.docx(69页珍藏版)》请在冰豆网上搜索。
第四章AD及DA与温度显示
第四章A/D及D/A
项目一A/D转换
【项目任务】
将电位器输出的电压值转换成数字量并显示在数码管上。
【任务分析】
将电压、电流等模拟量转换成数字量,就需要相应的转换芯片,单片机采集模拟信号时,通常需要在前端加上模拟量/数字量转换器,简称模/数转换器,即通常所说的A/D转换芯片。
【硬件选择】
电源模块、主机模块、显示模块、ADC/DAC模块。
【接线及原理图】
1.接线表(见表4-1)
表4-1
P0.0-P0.7
AD0809芯片的D0-D7
P3.3
EOC
P3.6
WR
P3.7
RD
P2.7
CS
时钟源OUT
CLK
A、B、C
GND
电压源OUT
IN0
P1.0-P1.7
数码管D0-D7
P3.0
CS1
P3.1
CS2
P3.2
CSWR
电源+5V,GND
所有模块的+5V,GND
2.原理图(如图4-1所示)
图4-1AD转换原理图
【知识链接】
1.什么是模拟量、数字量
模拟信号是时间连续、数值连续的物理量,他具有无穷多个数值,其数学表达式也很复杂,例如正弦函数、指数函数等。
人从自然界感知的许多物理量均是属于模拟性质的,例如速度、压力、温度、声音、重量以及位置等等。
在工程技术上,为了便于分析常用传感器将模拟量转换为电流、电压或者电阻等电学量。
(如图4-2和图4-3所示)
图4-2不规则的模拟量图4-3正弦波模拟量
数字量就是用一系列0和1组成的二进制代码表示某个信号大小的量。
用数字量表示同一个模拟量时,数字为位数可多可少,位数越多,则表示精度越高,位数越少则表示精度越低。
数字信号在时间上和数值上是离散的,上面所说的0和1不是十进制中的数字,而是逻辑0和逻辑1,因而称之为二进制数字逻辑,或者简称数字逻辑。
二值数字逻辑的产生,是基于客观世界的许多事物可以彼此相关又互相对立的两种状态来描述的,例如,是与非、真与假、开与关,如此等等。
而且在电路上,可以用电子元器件的开关特性来实现的,由此形成离散信号电压或数字电压。
这些数字电压通常用逻辑电平来表示。
应当注意,逻辑电平不是物理量,而是物理量的相对表示。
2.模/数转换原理
模数转换是将模拟输入信号转换为N位二进制数字输出信号的技术。
采用数字信号处理能够方便实现各种先进的自适应算法,完成模拟电路无法实现的功能,因此,越来越多的模拟信号处理正在被数字技术所取代。
与之相应的是,作为模拟系统和数字系统之间桥梁的模数转换的应用日趋广泛。
为了满足市场的需求,各芯片制造公司不断推出性能更加先进的新产品、新技术。
模数转换包括采样、保持、量化和编程四个过程。
采样就是将一个连续变化的信号x(t)转换成时间上离散的采样信号x(n)。
根据奈奎斯特采样定理,对于采样信号x(t),如果采样频率fs大于或等于2fmax(fmax为x(t)最高频率成分),则可以无失真地重建恢复原始信号x(t)。
实际上,由于模数转换器器件的非线性失真,量化噪声及接收机噪声等因素的影响,采样速率一般取fs=2.5fmax。
通常采样脉冲的宽度tw是很短的,故采样输出是断续的窄脉冲。
要把一个采样输出信号数字化,需要将采样输出所得的瞬时模拟信号保持一段时间,这就是保持过程。
量化是将连续幅度的抽样信号转换成离散时间、离散幅度的数字信号,量化的主要问题就是量化误差。
假设噪声信号在量化电平中是均匀分布的,则量化噪声均方值与量化间隔和模数转换器的输入阻抗值有关。
编码是将量化后的信号编码成二进制代码输出。
这些过程有些是合并进行的,例如,采样和保持就利用一个电路连续完成,量化和编码也是在转换过程同时实现的,且所用时间又是保持时间的一部分。
实现这些过程的技术有很多,从早在上世纪70年代就出现的积分型到最新的流水线模数转换技术,种类繁多。
由于原理的不同,决定了它们性能特点的差别。
3.ADC0809芯片工作介绍
ADC0809(如图4-4所示)是采样分辨率为8位的、以逐次逼近原理进行模/数转换的器件。
其内部有一个8通道多路开关,它可以根据地址码锁存译码后的信号,只选通8路模拟输入信号中的一个进行A/D转换。
图4-4
主要特性:
1).8路输入通道,8位A/D转换器,即分辨率为8位。
2).具有转换起停控制端。
3).转换时间为100μs
4).单个+5V电源供电
5).模拟输入电压范围0~+5V,不需零点和满刻度校准。
6).工作温度范围为-40~+85摄氏度
7).低功耗,约15mW。
ADC0809结构:
ADC0809是CMOS单片型逐次逼近式A/D转换器,内部结构如图4-5所示:
图4-5
ADC0809芯片有28条引脚,采用双列直插式封装,如图4-6所示。
图4-6
下面对各引脚功能进行介绍:
(如图4-7所示)
IN0~IN7:
8路模拟量输入端。
2-1~2-8:
8位数字量输出端。
ADDA、ADDB、ADDC:
3位地址输入线,用于选通8路模拟输入中的一路
图4-7
ALE:
地址锁存允许信号,输入,高电平有效。
START:
A/D转换启动脉冲输入端,输入一个正脉冲(至少100ns宽)使其启动(脉冲上升沿使0809复位,下降沿启动A/D转换)。
EOC:
A/D转换结束信号,输出,当A/D转换结束时,此端输出一个高电平(转换期间一直为低电平)。
OE:
数据输出允许信号,输入,高电平有效。
当A/D转换结束时,此端输入一个高电平,才能打开输出三态门,输出数字量。
CLK:
时钟脉冲输入端。
要求时钟频率不高于640KHZ。
REF(+)、REF(-):
基准电压。
Vcc:
电源,单一+5V。
GND:
地。
ADC0809的工作过程:
首先输入3位地址,并使ALE=1,将地址存入地址锁存器中。
此地址经译码选通8路模拟输入之一到比较器。
START上升沿将逐次逼近寄存器复位。
下降沿启动A/D转换,之后EOC输出信号变低,指示转换正在进行。
直到A/D转换完成,EOC变为高电平,指示A/D转换结束,结果数据已存入锁存器,这个信号可用作中断申请。
当OE输入高电平时,输出三态门打开,转换结果的数字量输出到数据总线上。
(如图4-8所示)
图4-8ADC0809工作时序图
【软件设计】
1.编程思路
硬件连接,AD0809的D0-D7是转换数据的输出端,所以直接接到单片机的P0口,这里需要注意,数据输出端尽可能不要接到其他I/O口,因为AD0809是用51单片机总线的方式驱动的,而51单片机的数据总线是P0口,所以要接到P0口。
AD0809的EOC是读忙标志位,当AD0809在转换期间,这个引脚是低电平,当转换结束时,会输出一个高电平,此端口接到单片机的P3.3口,就可以通过扫描单片机P3.3口是否有高电平,从而知道数据是否转换完毕。
P3.6,P3.7是单片机读写外部存储器要用的。
P2.7接到CS端,当单片机要用到AD0809时,会向地址总线写入AD0809的地址,可以看出如果CS接到P2.7端口,那么AD0809对应的地址则是0x7ff8,因为单片机的地址总线是P0口和P2口,把CS接到P2.7对应的编码就是0111111111111000,可能就有人疑问了,为什么最后的三位是零,因为AD0809芯片的ABC通道选择端接在了P0.0-P0.2端口上,我们只用芯片其中一个端口,为了接线方便就直接全部短接,然后接地了。
AD0809内部没有晶振,所以要外接晶振,时钟源的输出端OUT,接到CLK就是这个原因。
电位器输出端OUT接到AD0809的输入端通道0,AD0809有8个转换通道,但是每次只能开启一个输入端,因为只需要转换一个模拟量,所以只需要一路通道就行了。
编程开始用XBYTE的意思是定义外部地址,因而要使用absacc.h这个头文件,AD0809芯片的地址这里是0x7ff8。
在AD0809的子程序中,先定义了一个指针变量,然后这个指针变量指向ad0ad这个变量,而这个变量正是AD0809芯片所在的地址。
再接下来就是启动转换,转换完毕后,指针变量会将它里面的转换完毕的值传给canser这个全局变量,然后进行分离显示。
流程图如图4-9所示。
图4-9
2.参考程序
#include
#include//要使用XBYTE所以才包含这个头文件
#defineuintunsignedint
#defineucharunsignedchar//宏定义
#definead0adXBYTE【0x7ff8】//定义芯片外部存储器的地址为0x7ff8
/*端口定义*/
sbitad_busy=P3^3;//AD0809的读忙标志位
sbitCS1=P3^0;
sbitCS2=P3^1;
sbitCSWR=P3^2;
ucharled_table【】={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//数组
uchard1,d2,d3,d4;
uintcanser;
/*延迟子程序*/
voiddelay_1ms(uintx)
{
uinti,j;
for(i=x;i>0;i--)
{
for(j=110;j>0;j--);
}
}
/*数码管显示程序*/
voidshuma_display()
{
CS1=1;
CS2=1;
CSWR=0;
P1=led_table【d1】;
CS1=0;
CSWR=1;
CS1=1;
CSWR=0;
P1=0x7f;
CS2=0;
CSWR=1;
CS2=1;
CSWR=0;
delay_1ms
(2);
P1=led_table【d2】;
CS1=0;
CSWR=1;
CS1=1;
CSWR=0;
P1=0xbf;
CS2=0;
CSWR=1;
CS2=1;
CSWR=0;
delay_1ms
(2);
P1=led_table【d3】;
CS1=0;
CSWR=1;
CS1=1;
CSWR=0;
P1=0xdf;
CS2=0;
CSWR=1;
CS2=1;
CSWR=0;
delay_1ms
(2);
P1=led_table【d4】;
CS1=0;
CSWR=1;
CS1=1;
CSWR=0;
P1=0xef;
CS2=0;
CSWR=1;
CS2=1;
CSWR=0;
delay_1ms
(2);
}
/AD转换子程序*/
voidad0809(void)
{
ucharxdata*ad_adr;//定义指针变量
ad_adr=&ad0ad;//引用指针,使指针指向AD0809的存储器
*ad_adr=0;//启动AD0809转换
while(ad_busy==0);//等待转换完毕
canser=*ad_adr;//将转换完毕的数据传给canser这个变量
}
/*对数据进行分离*/
voidmake_canser()
{
d1=canser/1000;
d2=canser%1000/100;
d3=canser%1000%100/10;
d4=canser%1000%100%10;
}
/*主程序*/
voidmain()
{
while
(1)//无限循环
{
shuma_display();//调用数码管显示程序
ad0809();//调用AD0809驱动程序
make_canser();//分离数据子程序
}
}
【知识链接二】
1.指针的概念及初步应用
指针是C语言中的一个重要概念,也是C语言的一个重要角色。
利用指针变量可以表示各种数据结构,能很方便地使用数组和字符串,并能象汇编语言一样处理内存地址,从而编出精练而高效的程序。
指针极大地丰富了C语言的功能。
学习指针是学习C语言中最重要的一环,能否正确理解和使用指针是我们是否掌握C语言的一个标志。
同时,指针也是C语言中最为困难的一部分,在学习中除了要正确理解基本概念,还必须要多编程,上机调试。
只要作到这些,指针也是不难掌握的。
在计算机中,所有的数据都是存放在存储器中的。
一般把存储器中的一个字节称为一个内存单元,不同的数据类型所占用的内存单元数不等,如整型量占2个单元,字符量占1个单元等。
为了正确地访问这些内存单元,必须为每个内存单元编上号。
根据一个内存单元的编号即可准确地找到该内存单元。
内存单元的编号也叫做地址。
既然根据内存单元的编号或地址就可以找到所需的内存单元,所以通常也把这个地址称为指针。
内存单元的指针和内存单元的内容是两个不同的概念。
可以用一个通俗的例子来说明它们之间的关系。
我们到银行去存取款时,银行工作人员将根据我们的帐号去找我们的存款单,找到之后在存单上写入存款、取款的金额。
在这里,帐号就是存单的指针,存款数是存单的内容。
对于一个内存单元来说,单元的地址即为指针,其中存放的数据才是该单元的内容。
在C语言中,允许用一个变量来存放指针,这种变量称为指针变量。
因此,一个指针变量的值就是某个内存单元的地址或称为某内存单元的指针。
严格地说,一个指针是一个地址,是一个常量。
而一个指针变量却可以被赋予不同的指针值,是变量。
但在常把指针变量简称为指针。
为了避免混淆,我们中约定:
“指针”是指地址,是常量,“指针变量”是指取值为地址的变量。
定义指针的目的是为了通过指针去访问内存单元。
既然指针变量的值是一个地址,那么这个地址不仅可以是变量的地址,也可以是其它数据结构的地址。
在一个指针变量中存放一个数组或一个函数的首地址有何意义呢?
因为数组或函数都是连续存放的。
通过访问指针变量取得了数组或函数的首地址,也就找到了该数组或函数。
这样一来,凡是出现数组,函数的地方都可以用一个指针变量来表示,只要该指针变量中赋予数组或函数的首地址即可。
这样做,将会使程序的概念十分清楚,程序本身也精练,高效。
在C语言中,一种数据类型或数据结构往往都占有一组连续的内存单元。
用“地址”这个概念并不能很好地描述一种数据类型或数据结构,而“指针”虽然实际上也是一个地址,但它却是一个数据结构的首地址,它是“指向”一个数据结构的,因而概念更为清楚,表示更为明确。
这也是引入“指针”概念的一个重要原因。
指针变量的定义:
C语言规定所有变量在使用前必须通过定义来指定其类型,并按此分配内存单元。
指针变量不同与整形变量和其他类型变量,它是用来存放地址的,必须将其定义为指针类型。
其格式如下:
类型说明符*变量名
例如:
char*d1;
int*a1;
其中,*表示一个指针变量,变量名即为定义指针的变量名,类型说明符表示本指针变量所指的对象的数据类型。
给指针变量赋值有两种方法,例如:
inta,*p=&a;
或者
inta,*p;
p=&a;
用第二种方法,被赋值的指针变量前不能再加*说明符,如写为*p=&a;是错误的写法。
事实上,若定义了变量以及指向该变量的指针为
inta,*p;
若有“p=&a”则称p指向变量a,或者说p具有了变量a的地址。
以后在处理程序中,凡是可以写&a的地方,就可以替换成指针的表示p,a也可以替换成*p。
【调试与结果演示】(如图4-10所示)
图4-10显示的电压值,电压约为2.45V
【项目总结】
1.AD0809可以将0-5V模拟电压转换为对应的0-255个数值,也就是将0-5V等分255分,如0V电压对应就是显示0,但是5V电压对应就是显示255,而2.5V电压则对应显示127左右。
2.AD0809芯片的ABC引脚在本实验中是全部接地的,但是如果其他实验要用到2个或两个以上的转换通道,则需要接到P.0.-P0.2I/O口上,使用软件切换通道。
【参考评分标准】(见表4-2)
表4-2参考评分标准
评分项目
配分
配分细则
主要参数评分
60
1.数码管为四位显示,能够准确显示电位器现在所输出的电压,数码管显示清晰,60分。
2.数码管为四位显示,显示的的数值不能够实时更新,数码管显示清晰,40分。
3.数码管为四位显示,显示的数值与实际误差非常大,数码管显示清晰,30分。
4.数码管不能够显示,0分。
连线及工艺评分
20
1.电源,地线全部连接正确,5分。
2.AD0809控制线连接正确,15分。
3.数码管控制线连接正确,10分。
模块接线图评分
10
1.电源,地线全部连接正确,1分。
2.AD0809控制线连接正确,3分。
3.数码管控制线连接正确,1分。
4.画面整洁得5分,基本整洁得2分,看不清0分。
职业安全意识评分
10
同前
项目二D/A转换
【项目任务】
使用单片机输出0-255个数值,经过DAC0832转换芯片以后,使用电平指示灯将对应的输出电压显示出来。
【任务分析】
DAC0832是一个数模转换芯片,能够将0-255个数值转换成对应的电压并输出,实际上DA转换就是AD转换的逆过程,AD转换就将模拟量转换成数字量,而DA转换则相反,就是将数字量转换成模拟量输出。
任务要求是单片机输出数字量,经过DA转换后,用电平指示灯显示出来,就要考虑芯片的驱动问题,DAC0832芯片驱动很简单,只需要将其中两个引脚拉低,芯片就可以转换了。
【硬件选择】
电源模块、主机模块、ADC/DAC模块。
【接线及原理图】
1.接线表(见表4-3)
表4-3
DAC0832的WR,CS
GND
DAC0832的OUT
电平指示IN
P0.0-P0.7
DAC0832的D0-D7
电源+12V,-12V
DAC0832的+12V,-12V
电源+5V,GND
所有模块+5V,GND
12V直流电源GND
5V直流电源GND
2.原理图(如图4-11所示)
图4-11DA转换原理图
【知识链接】
1.D/A转换
D/A(数/模)转换器输入的是数字量,经转换后输出的是模拟量,为单片机在模拟环境中的应用提供了一种数据转换接口。
为把数字量转换为模拟量,在D/A转换芯片中要有解码网络,常用的主要为二进制全电阻解码网络和T型电阻解码网络。
转换过程是先将各位数码按其权的大小转换为相应的模拟分量,然后再以叠加方法把各模拟分量相加,其和就是D/A转换的结果。
对于D/A转换器的使用要注意区分输出形式和锁存器的存在。
1).电压与电流输出形式
D/A转换器有两种输出形式,一种是电压输出形式,即输入是二进制数或BCD码的数字量,而输出为电压。
另一种是电流输出形式,即输出为电流。
在实际应用中如需要电压模拟量的话,对于电流输出的D/A转换器,可在其输出端加运算放大器,通过运算放大器构成电流-电压转换电路,将转换器的电流输出变为电压输出。
2).带与不带锁存器的D/A转换器
由于实现模拟量转换时需要一定时间的,在这段时间内D/A转换器的输入端的数字量应保持稳定,为此应当在数模转换器数字量输入端的前面设置锁存器,以提供数据锁存功能。
根据转换器芯片内是否有锁存器,可以把D/A分为内部无锁存器和内部有锁存器两类。
D/A转换器的技术性能指标很多,如绝对精度、相对精度、线性度、输出电压范围、温度系数等等。
2.DAC0832芯片简介
DAC0832是一个8位D/A转换芯片,但电源供电,从+5V-+15V均可以正常工作,基准电压范围为±10V,电流建立时间为1us,CMOS工艺,低功耗20mw,芯片为20引脚,双列直插式封装。
其引脚排列如图4-12所示:
图4-12
DI7-DI0:
转换数据输入。
CS:
片选信号,低电平有效。
ILE:
数据锁存允许信号(输入),高电平有效。
WR:
第1写信号(输入)低电平有效,该信号与ILE信号共同控制数据是直通方式还是数据锁存方式。
当ILE=1和WR=0,为输入寄存器直通式;当ILE=1和WR=1,为输入寄存器锁存方式。
XFER:
数据传送控制信号,低电平有效。
WR2:
第2写信号(输入),低电平有效。
Iout1:
电流输出“1”。
Iout2:
电流输出“2”。
Rfb:
反馈电阻。
Verf:
基准电压,是外加高精度电压源,与芯片内的电阻网络相连,该电压可正可负,范围为10V-+10V。
DGND:
数字地。
AGND:
模拟地。
3.LM358运算放大器介绍
LM358内部包括有两个独立的、高增益、内部频率补偿的双运算放大器,适合于电源电压范围很宽的单电源使用,也适用于双电源工作模式,在推荐的工作条件下,电源电流与电源电压无关。
它的使用范围包括传感放大器、直流增益模块和其他所有可用单电源供电的使用运算放大器的场合。
(如图4-13所示)
图4-13LM358芯片
LM358的封装形式有塑封8引线双列直插式和贴片式。
(如图4-14所示)
图4-14
1).内部频率补偿
2).直流电压增益高(约100dB)
3).单位增益频带宽(约1MHz)
4).电源电压范围宽:
单电源(3—30V);双电源(±1.5一±15V)
5).低功耗电流,适合于电池供电
6).低输入偏流
7).低输入失调电压和失调电流
8).共模输入电压范围宽,包括接地
9).差模输入电压范围宽,等于电源电压范围
10).输出电压摆幅大(0至Vcc-1.5V)
【软件设计】
1.编程思路
由于这个程序不需要加其他硬件,只需要使用DA转换就行了,所以将
DAC0832芯片的WR和CS端直接接地,然后单片机轮流向芯片输出0-255,由于芯片现在控制端直接接地,输出的数据就会被直接转换并且输出。
(如图4-15所示)
图4-15转换芯片操作时序图
2.参考程序
#include
#defineuintunsignedint
#defineucharunsignedchar
/*延时子程序*/
voiddelay_1ms(uintx)
{
uinti,j;
for(i=x;i>0;i--)
{
for(j=110;j>0;j--);
}
}
/*主程序*/
voidmain()
{
uchari;
while
(1)
{
P0=i;
i++;
delay_1ms(50);
if(i>=255)
{
i=0;
}
}
}
【知识链接二】
1.变量赋初值
在写程序的时候,经常要对一些变量赋个初始值。
C语言允许在定义变量的同时可以对变量进行初始化。
inta=4;//指定a为整型变量,初始值为4。
也可以对几个变量其中一部分赋值,例如:
chard1,d2,d3,d4=4;//指定d1,d2,d3,d4为字符型变量,并对d4赋值4。
如果要对几个变量同时赋值,也可以这么写,例如:
chard1=1,d2=2,d3=3;//定义d1,d2,d3为char型变量,并且对其赋值分别为1、2、3。
要注意的是,变量的初始值不是在编译阶段完成的,而是在程序运行到执行本函数的时候赋的初始值。
【调试与结果演示】(如图4-16所示)
图4-16电平指示灯正在显示此时电平的高低
【项目总结】
1.转换芯片的WR和CS端口在本实验中被直接接地拉低