AD转换及显示
##include"reg51.h"
#define uchar unsigned char
#define uint unsigned int
#define LED_DIGPORT P0; //数码管位选接上拉电阻
#define AD_DATAPORT P1; //A/D数据口
#define LED_WORDPORT P2; //数码管段码
sbit AD_EOC=P3^3; //A/D转换结束信号输出端
sbit AD_CLK=P3^4; //A/D时钟信号输入端
sbit AD_START=P3^6; //启动A/D转换控制信号输入端
sbit AD_OE=P3^7; //A/D输出允许控制端
sbit WARM=P3^1; //控制蜂鸣器输出端
sbit LED=P3^0; //基准电压采集结束显示灯
uchar code Seg_Code[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
//共阳极段码
uchar code SegNode_Code[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
//有小数点段码
uchar a[4],dig=0x01;
uchar flag;
uchar i,max,min,count;
long int sum=0,sum1,sum2;
uchar tab[6];
void Delay(uchar t1,uchar t2)
//延时子程序,t1,t2是无符号的字符型全局变量
{ for(;t1>0;t1--)
for(;t2>0;t2--);
}
void Led_Display() //数码管显示子程序
{ uchar i;
for(i=0;i<4;i++) //4个数码管
{ LED_WORDPORT=0xff; //显示清屏
LED_DIGPORT=dig<<i; //位码
LED_WORDPORT=a; //段码
Delay(1,200); //延时
}
}
void time0() interrupt 1
{
AD_CLK=~AD_CLK; //A/D时钟信号
}
void AD_init()
{
for(count=0;count<6;count++) //采集六次转换后的数字量
{
while(!AD_EOC);
//若AD_EOC为低电平,即转换期间,等待,直到转换结束
AD_START=1; //给START一个高电平,上升沿复位内部寄存器
AD_OE=1; //数据输出有效,允许输出
tab[count]=AD_DATAPORT; //转换后的数字量放tab里
Delay(1,10); //延时,给START一个正脉冲
AD_OE=0; //数据输出无效,不允许输出
AD_START=0; //给START一个低电平,启动ADC0809工作
Delay(1,10); //延时一段时间,使得AD转换次数少些,等待AD转换
}
for(i=0;i<6;i++) //将tab内数字量最大的存MAX里,最小的存MIN内
{
max=tab[0];
min=tab[0];
if(max<tab)
{max=tab;}
if(min>tab)
{min=tab;}
}
sum1=(tab[0]+tab[1]+tab[2]+tab[3]+tab[4]+tab[5]-max-min)/4;
//TAB内数字量去掉最大和最小的总和放sum1中
sum1=(sum1*50000)/255;
//将总和*10000转换为整数,再转换为跟模拟量对应的数值,以便显示程序调用sum1
count=0; //清零
LED=0; //基准电压采集结束显示灯亮
}
void AD_chuli() //A/D信号处理
{
AD_START=1; //又上升沿复位内部寄存器
AD_OE=1; //OE为高电平时,允许输出,转换结果出现D7~D0
if(count<6) //采集不满6次,不处理,只count++
{
tab[count]=AD_DATAPORT;
count++;
flag=0;
sum=0;
}
if(count==6) //采集到6次时
{
LED=0; //基准电压采集结束显示灯亮
max=tab[0];
min=tab[0];
for(i=0;i<6;i++)
{
if(max<tab) //将tab内数字量最大的存MAX里,最小的存MIN内
{max=tab;}
if(min>tab)
{min=tab;}
}
sum=(tab[0]+tab[1]+tab[2]+tab[3]+tab[4]+tab[5]-max-min)/4;
//TAB内数字量去掉最大和最小的总和放sum中
sum=(sum*50000)/255;
//将总和*10000转换为整数,再转换为跟模拟量对应的数值,以便显示程序调用sum
sum2=sum;
a[0]=Seg_Code[sum/10%10]; //千分位
a[1]=Seg_Code[sum/100%10]; //百分位
a[2]=Seg_Code[sum/1000%10]; //十分位
a[3]=SegNode_Code[sum/10000]; //个位
count=0;
flag=1;
}
Delay(1,10);
AD_OE=0; //OE为低电平时,不允许输出,D7~D0对外成高阻态
AD_START=0; //下降沿又开始启动A转换D
Delay(1,10); //延时一段时间,使得AD转换次数少些,等待AD转换
}
void main(void) //主程序
{
Delay(1,30);
TMOD=0x02; TH0=200; TL0=200;
//定时器工作在方式2,自动重装初值的八位计数器,须定时200us左右
TR0=1; ET0=1; PT0=1;
//TR0启动T0计数,ET0开T0中断,PT0高优先级T0中断
EA=1; //开所有中断
WARM=0; //蜂鸣器不工作
AD_START=0;
AD_START=1; //上升沿复位内部寄存器
AD_START=0; //下降沿开始A/D
if(AD_EOC); //AD_EOC为高电平,即转换结束
AD_init(); //存储数字量
while(1)
{
Led_Display(); //数码管显示
if(AD_EOC)
AD_chuli(); //查询
if(sum2-sum1>10000||sum1-sum2>10000)
//10000代表灵敏度暂设为1V上下
WARM=1;
else
WARM=0;
}