项目中由于单片机开发板自带的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。
引脚及功能:
![](/qrcode.jpg)
-
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();//显示程序
}
}
}
上述部分是百度百科的知识,我只是粘贴在这以备自己后面用到,以上仅供参考即可。