一,ADC0809概述:
ADC0809 是采用CMOS 工艺制造的双列直插式单片8 位A/D 转换器。 分辨率8位,拥有8 个模拟量输入通道,有通道地址译码锁存器,输出带三态数据锁存器。启动信号为脉冲启动方式,最大可调节误差为±1LSB。ADC0809 内部没有时钟电路,故CLK 时钟需由外部输入,时钟clk 允许范围为500kHz-1MHZ,典型值640kHz。每通道的转换需66-73 个时钟脉冲,转换时间大约100μs,工作温度范围为-40℃-+85℃。功耗为15mW,输入电压范围为0~5V,单一+5V 电源供电,基准电压5V。
二,adc0809引脚介绍
adc0809引脚介绍:
IN0~IN7:8路模拟量输入端。
D0~D7:8位数字量输出端。
ALE:地址锁存允许信号,输入,高电平有效(上升沿)。
START:A/D转换启动信号,输入,高电平有效(下降沿)。
EOC:A/D转换结束信号,输出。当启动转换时,该引脚为低电平,当A/D转换结束时,该线脚输出高电平。
OE:数据输出允许信号,输入,高电平有效。当转换结束后,如果从该引脚输入高电平,则打开输出三态门,输出锁存器的数据从D0~D7送出。
CLK:时钟脉冲输入端。要求时钟频率不高于640KHZ.
REF+、REF-:基准电压输入端。
Vcc:电源,接+5V电源。
GND:地。
ADDA、ADDB、ADDC:3位地址输入线,用于选择8路模拟通道中的一路,具体定义如下图:
内部结构图如下图:
操作时序图:
三,尖峰检测电路:
运用集成运算放大器构成同相比例运算电路,不规则信号(正)通过输入端输入不停给电容充电,当充电完成后,当电压下降,由于二极管截至,电容将向运放放电,输出输入信号的峰值。图中二极管起保护作用,三极管构成的电路(当开关接高电平时,三极管导通)给电容放电提供通道。
四,程序构成:
LCD1602显示程序,ADC0809八路采集程序。
主函数将依次采集ADC0809八路的输入信号,其中IN1接在尖峰检测电路的输出端,用于采集输入不规则信号的峰值(<=5V)(实际电路采集的电压要考虑二极管的压降),IN0,IN2-IN7外接7个电位器,采集电位器的电压,显示屏依次显示采集电压。
五,程序源码:
#include "reg51.h"
#include "lcd1602.h"
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
sbit addA=P2^0;
sbit addB=P2^1;
sbit addC=P2^2;
sbit adStart=P2^6;
sbit adOE=P2^7;
sbit adCLK=P3^4;
sbit adEOC=P3^6;
sbit LED=P3^7;
sbit RS = P2^3; //定义端口
sbit RW = P2^4;
sbit EN = P2^5;
#define RS_CLR RS=0
#define RS_SET RS=1
#define RW_CLR RW=0
#define RW_SET RW=1
#define EN_CLR EN=0
#define EN_SET EN=1
#define DataPort P0
//ADC0809结构体
typedef struct _AD
{
uchar addrA;
uchar addrB;
uchar addrC;
uint PortFlag;
uchar ADCPort[8][5];
}AD;
AD ad;
uchar code *dat[8]={{" ADC_PORT0:0.00V"},
{" ADC_PORT1:0.00V"},
{" ADC_PORT2:0.00V"},
{" ADC_PORT3:0.00V"},
{" ADC_PORT4:0.00V"},
{" ADC_PORT5:0.00V"},
{" ADC_PORT6:0.00V"},
{" ADC_PORT7:0.00V"}};
//按键结构体
typedef struct _Button
{
uchar mode;
uchar keyvalue;
uchar sure;
uchar cancel;
uchar buttonvalue;
}Button;
typedef struct _CALCULATE
{
uchar dat[3];
int result[3];
uchar symbol;
}CALCULATE;
CALCULATE calc;
Button button={0,0,0,0};
sbit ButtonSureCancel=P3^2;
sbit ButtonModeSelection=P3^3;
///////////////////////////////////////函数声明区/////////////////////////////////////////
void ADC0809_Operation(uchar ADport);
void delay_ms(uint i);
static uchar AD_Acquisition(void);
static uchar AD_Handler(uchar dat);
void Display_AD_Value(uchar x,uchar y,uchar *s);
void ALL_Init(void);
void LCD_Write_Com(uchar com);
void LCD_Write_Data(uchar Data);
void LCD_Clear(void);
void LCD_Write_String(uchar x,uchar y,uchar *s);
void LCD_Write_Char(uchar x,uchar y,uchar Data);
void LCD_Init(void);
void DelayMs(uchar t);
void DelayUs2x(uchar t);
//void delay(void);
/////////////////////////////////////////////////END///////////////////////////////////////
/*
* 函数名称:使用嵌套汇编的延时函数
* 参数: 无
* 返回值: 无
*/
//void delay(void)
//{
//#pragma ASM
// MOV R7,#02
// D1: MOV R4,#125
// D2: MOV R3,#248
// DJNZ R3,$
// DJNZ R4,D2
// DJNZ R7,D1
//#pragma ENDASM
//}
/*
* 函数名称:主函数
* 参数: 无
* 返回值: 无
*/
int main(void)
{
uchar i=0;
ALL_Init();
LCD_Clear();
delay_ms(20);
while(1)
{
for(i=0;i<8;i++)
ADC0809_Operation(i);
}
return 0;
}
/*
* 函数名称:所有初始化函数
* 参数: 无
* 返回值: 无
*/
void ALL_Init(void)
{
LCD_Init();
LCD_Clear();
LCD_Write_String(0,0," AD System READY");
adCLK=0;
adOE=adStart=0;
TMOD=0x12;
TH0=0xff;
TL0=0xff;
TH1=(65535-50000)/256;
TL1=(65535-50000)%256;
ET0=1;
PT0=1;//最高优先级
ET1=1;
IT0=1;
EX0=1;
IT1=1;
EX1=1;
ES=1;
EA=1;
TR0=1; //关闭定时0
TR1=0;
}
/*
* 函数名称:外部中断0辅助函数
* 参数: 无
* 返回值: 无
*/
void Interrupt_Handler_Auxiliary(void)
{
}
/*
* 函数名称:外部中断0函数
* 参数: 无
* 返回值: 无
*/
void INTER0(void)interrupt 0 using 0
{
}
/*
* 函数名称:定时器0函数
* 参数: 无
* 返回值: 无
*/
void INTER1(void)interrupt 1 using 0
{
adCLK=!adCLK;
}
/*
* 函数名称:外部中断1函数
* 参数: 无
* 返回值: 无
*/
void INTER2(void)interrupt 2 using 1
{
}
/*
* 函数名称:延时函数
* 参数: 无
* 返回值: 无
*/
void delay_ms(uint i)
{
uint j=0;
uint k=0;
for(j=0;j<i;j++)
for(k=0;k<=118;k++);
}
/*
* 函数名称:AD数据显示函数
* 参数: 无
* 返回值: 无
*/
void Display_AD_Value(uchar x,uchar y,uchar *s)
{
switch(ad.PortFlag)
{
case 0:
LCD_Write_String(0,0,dat[0]);
break;
case 1:
LCD_Write_String(0,0,dat[1]);
break;
case 2:
LCD_Write_String(0,0,dat[2]);
break;
case 3:
LCD_Write_String(0,0,dat[3]);
break;
case 4:
LCD_Write_String(0,0,dat[4]);
break;
case 5:
LCD_Write_String(0,0,dat[5]);
break;
case 6:
LCD_Write_String(0,0,dat[6]);
break;
case 7:
LCD_Write_String(0,0,dat[7]);
break;
default:
LCD_Write_String(0,0," No ADport Value");
break;
}
LCD_Write_String(x,y,s);
LCD_Write_String(0,1," AD Dat Finished");
}
/*
* 函数名称:AD数据采集函数
* 参数: 无
* 返回值: 无
*/
static uchar AD_Acquisition(void)
{
uchar temp=0;
LCD_Clear();
LCD_Write_String(0,0," Start AD");
adStart=0;
adOE=0;
adStart=1; //启动AD转换
_nop_();
_nop_();
adStart=0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
while(0==adEOC);//等待转换结束
adOE=1;
temp=P1; //读取AD数据,数据范围为0-255
adOE=0;
return temp;
}
/*
* 函数名称:AD数据处理函数
* 参数: 无
* 返回值: 无
*/
static uchar AD_Handler(uchar dat)
{
float t;
int t1;
uchar str[4];
if(ad.PortFlag==1)
t=1.3+(5.0*dat/256);
else
t=(5.0*dat/256);
if(t>=2.0)
LED=0;
else
LED=1;
t1=(int)(t*100);
str[0]=t1/100+'0';
str[1]=0x2e;
str[2]=t1%100/10+'0';
str[3]=t1%10+'0';
switch(ad.PortFlag)
{
case 0:
ad.ADCPort[0][0]=str[0];
ad.ADCPort[0][1]=str[1];
ad.ADCPort[0][2]=str[2];
ad.ADCPort[0][3]=str[3];
ad.ADCPort[0][4]='\0';
Display_AD_Value(11,0,ad.ADCPort[0]);
break;
case 1:
ad.ADCPort[1][0]=str[0];
ad.ADCPort[1][1]=str[1];
ad.ADCPort[1][2]=str[2];
ad.ADCPort[1][3]=str[3];
ad.ADCPort[1][4]='\0';
Display_AD_Value(11,0,ad.ADCPort[1]);
break;
case 2:
ad.ADCPort[2][0]=str[0];
ad.ADCPort[2][1]=str[1];
ad.ADCPort[2][2]=str[2];
ad.ADCPort[2][3]=str[3];
ad.ADCPort[2][4]='\0';
Display_AD_Value(11,0,ad.ADCPort[2]);
break;
case 3:
ad.ADCPort[3][0]=str[0];
ad.ADCPort[3][1]=str[1];
ad.ADCPort[3][2]=str[2];
ad.ADCPort[3][3]=str[3];
ad.ADCPort[3][4]='\0';
Display_AD_Value(11,0,ad.ADCPort[3]);
break;
case 4:
ad.ADCPort[4][0]=str[0];
ad.ADCPort[4][1]=str[1];
ad.ADCPort[4][2]=str[2];
ad.ADCPort[4][3]=str[3];
ad.ADCPort[4][4]='\0';
Display_AD_Value(11,0,ad.ADCPort[4]);
break;
case 5:
ad.ADCPort[5][0]=str[0];
ad.ADCPort[5][1]=str[1];
ad.ADCPort[5][2]=str[2];
ad.ADCPort[5][3]=str[3];
Display_AD_Value(11,0,ad.ADCPort[5]);
break;
case 6:
ad.ADCPort[6][0]=str[0];
ad.ADCPort[6][1]=str[1];
ad.ADCPort[6][2]=str[2];
ad.ADCPort[6][3]=str[3];
ad.ADCPort[6][4]='\0';
Display_AD_Value(11,0,ad.ADCPort[6]);
break;
case 7:
ad.ADCPort[7][0]=str[0];
ad.ADCPort[7][1]=str[1];
ad.ADCPort[7][2]=str[2];
ad.ADCPort[7][3]=str[3];
ad.ADCPort[7][4]='\0';
Display_AD_Value(11,0,ad.ADCPort[7]);
break;
}
delay_ms(100);
return 0;
}
/*
* 函数名称:AD采集函数
* 参数: 无
* 返回值: 无
*/
void ADC0809_Operation(uchar ADport)
{
switch(ADport)
{
case 0:
addA=0;addB=0;addC=0;//PORT0
ad.PortFlag=0;
break;
case 1:
addA=1;addB=0;addC=0;//PORT0
ad.PortFlag=1;
break;
case 2:
addA=0;addB=1;addC=0;//PORT0
ad.PortFlag=2;
break;
case 3:
addA=1;addB=1;addC=0;//PORT0
ad.PortFlag=3;
break;
case 4:
addA=0;addB=0;addC=1;//PORT0
ad.PortFlag=4;
break;
case 5:
addA=1;addB=0;addC=1;//PORT0
ad.PortFlag=5;
break;
case 6:
addA=0;addB=1;addC=1;//PORT0
ad.PortFlag=6;
break;
case 7:
addA=1;addB=1;addC=1;//PORT0
ad.PortFlag=7;
break;
}
AD_Handler(AD_Acquisition());
}
/*
* 函数名称:延时函数
* 参数: 无
* 返回值: 无
*/
void DelayUs2x(uchar t)
{
while(--t);
}
/*
* 函数名称:延时函数
* 参数: 无
* 返回值: 无
*/
void DelayMs(uchar t)
{
while(t--)
{
//大致延时1mS
DelayUs2x(245);
DelayUs2x(245);
}
}
/*
* 函数名称: 判忙函数
* 参数: 无
* 返回值: 无
*/
bit LCD_Check_Busy(void)
{
DataPort= 0xFF;
RS_CLR;
RW_SET;
EN_CLR;
_nop_();
EN_SET;
return (bit)(DataPort & 0x80);
}
/*
* 函数名称: 写入命令函数
* 参数: 无
* 返回值: 无
*/
void LCD_Write_Com(uchar com)
{
// while(LCD_Check_Busy()); //忙则等待
RS_CLR;
RW_CLR;
EN_SET;
DataPort= com;
_nop_();
EN_CLR;
}
/*
* 函数名称: 写入数据函数
* 参数: 无
* 返回值: 无
*/
void LCD_Write_Data(uchar Data)
{
// while(LCD_Check_Busy()); //忙则等待
RS_SET;
RW_CLR;
EN_SET;
DataPort= Data;
_nop_();
EN_CLR;
}
/*
* 函数名称:清屏函数
* 参数: 无
* 返回值: 无
*/
void LCD_Clear(void)
{
LCD_Write_Com(0x01);
DelayMs(5);
}
/*
* 函数名称:写入字符串函数
* 参数: 无
* 返回值: 无
*/
void LCD_Write_String(uchar x,uchar y,uchar *str)
{
if (y == 0)
{
LCD_Write_Com(0x80 + x); //表示第一行
}
else
{
LCD_Write_Com(0xC0 + x); //表示第二行
}
while (*str)
{
LCD_Write_Data(*str);
str ++;
}
}
/*
* 函数名称:写入字符函数
* 参数: 无
* 返回值: 无
*/
void LCD_Write_Char(uchar x,uchar y,uchar Data)
{
if (y == 0)
{
LCD_Write_Com(0x80 + x);
}
else
{
LCD_Write_Com(0xC0 + x);
}
LCD_Write_Data( Data);
}
/*
* 函数名称:初始化函数
* 参数: 无
* 返回值: 无
*/
void LCD_Init(void)
{
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
DelayMs(5);
LCD_Write_Com(0x38);
LCD_Write_Com(0x08);
LCD_Write_Com(0x01);
LCD_Write_Com(0x06);
DelayMs(5);
LCD_Write_Com(0x0C);
}
五,仿真图:
通道1:(尖峰检测电路采集)
注:黄色波形是尖峰检测电路中输入信号(使用峰值5V的正弦信号模拟),蓝色是经过电路后输出波形(峰值为一条线),连接到ADC0809的通道1进行采集。采集电压为4.95V近似为5v。
通道0:
通道2:
通道3:
通道4:
通道5:
通道6:
通道7: