基于51单片机的ADC0809多路采集及尖峰脉冲电路峰值检测

一,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:
在这里插入图片描述

发布了26 篇原创文章 · 获赞 23 · 访问量 5744

猜你喜欢

转载自blog.csdn.net/liuxianfei0810/article/details/105333753
今日推荐