/*------------------------------------------------------------------------------                                                                          
 YL-51单片机开发板演示程序 - ADC0804(模数转换)5V数字电压表                  
                                                                            
 MCU:STC89C52 ,晶体频率：12MHz                                             
                                                                           
 功能:在数码管上能方便的显示出ADIN端的输入电压.当ADIN接上跳线帽时,          
 拧动电位器，会在数码管的前四位显示RE2电位器的输出电压值0-5V之间的数值.     
 也可以把ADIN左边的接线柱用杜邦线引出作为电压表的正表笔,负表笔为主板的地    
                                                                           
【版权】Copyright(C) 云龙电子  www.yunlongdz.cn  All Rights Reserved        
【声明】此程序仅用于学习与参考，引用请注明版权和作者信息！                  
【注意】电压表的精度和学习板供电电压有关,基准电压为5V.                     
------------------------------------------------------------------------------*/

#include<reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit adcs=P0^7;      //芯片选择信号,控制芯片的启动和结果读取,低电平有效
sbit adrd=P3^7;      //读数据控制,低电平有效
sbit adwr=P3^6;     //AD转换起动控制,上升沿有效
sbit dula=P2^6;   //数码管段选
sbit wela=P2^7;   //数码管位选
uchar code table_du[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,
0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};  //数码管段选编码

void delay(uint i)  //5ms延时子程序
{       
	uint j;
    for(;i>0;i--)
    for(j=0;j<410;j++);
}


void start_ad(void)  //启动AD转换子程序
{       
	wela=1;
	adcs=0;      //允许进行A/D转换
    adwr=0;
	_nop_();
	adwr=1;     //adwr由低变高时,AD开始转换
    adcs=1;    //停止AD转换
}


read_ad()  //读A/D数据子程序
{       
	uint ad_data;
    P1=0xff;
	wela=1;
    adcs=0;              //允许读
    adrd=0;             //读取转换数据结果数据结果
    _nop_();
    ad_data=P1;       //把数据存到ad_data中
	wela=1;
    adrd=1;
	adcs=1;        //停止A/D读取
    return(ad_data);
}



void data_shout(uint ad_data)  //数据处理与显示子程序
{                              //说明:当输入电压为5V时,A/D输出为FFH,即输入电压=AD数据*(5/255)=AD数据/(255/5)=AD数据/51
	uint a=50,one,two,three,four;
    one=ad_data/51;                       //第一位数码管
	two=ad_data%51*10/51;                 //第二位数码管
	three=ad_data%51*10%51*10/51;         //第三位数码管
	four=ad_data%51*10%51*10%51*10/51;   //第四位数码管
    while(a--)
    {   
		P0=0xff;       //关闭所有数码管显示，防止有交替重影，专业名称叫（消隐）		
		wela=1;
		wela=0;		
		P0 =table_du[one]-0x80; //-0x80是为了显示小数点
		dula=1;
		dula=0;
		P0=0x7e;   //第1位数码管位选
		wela=1;
		wela=0;	
        delay(1);

		P0=0xff;       	
		wela=1;
		wela=0;			
		P0=table_du[two]; 
		dula=1;
		dula=0;
		P0=0x7d;   //第2位数码管位选
		wela=1;
		wela=0;	
        delay(1);
		
		P0=0xff;       		
		wela=1;
		wela=0;			
		P0=table_du[three]; 
		dula=1;
		dula=0;
		P0=0x7b;   //第3位数码管位选
		wela=1;
		wela=0;	
        delay(1);

		P0=0xff;       	
		wela=1;
		wela=0;			
		P0=table_du[four]; 
		dula=1;
		dula=0;
		P0=0x77;   //第4位数码管位选
		wela=1;
		wela=0;	
		delay(1);
		
    }
}

void main()
{      
	while(1)
    {      
		start_ad();             //启动AD
        data_shout(read_ad());  //读AD数据并显示
    }
}


