51单片机:用ADC0832做模数转换,测量电压大小

51单片机:用ADC0832做模数转换,测量外界电压大小

问题要求

利用51单片机,外加一个ADC0832模数转换器,设计一个可以实时测量电压的电路。测量电压的范围是0-5V(允许误差),要求测出的电压用数码管实时显示,精确到小数点后两位。

代码编写:

//----------------------------------------------------------
//       用ADC0832测量电压,并将测量值显示在数码管上
//----------------------------------------------------------
#include
#include
#define uchar unsigned char
#define uint  unsigned int 
uchar Get_AD_Result();   //模数转换结果
void ET0_init();         //定时器0中断
void RT1_init();          //定时器1中断


//ADC0832引脚定义
sbit CS   = P1^0;
sbit CLK  = P1^1;
sbit DIDO = P1^2;

//数码管位选
sbit qian = P2^4;	  
sbit bai  = P2^5;
sbit shi  = P2^6;
sbit ge   = P2^7;

//数码管位选
unsigned char date[4];
//共阴极七段数码
unsigned char code tb[18]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
				          0x7f,0x6f,0x77,0x7c,0x39,0x5e,
						  0x79,0x71,0x00,0X80};



//------------------------------
//            主函数
//-------------------------------
void main()			
{  
   ET0_init();    //定时器0初始化
   RT1_init();    //定时器1初始化
   ET0  = 1;
   TR0  = 1;
   ET1  = 1;
   TR1  = 1;
   EA   = 1;     //打开总中断
   CLK = 0;      //ADC0832初始化
   CS   = 1;   
   while(1);

}

//---------------------------------
//            定时器0中断
//---------------------------------
void ET0_INT() interrupt 1   
{	
    static uchar i;
    
	TH0  = (65536-2000)/256; // 重装初值
    TL0  = (65536-2000)%256;

	P2 |= 0xf0;  //消影
	switch(i)	 //位选,选择点亮的数码管,
	{
	    case(0):
		  P0 = date[0];qian = 0;break;//显示千位
	    case(1):
		  P0 = date[1];bai  = 0;break;//显示百位
	    case(2):
		  P0 = date[2];shi  = 0;break;//显示十位
		case(3):
		  P0 = date[3];ge   = 0;break;//显示个位		
  }

	i++;
    if(i==4)
	   {
		  i=0;
	   }

}

//---------------------------------------------
//        定时器T1中断服务程序
//---------------------------------------------
void ET1_INT() interrupt 3   
{
 // float L = 500.0/256.0;
  uint vt;
  uchar AD;

  TH1  = (65536-2000)/256; // 重装初值
  TL1  = (65536-2000)%256;
  
  AD = Get_AD_Result();
  vt = (500.0/256.0)*AD; //测量电压值
 
  date[0] =tb[vt/1000];
  date[1] =tb[vt/100%10]|0x80; //点亮小数点
  date[2] =tb[vt/10%10];
  date[3] =tb[vt%10];
}

//------------------------------
//     获取AD转换结果(0通道)
//------------------------------
uchar Get_AD_Result()         //包含11个CLK下降沿      
{
    uchar i, dat;
    CS = 1;              //ADC0832未工作时,CS端为高电平,此时芯片禁用
    _nop_;               //对于延时很短的,要求在us级的,采用“_nop_”函数      
    CLK =1;                  
    CS = 0;
    DIDO = 1; CLK = 0; _nop_; CLK = 1; _nop_; //SCLK第一个下降沿来到时,DI = 1启动ADC0832
    DIDO = 1; CLK = 0; _nop_; CLK = 1; _nop_; //SCLK第二个下降沿 
    DIDO = 0; CLK = 0; _nop_; CLK = 1; _nop_; //SCLK第三个下降沿,发送1,0选择通道cho
    DIDO = 1;                                //释放总线
    for(i = 0; i < 8; i++)                  //第4个下降沿到第11个下降沿
    {
        CLK = 0;                           //clk处于下降沿,每一个下降沿DO端输入下一个
        _nop_;                              //对于延时很短的,要求在us级的,采用_nop_函数      
        if(DIDO) dat |= 0x01;              // dat = dat | 0x01,dat和0x01做“或”的运算,意思是最低位置1,其它位保持不变。
        CLK = 1; _nop_;                      //clk处于上升沿
        dat <<= 1;                          //数据左移
    }
    return (dat);
    CS = 1;                                  //ADC0832停止工作
}

//------------------------------
//定时器0初始化
//------------------------------
void ET0_init()             
{
	TMOD &= 0xf0;			//定时器0
    TMOD |= 0x01;
    TH0  = (65536-2000)/256; //2ms溢出
    TL0  = (65536-2000)%256; 
}

//---------------------------------
//         定时器1初始化
//-----------------------------------
void RT1_init()   
{
   TMOD &= 0x0f;			 
   TMOD |= 0x10;
   TH1  = (65536-2000)/256; //2ms溢出
   TL1  = (65536-2000)%256; 
}

电路设计图:

51单片机:用ADC0832做模数转换,测量电压大小_第1张图片

仿真结果:

51单片机:用ADC0832做模数转换,测量电压大小_第2张图片
51单片机:用ADC0832做模数转换,测量电压大小_第3张图片
51单片机:用ADC0832做模数转换,测量电压大小_第4张图片
(注:ADC0832初始化参考了zhai1997的博客)

你可能感兴趣的:(51单片机)