第7章AD转换.docx
《第7章AD转换.docx》由会员分享,可在线阅读,更多相关《第7章AD转换.docx(53页珍藏版)》请在冰豆网上搜索。
第7章AD转换
第7章AD转换
7.1概述
7.1.1AD转换器
AD转换器即ADC(AnalogtoDigitalConverter),是能将模拟量转换为数字量的器件。
单片机能直接处理和控制的是数字量,对于模拟量,则可通过AD转换器件将其先转换为数字量,然后再交付单片机去做进一步处理。
在AD转换器件将模拟量转换为数字量的过程中,有许多参数值得我们关注,其中最重要的两个参数是转换时间和转换分辨率。
目前,常见AD转换器与微处理器间的数据接口有并行和串行之分,AD转换器的转换精度有8位、10位、12位等多种类型。
此处选取并行8位AD转换器ADC0809,并行12位AD转换器AD574,串行8位AD转换器ADC0832,串行12位AD转换器TLC2543,共四种AD转换器件,分别说明其特点和使用方法。
7.1.2AD转换分辨率
AD转换中,用转换分辨率来表示AD转换器对输入模拟信号的分辨能力,常用转换结果的二进制数的位数来表示,8位精度代表转换结果用8位二进制数表示,12位精度代表转换结果用12位二进制数表示。
以下通过两个例子具体解释其内在含义。
例1:
假设被转换的模拟量是电压信号,被测电压值在0V~5V的固定区间内连续可调,AD转换器分辨率假设是8位。
我们已经熟知,8位无符号二进制数的数值范围是十进制的0~255,共256个数。
如果AD转换器分辨率是8位,则从理论上说,被测电压范围5V(5V-0V=5V)被平均等分为256等份,每一份是5V/256=0.01953125V≈0.02V=20mV,这每一份的含义是:
电压每增大20mV,AD转换结果的数值就增加1;0V电压对应的转换结果应该是最小值0,而5V电压对应的转换结果应该是最大值255,2.5V电压对应的转换结果应该是0~255的中间值128,其它电压依次成比例对应某一数值。
例2:
假设被转换的模拟量是电压信号,被测电压值在0V~5V的固定区间内连续可调,AD转换器分辨率假设是12位。
显然,12位无符号二进制数的数值范围是十进制的0~4095,共4096个数。
当AD转换分辨率是12位时,5V电压范围被平均等分为4096等份,每一份是5V/4096=0.001220703125V≈0.0012V=1.2mV,即电压每增大1.2mV,AD转换结果的数值就增加1;0V电压对应转换结果依然是最小值0,5V电压对应的转换结果是最大值4095,2.5V被测电压对应的转换结果应该是0~4095的中间值2048,其它电压依次成比例对应某一数值。
从以上两个例子可以看出,转换分辨率越高,被测模拟量范围被平均等分的份数就越多,每一份代表的模拟量值就越小,转换分辨率就越高。
实际工作中,一般以系统所用数据总线的位数、系统测量的精度等作为选择AD转换分辨率的依据。
AD转换中,转换分辨率与转换精度密切相关但不完全相同,在不严格区分的条件下,可以认为它们是等同的。
7.1.3AD转换时间
AD转换时间,即完成一次AD转换所用的时间,是指从发出转换开始指令,到数据输出端得到稳定的数字量所经历的时间。
若被测模拟信号变化较快,而AD转换时间较长,则模拟信号的很多中间变化细节可能被遗漏,造成转换结果信息的不完整和疏漏。
实际工作中,AD转换时间是选用AD转换芯片时的一个重要参数指标。
本单元介绍的ADC0809的转换时间是100μs,AD574的转换时间不超过35μs(典型值20μs),串行口8位AD转换器ADC0832的转换时间是32μs,串行口12位AD转换器TLC2543的转换时间是10μs。
7.2ADC0809
7.2.1ADC0809介绍
ADC0809是8位AD转换芯片,有8路模拟信号输入通道,转换时间100μs。
其实物图如图7-1所示,图7-2是其PDIP封装管脚图。
表7-1列出了各引脚定义及功能描述。
图7-1ADC0809实物图图7-2ADC0809的PDIP封装管脚图
表7-1ADC0809引脚定义
引脚
序号
引脚
名称
功能描述
引脚
序号
引脚
名称
功能描述
1
IN3
模拟通道3输入端
15
D2(2-6)
输出数据第2位
2
IN4
模拟通道4输入端
16
VREF(-)
参考电压负极端
3
IN5
模拟通道5输入端
17
D0(2-8)
输出数据第0位(最低位)
4
IN6
模拟通道6输入端
18
D4(2-4)
输出数据第4位
5
IN7
模拟通道7输入端
19
D5(2-3)
输出数据第5位
6
START
转换启动信号输入端
20
D6(2-2)
输出数据第6位
7
EOC
转换结束信号输出端
21
D7(2-1)
输出数据第7位(最高位)
8
D3(2-5)
输出数据第3位
22
ALE
地址锁存允许信号
9
OE
输出允许信号端
23
ADDC
通道地址线C
10
CLOCK
外部时钟脉冲信号输入端
24
ADDB
通道地址线B
11
Vcc
电源端
25
ADDA
通道地址线A
12
VREF(+)
参考电压正极端
26
IN0
模拟通道0输入端
13
GND
接地端
27
IN1
模拟通道1输入端
14
D1(2-7)
输出数据第1位
28
IN2
模拟通道2输入端
ADC0809管脚简介如下:
◆引脚26~28,1~5——IN0~IN7,8路模拟通道输入端;具体转换哪一路模拟信号,要与引脚23~25通道地址线配合选定;
◆引脚6——START,转换启动信号输入端;
◆引脚7——EOC,转换结束信号输出端;EOC引脚在每一次转换期间均保持低电平,当转换结束时,EOC电平拉高。
故可以通过查询EOC引脚是否为高电平,来判断本次转换是否结束;也可将此信号作为中断源信号(需加反向器)去触发中断;
◆引脚21,20,19,18,8,15,14,17——输出数据7~0位引脚;转换结果是1个字节的数字量数据,最高位(第7位)是21引脚,最低位(第0位)是17引脚;
◆引脚9——OE,输出允许信号端(OUTPUTENABLE);当一次转换结束后,只有在OE端是高电平期间,转换结果才输出到输出数据引脚,这时单片机才能读取转换结果;
◆引脚10——CLOCK,外部时钟脉冲信号输入端;ADC0809转换时,外部时钟信号的频率最小10KHz,最大1280KHz,典型值是640KHz,一般选用500KHz。
使用1000KHz(1MHz)亦可。
实际中具体做法是:
51单片机的第30引脚(ALE)对外输出单片机外接晶振的6分频脉冲信号,如51单片机外接晶振12MHz时,ALE输出12MHz/6=2MHz的脉冲信号,此脉冲信号经D触发器二分频以后,可得1MHz脉冲信号,可以作为AD转换的时钟脉冲信号;也可以在得到1MHz脉冲信号后再次二分频,得到500KHz的脉冲信号。
实现二分频的元器件可以选用D触发器74HC74芯片,具体硬件电路参见本节后续实例部分。
◆引脚11——Vcc,电源端;接5V电源;
◆引脚12——VREF(+),参考电压正极端,一般接5V;
◆引脚13——GND,接地端;
◆引脚16——VREF(-),参考电压负极端,一般接地;
◆引脚22——ALE,地址锁存允许信号;一般与引脚6(START)并接在一起使用,可以参看本节后面的时序图(图7-3)。
◆引脚23~25——ADDC、ADDB、ADDA,通道地址线;三根引脚线上电平的组合,分别对应8路输入模拟信号,具体对应关系如表7-2所示;
表7-2通道地址与所选通道之间的关系
通道地址
所选模拟量通道
ADDC
ADDB
ADDA
0
0
0
IN0
0
0
1
IN1
0
1
0
IN2
0
1
1
IN3
1
0
0
IN4
1
0
1
IN5
1
1
0
IN6
1
1
1
IN7
7.2.2ADC0809应用实例1
功能要求:
使用ADC0809芯片,实现AD转换,并将转换结果在0802LCD上显示。
硬件说明:
1、硬件连接图如图7-4所示。
本例将ADC0809的通道地址线ADDC、ADDB、ADDA全部接地(全部低电平),即选取0通道作为模拟信号的输入通道;
2、调节ADC0809的12和16引脚间的可调电位器R4(10KΩ,即103),使其输出电压在0~5V之间变化,将此电压作为被测模拟信号(实际中可能来自别处),并连接到模拟通道0;3、51单片机的30引脚输出的2MHz脉冲信号,经74HC74两次二分频之后,输出500KHz脉冲信号,再输入到ADC0809的第10引脚CLK,作为外部时钟脉冲信号;
软件说明:
1、本例依照ADC0809时序,如图7-3所示,可以看到,START与ALE几乎同步且变化一致,故在硬件中将它们并接,保留名称START;
2、本例采用查询方式,在启动AD转换后,查询EOC是否为1(如若是0,说明转换未完成,则继续等待),当EOC为1以后,将输出允许信号端OE拉高,允许转换结果输出,此时将转换结果从P0口读入,之后再将OE拉低;
3、将转换结果送入0802LCD显示。
图7-3ADC0809时序图
图7-4ADC0809实例1硬件连接图
程序清单如下:
#include
#defineucharunsignedchar
sbitRS=P3^3;
sbitRW=P3^4;
sbitE=P3^5;
sbitSTART=P2^0;
sbitOE=P2^1;
sbitEOC=P2^2;
voidwrcmd(ucharcmd)
{
ucharm;
RW=0;
RS=0;
P1=cmd;
for(m=0;m<=2;m++);
E=1;
for(m=0;m<=2;m++);
E=0;
}
voidwrdata(ucharshuju)
{
ucharm;
RW=0;
RS=1;
P1=shuju;
for(m=0;m<=2;m++);
E=1;
for(m=0;m<=2;m++);
E=0;
}
voidinit0802(void)
{
RW=0;
E=0;
wrcmd(0x38);
wrcmd(0x0c);
wrcmd(0x06);
wrcmd(0x01);
}
voiddisp0802(ucharx,uchary,ucharch)
{
ucharm;
wrcmd(0x80+x*0x40+y);
for(m=0;m<=252;m++);
wrdata(ch);
}
/*********************************/
main()
{
ucharad;
init0802();
while
(1)
{
START=0;START=1;START=0;
while(EOC==0);
OE=1;ad=P0;OE=0;
disp0802(0,0,ad/100+'0');
disp0802(0,1,ad/10%10+'0');
disp0802(0,2,ad%10+'0');
}
}
7.2.3ADC0809应用实例2
功能要求:
使用ADC0809芯片,实现AD转换,并将转换结果在0802液晶屏上显示。
硬件说明:
1、本例使用总线接法。
将ADC0809的通道地址线ADDC、ADDB、ADDA分别连接到74HC573锁存器的输出端Q2、Q1和Q0端;在P2口只使用P2.7引脚时(P2.7为低电平0),P2口和P0口组合的地址范围是二进制的0111111111111000到0111111111111111,对应的十六进制地址范围是0x7FF8~0x7FFF,恰好依次对应通道0~通道7,共计8个模拟通道;74HC573的锁存使能引脚LE(引脚11),连接到51单片机的30引脚ALE;
2、调节接在ADC0809的12和16引脚间的可调电位器R4(10KΩ,即103),使其输出电压在0~5V之间变化,将此电压作为被测模拟信号(实际中可能来自别处),连接到模拟通道0~7,并通过软件来具体选择使用哪个通道进行AD转换;
3、ADC0809第10引脚CLK是外部时钟脉冲信号,将51单片机30引脚输出的2MHz脉冲信号(外接晶振12MHz),通过74HC74经两次二分频之后,输出500KHz脉冲信号;
4、芯片74HC02是4组两输入或非门,本例仅使用了4组中的2组,其余2组空闲未用。
51单片机P2.7与P3.6引脚信号,作为两输入或非门的输入(74HC02的A1,B1),输出(74HC02的Y1)连接到ADC0809的启动转换信号引脚START(START与旁边的ALE引脚并联)。
这样连接的理由是:
在P2.7恒为低电平的条件下,只要51单片机向ADC0809发出一次写操作指令(低电平持续时间很短的脉冲信号,且只有一次,不是连续的脉冲信号),无论写入的数据数值是多少,P3.6发出的低电平脉冲与P2.7的恒低电平,经或非运算后,恰好是一个正脉冲信号,与7-3图中ADC0809时序的START信号要求一致。
同理,P2.7与P3.7引脚信号,连接到74HC02的另一组或非门的两个输入端(74HC02的A2,B2),输出(74HC02的Y2)连接到ADC0809的输出允许信号端OE。
51单片机从ADC0809读取数据时,必定发出一次读操作指令(低电平持续时间很短的脉冲信号,且只有一次,不是连续的脉冲信号),P3.7发出的低电平脉冲与P2.7的恒低电平,经或非运算后,是一个正脉冲信号,此时刚好读取转换结果(参见7-3图中ADC0809时序的OE信号要求)。
5、本例依旧采用硬件查询方式,来判断一次AD转换是否结束,硬件连接中使用单片机的P3.2引脚查询。
如果要使用中断方式,则可以将74HC02的A3、B3短接后,连接至ADC的EOC,而74HC02的Y3连接到单片机51的P3.2引脚(低电平有效),作为外部中断源使用。
6、硬件连接图如图7-5所示。
软件说明:
1、本例中宏定义#defineINXBYTE[0x7ff8]是定义51单片机的片外并行接口,0x7FF8是模拟通道0的地址,0x7FF9是模拟通道1的地址……,0x7FFF是模拟通道7的地址。
2、主函数中*ad0809=0;语句是向ADC0809写数据0(写其它数据也可以,只要是写操作就可以),功能是启动转换;ad=*ad0809;语句是从ADC0809读取转换结果;这几条语句涉及C语言的指针概念,以下给出较详细的说明;
3、主程序最后将转换结果送入0802LCD显示。
C语言知识:
指针
指针是C语言中的一个重要概念,也是C语言的重要特色之一。
使用指针可以使C语言程序变得紧凑、高效、简洁。
具体编程中,使用指针可以使处理直接深入到内存地址单元这一底层硬件层面;对于数组、字符串等复杂数据结构,指针更有其独特的使用效果。
1、地址
谈及指针就不能不提地址,而且,地址的概念也频繁出现在单片机、DSP、ARM等类计算机软硬件知识和实际应用中,那么,地址究竟指什么呢?
简言之,地址就是计算机存储器单元的编号。
计算机的存储器是用来存放计算机程序和数据的电子元器件。
为了有效管理存放在存储器内的程序和数据,一般以字节为单位,将存储器空间划分为若干数量的存储单元,并且为每一个存储单元编号──就像给大楼里的每个房间编号一样,每一个存储单元的编号就是该存储单元的地址。
一般使用0和正整数编号,并且从0开始。
第一个字节编号为0,则第一个字节单元的地址就是0;第二个字节编号为1,则第二个字节单元的地址就是1,……,依次类推,直至将整个存储器空间的每一个字节都编上号。
这时,存储器空间的每一个字节都有了自己独一无二的地址,通过这个地址,就可以方便地访问(读或者写操作)这个存储单元了。
需要特别说明的是,在实际应用中,地址一般以十六进制数表示,所以我们经常看到的地址都以0xXXXX或者XXXXH的形式出现(0x和H常用于表示十六进制数)。
2、指针
就本质而言,指针就是地址。
以下以变量为对象,具体说明指针的概念。
(1)变量及其地址
对于变量,前已述及,变量有类型之分、有名称之别、其值可以变化。
当声明或定义一个变量之后,计算机就为该变量分配一片连续的存储空间(几个字节),用于存放该变量的值,这一片连续存储空间的首地址就是该变量的地址。
例如语句inta=32;声明了一个名字为a的整型变量,并赋初值为十进制数32。
此时,计算机就分配2个字节的存储空间给变量a,用于存放变量a的值32。
假设这2个字节的地址编号是十六进制数0x1000和0x1001,则地址编号0x1000就是变量a的地址。
(2)指针
通过变量名获取变量值,是变量的基本使用方法,除此方法以外,还可以通过对变量地址的访问,获取变量的值。
要访问变量的地址就涉及到了指针。
①指针变量
指针变量是用来存储地址值的变量。
对此变量,可从以下几点理解和掌握:
首先,指针变量是变量,与一般的变量,如整型变量、字符型变量等都类似,也有类型之分、名称之别、其值可变等特点或属性;其次,指针变量与一般变量又不同,有其特殊的一面,这就是:
指针变量的值只能是地址,即,它只能存储存储器单元的编号。
②指针变量的定义
指针变量的定义与一般变量的定义类似,仅在变量名前多了一个星型符号*(即乘号)。
指针变量定义的一般形式为:
类型名*指针变量名;
例如:
int*pa;声明了一个名字为pa,类型是整型的指针变量,但没有赋初值。
③指针变量的指向
指针变量的指向,是指指针变量存储地址的过程。
指针变量存储了谁的地址,我们就称该指针变量指向了谁。
指针变量的指向过程,是通过将地址值赋值给指针变量来实现的。
例如:
inta=32;
int*pa;
pa=&a;
这三条语句中,第一句是整型变量a的声明;第二句是整型指针变量pa的声明;第三句是指向。
pa=&a;中的&是获取地址,简称取地址,&a就是获取变量a的地址,而本条语句是一条赋值语句,是将变量a的地址赋值给指针变量pa,此时我们就称指针变量pa指向变量a,言下之意,指针变量pa的值是变量a的地址。
下面来解释一下指针变量的类型。
如上述三条语句的第二句:
int*pa;其中的类型关键字int,是该指针变量pa的类型,那么,此处的int意义何为呢?
其实,指针变量的类型是该指针变量指向对象的类型。
还是以以上三条语句为例,由于变量a是整型,而pa指向了a,所以指针变量pa的类型就是pa指向的对象(变量a)的类型,即整型。
因此,指针变量的类型,应和它指向的对象类型匹配一致。
④指针变量的引用
指针变量的引用,其实就是使用,称为“引用”的原因是,在获取变量值的过程中,总是间接(而非直接)地引用指针。
对比以下左右两个相似的程序段,分析其功能,借此说明指针变量的引用。
inta=32,b=5,c;inta=32,b=5,c;
c=a+b;int*pa;
pa=&a;
c=*pa+b;
左边的程序段简单明了,就是求解变量a和变量b的和,并将和赋值给变量c,变量c的值为37。
右边的程序段中,前面三句功能比较清楚:
定义了三个整型变量a,b,c,变量a和b有初始值32和5,变量c没有赋初值;定义整型指针变量pa;指针变量pa指向变量a。
关键是第四条语句:
c=*pa+b;这是一条先求和再赋值的赋值语句,求和的一个加数是变量b,另一个是*pa。
此处的*pa不再是指针变量的定义,而是指针变量的引用,需要特别说明的是:
语句c=*pa+b;中的星号*,既不是乘号,也不是指针定义中出现的星号,而是指针运算符,即取该指针指向的内容。
所以,语句c=*pa+b;中的*pa是获取指针变量pa指向的内容,即pa指向的对象(变量a)的值32,或pa指向的内容(变量a的地址中的值,即变量a的值)。
所以,语句c=*pa+b;与语句c=a+b;完全等效,两个程序段的执行结果相同,变量c的值都是37。
图7-5ADC0809实例2硬件连接图
程序清单如下:
#include
#include
#defineucharunsignedchar
#defineINXBYTE[0x7ff8]
sbitRS=P3^3;
sbitRW=P3^4;
sbitE=P3^5;
sbitEOC=P3^2;
//*************************
voidwrcmd(ucharcmd)
{
ucharm;
RW=0;
RS=0;
P1=cmd;
for(m=0;m<=2;m++);
E=1;
for(m=0;m<=2;m++);
E=0;
}
voidwrdata(ucharshuju)
{
ucharm;
RW=0;
RS=1;
P1=shuju;
for(m=0;m<=2;m++);
E=1;
for(m=0;m<=2;m++);
E=0;
}
voidinit0802(void)
{
RW=0;
E=0;
wrcmd(0x38);
wrcmd(0x0c);
wrcmd(0x06);
wrcmd(0x01);
}
voiddisp0802(ucharx,uchary,ucharch)
{
ucharm;
wrcmd(0x80+x*0x40+y);
for(m=0;m<=252;m++);
wrdata(ch);
}
/*************************************************/
main()
{
ucharad;
uchar*ad0809;//定义无符号字符型指针变量ad0809
init0802();
ad0809=&IN;//指针变量ad0809指向片外数据存储器区地址为0x7ff8的存储单元
while
(1)
{
*ad0809=0;//将数据0写入存储单元0x7ff8
while(EOC==0);
ad=*ad0809;//从存储单元0x7ff8中读取数据并赋值给变量ad
disp0802(0,0,ad/100+'0');
disp0802(0,1,ad/10%10+'0');
disp0802(0,2,ad%10+'0');
}
}
注1:
若使用中断方式时,可将74HC02的A3和B3短接,再连接到ADC0809的EOC引脚,而74HC02的Y3引脚连接到51单片机的P3.2INT0引脚。
程序清单如下:
#include
#include
#defineucharunsignedchar
#defineINXBYTE[0x7ff8]
ucharad=0,*ad0809=0;
sbitRS=P3^3;
sbitRW=P3^4;
sbitE=P3^5;
sbitEOC=P3^2;
//*************************
voidwrcmd(ucharcmd)
{
ucharm;
RW=0;