ADC0809模数转换器工作原理及编程

        项目中由于单片机开发板自带的ADC模块不够用,单片机自带的ADC模块是XPT2046,只有一个外部模拟输入信号通道,不能够满足我的需求,所以我打算采用ADC0809来作为模数转换芯片。

        ADC0809是美国国家半导体公司生产的CMOS工艺8通道,8位逐次逼近式A/D模数转换器。其内部有一个8通道多路开关,它可以根据地址码锁存译码后的信号,只选通8路模拟输入信号中的一个进行A/D转换。

特性:

1)8路输入通道,8位A/D转换器,即分辨率为8位。

2)具有转换起停控制端。

3)转换时间为100μs(时钟为640KHz时),130μs(时钟为500KHz时)。

4)单个+5V电源供电。

5)模拟输入电压范围0~+5V,不需零点和满刻度校准。

6)工作温度范围为-40~+85摄氏度。

7)低功耗,约15mW。

引脚及功能:

  • IN0~IN7:8路模拟量输入端。

  • 2-1~2-8:8位数字量输出端。

  • ADDA、ADDB、ADDC:3位地址输入线,用于选通8路模拟输入中的一路。

  • ALE:地址锁存允许信号,输入端,产生一个正脉冲以锁存地址。

  • START: A/D转换启动脉冲输入端,输入一个正脉冲(至少100ns宽)使其启动(脉冲上升沿使0809复位,下降沿启动A/D转换)。

  • EOC: A/D转换结束信号,输出端,当A/D转换结束时,此端输出一个高电平(转换期间一直为低电平)。

  • OE:数据输出允许信号,输入端,高电平有效。当A/D转换结束时,此端输入一个高电平,才能打开输出三态门,输出数字量。

  • CLK:时钟脉冲输入端。时钟频率范围为10KHz-1280KHz。

  • REF(+)、REF(-):基准电压。

  • Vcc:电源,单一+5V。

  • GND:地。

工作过程:

首先输入3位地址,并使ALE=1,将地址存入地址锁存器中。此地址经译码选通8路模拟输入之一到比较器。START上升沿将逐次逼近寄存器复位。下降沿启动 A/D转换,之后EOC输出信号变低,指示转换正在进行。直到A/D转换完成,EOC变为高电平,指示A/D转换结束,结果数据已存入锁存器,这个信号可用作中断申请。当OE输入高电平 时,输出三态门打开,转换结果的数字量输出到数据总线上。

转换数据的传送 A/D转换后得到的数据应及时传送给单片机进行处理。数据传送的关键问题是如何确认A/D转换的完成,因为只有确认完成后,才能进行传送。为此可采用下述三种方式。

(1)定时传送方式

对于一种A/D转换器来说,转换时间作为一项技术指标是已知的和固定的。例如ADC0809转换时间为128μs,相当于6MHz的MCS-51单片机共64个机器周期。可据此设计一个延时子程序,A/D转换启动后即调用此子程序,延迟时间一到,转换肯定已经完成了,接着就可进行数据传送。

(2)查询方式

A/D转换芯片有表明转换完成的状态信号,例如ADC0809的EOC端。因此可以用查询方式,测试EOC的状态,即可确认转换是否完成,并接着进行数据传送。

(3)中断方式

把表明转换完成的状态信号(EOC)作为中断请求信号,以中断方式进行数据传送。

不管使用上述哪种方式,只要一旦确定转换完成,即可通过指令进行数据传送。首先送出口地址并以信号有效时,OE信号即有效,把转换数据送上数据总线,供单片机接受。

                                  引脚                                                          通道的选择

编程(C语言)

#include "reg52.h"
float  shuju;
unsigned char sj;
unsigned int gata;
unsigned char gw,sw,bw;
unsigned char kk,tdao;

//4联共阳数码管,最高位显示通道号,其他三位为电压值
unsigned char code shuzi[]={
                            0xC0,0xF9,0xA4,0xB0,0x99,
                            0x92,0x82,0xF8,0x80,0x90};

unsigned char code duanxuan[]={0x0f,0x8f,0x4f,0xcf,0x2f,0xaf,0x6f,0xff};
sbit START=P3^1;  //ALE也连接P3.1
sbit OE=P3^3;
sbit EOC=P3^2;
sbit clock=P3^0;
void delay()
{
    unsigned char i;
   for(i=200;i>0;i--);
}

//timer init
void Timer()
{
 TMOD=0x21;
 
 TH0=0x3c;//20ms
 TL0=0xb0;

 TH1=0xff;//100khz
 TL1=0xfd;
 
}
void AD_zh()
{
 START=0;       //ADC0809的启动信号
  START=1;
  START=0;
 while(EOC==0);     //等待转换结束
 OE=1;              //输出转换数据
 sj=P1;             //P1口接收数据

 shuju=sj;//转换为浮点型
 shuju=(shuju/51.0)*100.00;//转换成百位数据;
 gata=shuju;//转换为整型
 bw=gata/100;//分离百位
 sw=(gata/10)%10;//分离十位
 gw=gata%10;//分离个位
}
//timer0/counter0 interrupt
void timer0(void) interrupt 1  //T0用于产生秒信号
{
 TH0=0x3c;
 TL0=0xb0;
 kk++;
  if(kk==20)
  {
  kk=0;
 tdao++;            //用于转换通道,测量各个通道数据
  if(tdao==8)
  {
   tdao=0;
  }
 }
}
void timer1(void) interrupt 3
{
 clock=~clock;          //定时器产生ADC0809所需的时钟信号
}
void display()
{
 P0=shuzi[gw];  //个位
 P2=0xf8&duanxuan[tdao];
 delay();
 
 P0=shuzi[sw];    //十位
 P2=0xf4&duanxuan[tdao];
 delay();

 P0=shuzi[bw]&0x7f;     //电压百位
 P2=0xf2&duanxuan[tdao];
 delay();

 P0=shuzi[tdao+1];   //通道从1~8,每秒换一个通道
 P2=0xf1&duanxuan[tdao];
 delay();
}


//the main fun
void main(void)
{

 uchar  i;
 Timer();
 TR0=1;
 ET0=1;
 TR1=1;
 ET1=1;
 EA=1;

while(1)
{
   AD_zh();

  for(i=0;i<10;i++)   //降低刷新速度,使显示稳定

   {
    display();//显示程序

   }
 }
}

上述部分是百度百科的知识,我只是粘贴在这以备自己后面用到,以上仅供参考即可。

发布了5 篇原创文章 · 获赞 4 · 访问量 164

猜你喜欢

转载自blog.csdn.net/ywanju/article/details/105230938