#include <reg51.h>   
#include <intrins.h>                            
#include <absacc.h>
#include <string.h> 
#include <math.h>

#define   uchar  unsigned char
#define   uint   unsigned int
#define   COM8279   XBYTE [0x0A001]   //8279ƿ
#define   DATA8279  XBYTE [0x0A000]   //8279ݿ

sbit     FAN=P3^3;    //
sbit     DQ=P3^4;     //18B20ݿ
sbit     CR=P3^5;     //ˮ

unsigned int   temper;             //ǰ¶
unsigned int   temp;               
unsigned int   set_temper=40;      //ǰ趨¶
unsigned int   p_2=4,p_1=0,p_0=0;  //ʾǰ趨¶ȣʮλλСλ
unsigned int   lock=0;             //
unsigned int   high_time,low_time,count=0;//ռձȵڲ 
unsigned int   keyval;	         //ֵ
unsigned int   time;             //ʱ
unsigned int   s,begin_judge1=0,begin_judge2=1,reset_judge=1,time=0;   

struct PID 
{ 
	unsigned int SetPoint; // 趨Ŀ
	unsigned int Proportion; // 
	unsigned int Integral; // ֳ
	unsigned int Derivative; // ΢ֳ  
	unsigned int LastError; // Error[-1] 
	unsigned int PrevError; // Error[-2] 
	unsigned int SumError; // Sums of Errors 
}; 
struct PID spid; // PID Control Structure 
unsigned int rout; // PID Response (Output) 
unsigned int rin; // PID Feedback (Input) 

uchar code ditab[16]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};  //ʮƶӦʮƣ18b20Сλ "-"
uchar led[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71}; //0Fļ
uchar data display[5]={0x00,0x00,0x00,0x00,0x00};     //ʾԪݣ4ݺһ              
uchar data temp_data[2]={0x00,0x00};   //¶ݷ

void delay(uint t);
void key();
void ledclr();

void get_temper()
{
	temper=display[2]*100+display[1]*10+display[0];
	set_temper=p_2*100+p_1*10+p_0;   
}

void delay(uint t)
{
  	for (;t>0;t--);
}

/*Initialize PID Structure*/ 
void PIDInit (struct PID *pp) 
{ 	memset ( pp,0,sizeof(struct PID)); } 

/*PID㲿*/ 
unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint ) 
{ 
	unsigned int dError,Error; 
	Error = pp->SetPoint - NextPoint; // ƫ 
	pp->SumError += Error; //  
	dError = pp->LastError - pp->PrevError; // ǰ΢ ϴ-ϴ
	pp->PrevError = pp->LastError; 
	pp->LastError = Error; 
	return (pp->Proportion * Error 	+ pp->Integral * pp->SumError 	+ pp->Derivative * dError); // ++΢ 
} 

/*¶ȱȽϴӳ*/ 
compare_temper() 
{ 
	if(set_temper>temper) 
	{ 
		if(set_temper-temper>10) //101
		{ 
			high_time=90; 
			low_time=10; 
		} 
		else 
		{ 
			{ get_temper(); 
			rin = s; 
			rout = PIDCalc ( &spid,rin ); // Perform PID Interation 
			} 
			if (high_time<=90) 
				high_time=(unsigned char)(rout/150); 
			else 
				high_time=90; 
			low_time= (100-high_time); 
		} 
	} 
	else if(set_temper<=temper) 
	{ 
		high_time=0; 
		low_time=100; 
	} 

} 

/*T0жϷӳ  PWMƽķת 40us*100=4ms*/ 
void serve_T0() interrupt 1 using 2
{ 
	if(++count<=(high_time)) 
		CR=1; 
	else if(count<=100) 
	{ 
		CR=0; 
	} 
	else 
		count=0; 
	TH0=0xec; 
	TL0=0x78; 
} 

void intsvr1(void) interrupt 0 using 1  //ж
{
	COM8279=0x40;  //FIFO
	keyval=DATA8279;
	key();
}

void ledclr()  //
{
	COM8279 = 0xD3; //RAMFIFO  1101 0011
	delay(100);
	COM8279=0x00; //8279˫,ڱɨ裬,8ַʾ
	COM8279=0x32; //ʱӷƵ,ƵΪ18   0011 0010
	COM8279=0x70; //öʾ            0111 0000
	COM8279=0x90; //дʾ            1001 0000
}

void key()
{
	char u;
	EX0=0;  
	/* ̣¶ */
	if(keyval==0x0DB)
	{
		lock=1-lock;		
		ledclr();		
		if(lock==1)
			DATA8279=0x38;   //L&UʾǷ			
		else
			DATA8279=0x3e;		
		delay(65535);		
		EX0=1;
		return;
	}
    if(lock==0)  //δʱ
	{
		   if(keyval== 0x0C3)
			  begin_judge1=1;
		   if(keyval== 0x0CB)
				reset_judge=1;
	       if(keyval==0x0D0)
		   {
			   if(spid.Proportion<15)
			   {
			    spid.Proportion++;
			   }
	
		   }
	
		   if(keyval==0x0D8)
	       {
			   if(spid.Proportion>0)
			   {
			    spid.Proportion--;
			   }
		   }
	
		   if(keyval==0x0D1)
	       {
			   if(spid.Integral<15)
			   {
				spid.Integral++;
			   }
		   }
	
		   if(keyval==0x0D9)
		   {
			  if(spid.Integral>0)
			  {
			   spid.Integral--;
			  }
		   }
	
		   if(keyval==0x0D2)
		   {
			  if(spid.Derivative<15)
			  {
			   spid.Derivative++;
			  }
		   }
	
		   if(keyval==0x0DA)
		   {
			  if(spid.Derivative>0)
			  {
			   spid.Derivative--;
			  }
		   }
	
		   if(keyval==0x0C0) //Сλ
		   {
			  if(p_0==9)
			  {
				if(p_1==9)
				{
					p_2++;
					p_0=0;
					p_1=0;
				}
				else
				{
					p_1++;
					p_0=0;
				}
			  }
			  else
				p_0++;
		   }
		
	       if(keyval==0x0C8)   //Сλ
		   {
			if(p_0==0)
			{
				if(p_1==0)
				{
					p_2--;
					p_1=9;
					p_0=9;
				}
				else
				{
					p_1--;
					p_0=9;
				}
			}
			else
		      p_0--;
		   }
		
		if(keyval==0x0C1)   //λ
		{
			if(p_1==9)
			{
				
				p_2++;
				p_1=0;
			}
			else
				p_1++;		
		}
		
		if(keyval==0x0C9)  //λ
		{		
			if(p_1==0)
			{
				p_2--;
				p_1=9;			
			}
			else
				p_1--;
		}
		
		if(keyval==0x0C2) //ʮλ
			p_2++;
		
		if(keyval==0x0cA) //ʮλ 
			p_2--;
	
	
	//**************** <0Ȼ>=80 ǿ趨Ϊ40*************
	
		if(!((0<=p_2)&&(p_2<8)))
		{
			ledclr();
		
			DATA8279=0x40;
			DATA8279=0x40;
			DATA8279=0x40;
			DATA8279=0x40;
			DATA8279=0x40;
			DATA8279=0x40;
			DATA8279=0x40;
			DATA8279=0x40;		
			delay(65535);
			delay(65535);
			delay(65535);
			p_2=4;
			p_1=0;
			p_0=0;
		
			EX0=1;
		
			return;
		}
	
	//*********************** ʾú¶ ************************//
		
		if(keyval==0x0C8||keyval==0x0C0||keyval==0x0C1||keyval==0x0C9||keyval==0x0C2||keyval==0x0CA)
		{
	    	ledclr();
	    	u=led[p_2];
     		DATA8279=u;
			u=led[p_1];
			u=u+0x80;
			DATA8279=u;
			u=led[p_0];
			DATA8279=u;
			DATA8279=0x00;
			DATA8279=0x63;
			DATA8279=led[12];
			delay(20000);
			ledclr();
	    	u=led[p_2];
     		DATA8279=u;
			u=led[p_1];
			u=u+0x80;
			DATA8279=u;
			u=led[p_0];
			DATA8279=u;
			DATA8279=0x00;
			DATA8279=0x63;
			DATA8279=led[12];
			delay(20000);
			ledclr();
	    	u=led[p_2];
     		DATA8279=u;
			u=led[p_1];
			u=u+0x80;
			DATA8279=u;
			u=led[p_0];
			DATA8279=u;
			DATA8279=0x00;
			DATA8279=0x63;
			DATA8279=led[12];
			delay(20000);
			EX0=1;
		}
		if(keyval==0x0C3||keyval==0x0CB)
		{
			delay(20000);
			EX0=1;
		}	
		if(keyval==0x0D8||keyval==0x0D0||keyval==0x0D1||keyval==0x0D9||keyval==0x0D2||keyval==0x0DA)
		{
		    ledclr();
		    DATA8279=0x73;  //P
		    DATA8279=0x06;  //I
		    DATA8279=0xde;  //D.
		    DATA8279=0x00;
		    DATA8279=0x00;
		    u=led[spid.Proportion];
	  	    DATA8279=u;
		    u=led[spid.Integral];
		    DATA8279=u;
		    u=led[spid.Derivative];
		    DATA8279=u;
		    delay(20000);
		    
		    ledclr();
		    DATA8279=0x00;	 
			DATA8279=0x00;	 
			DATA8279=0x00;	 
			DATA8279=0x00;	 
			DATA8279=0x00;	 
			DATA8279=0x00;	 
			DATA8279=0x00;	 
			DATA8279=0x00;
	        delay(20000);
		    
		    ledclr();
		    DATA8279=0x73;
		    DATA8279=0x06;
	    	DATA8279=0xde;
	        DATA8279=0x00;
		    DATA8279=0x00;
		    u=led[spid.Proportion];
	  	    DATA8279=u;
		    u=led[spid.Integral];
		    DATA8279=u;
		    u=led[spid.Derivative];
		    DATA8279=u;
		    delay(20000);
		
		    ledclr();
		    DATA8279=0x00;	 
			DATA8279=0x00;	 
			DATA8279=0x00;	 
			DATA8279=0x00;	 
			DATA8279=0x00;	 
			DATA8279=0x00;	 
			DATA8279=0x00;	 
			DATA8279=0x00;
		    delay(20000);
		    
		    ledclr();
		    DATA8279=0x73;
		    DATA8279=0x06;
		    DATA8279=0xde;
		    DATA8279=0x00;
		    DATA8279=0x00;
		    u=led[spid.Proportion];
	  	    DATA8279=u;
		    u=led[spid.Integral];
		    DATA8279=u;
	        u=led[spid.Derivative];
		    DATA8279=u;
		    delay(20000);
			
	        delay(65535);
		    EX0=1;
		}
	EX0=1;
	}
	EX0=1;
}

void TempControl()  //ȿ
{	
	if((display[2]*100+display[1]*10+display[0])>(p_2*100+p_1*10+p_0+20))
	{
		time++;
		if(time>10)
		{
			FAN=0;
			FAN=1;
		}
		
	}
	else
	{
		FAN=0;
		time=0;
	}
	
}

/****************ʾ***************************/
void disp()
{
	char k;
	char u;
	
	COM8279 = 0xD3;//RAMFIFO  1101 0011
	delay(100);
	COM8279=0x00; //8279˫,ڱɨ裬,8ַʾ
	COM8279=0x32;//ʱӷƵ,ƵΪ18   0011 0010
	COM8279=0x70;	//öʾ              0111 0000
	COM8279=0x90;//дʾ              1001 0000
	ledclr();
	if(begin_judge2==0)
	{
		if((display[2]*100+display[1]*10+display[0])<(p_2*100+p_1*10+p_0)-10)//״̬ʾ L
		{
			DATA8279=0x38;  
			DATA8279=0x00;
		}
		else
		{
			if((display[2]*100+display[1]*10+display[0])>(p_2*100+p_1*10+p_0+5))//ʾF
			{
				DATA8279=led[15];
				DATA8279=0x00;
			}
			else if((display[2]*100+display[1]*10+display[0])<(p_2*100+p_1*10+p_0))//ʾF
			{
				DATA8279=0x73; //һλʾP  PID
		    	DATA8279=0x00;
			}
			else
			{
				DATA8279=led[0]; //һλʾN  ״̬
		    	DATA8279=0x00;
			}
		}
	}
	for(k=2;k>=0;k--)  
	{
		u=led[display[k]];
		if(k==1)
		{
			u=u+0x80;//С
		}
		DATA8279=u;		
	}
	if(begin_judge2==0)
	{
		DATA8279=0x00;
		DATA8279=0x63;
		DATA8279=led[12];//ʾ
	}
	delay(100);
	TempControl();
}

/*DS18B20λ*/
ow_reset(void)
{
	char presence=1;
	while(presence)
	{
		while(presence)
		{
			DQ=1;_nop_();_nop_();//Ӹ
			DQ=0;                                       
			delay(50);           //550 us
			DQ=1;                                        
			delay(6);             //66 us
			presence=DQ;         //presence=0 λɹ,һ
		} 
		delay(45);             //ʱ500 us
		presence=~DQ;         
	}
	DQ=1;                   //ߵƽ
}

/*DS18B20д*/
void write_byte(uchar val)
{ 
	uchar i;
	for(i=8;i>0;i--)
	{
		DQ=1;_nop_();_nop_();                   //Ӹ
		DQ=0;_nop_();_nop_();_nop_();_nop_();   //5 us
		DQ=val&0x01;                           //λƳ
		delay(6);                               //66 us
		val=val/2;                             //1λ
	}
	DQ=1;
	delay(1);
}

/*DS18B201ֽں*/
uchar read_byte(void)
{
	uchar i;
	uchar value=0;
	for(i=8;i>0;i--)
	{
		DQ=1;_nop_();_nop_();
		value>>=1;
		DQ=0;_nop_();_nop_();_nop_();_nop_();         //4 us
		DQ=1;_nop_();_nop_();_nop_();_nop_();         //4 us
		if(DQ)value|=0x80;
		delay(6);                                     //66 us
	}
	DQ=1;
	return(value);
}


/*¶Ⱥ*/
read_temp()
{
	ow_reset();                   //߸λ
	delay(200);
	write_byte(0xcc);             //
	write_byte(0x44);             //ת
	ow_reset(); 
	delay(1);
	write_byte(0xcc);             //
	write_byte(0xbe);
	delay(00);	
	temp_data[0]=read_byte();     //¶ֵĵֽ
	temp_data[1]=read_byte();     //¶ֵĸֽ
	temp=temp_data[1];
	temp<<=8;                                               
	temp=temp|temp_data[0];       // ֽںϳһͱ
	return temp;                 //¶ֵ
}

/*¶ݴ*/
work_temp(uint tem)
{
	uchar n=0;
	if(tem>6348)                   // ¶ֵж
	{tem=65536-tem;n=1;}           // ¶,־λ1
	display[4]=tem&0x0f;           // ȡСֵֵ
	s=((unsigned int)temp_data[0]&0x0f)*100/16;
	display[0]=ditab[display[4]];  // Сʾֵ
	display[4]=tem>>4;             // ȡмλ,ֵֵ
	display[3]=display[4]/100;     // ȡλݴ
	display[1]=display[4]%100;     // ȡλݴ
	display[2]=display[1]/10;      // ȡʮλݴ
	display[1]=display[1]%10;  
	/*λʾж*/
	if(!display[3]) 
	{
		display[3]=0x0a;           //λΪ0ʱʾ
		if(!display[2])
		{
			display[2]=0x0a;         //θλΪ0ʱʾ
		}
	}
	if(n){display[3]=0x0b;}       //¶ʱλʾ"-"
}


main()
{
	int a[5], a_final, count_a, max, min;
	set_temper=40;      //ǰ趨¶
	p_2=4,p_1=0,p_0=0;  //ʾǰ趨¶ȣʮλλСλ
	lock=0;             //
	count=0;//ռձȵڲ 
	begin_judge1=0;
	begin_judge2=1;
	TMOD=0x21; 
	TH0=0xec; 
	TL0=0x78;	
	SCON=0x50; 
	PCON=0x00; 
	TH1=0xfd; 
	TL1=0xfd; 
	PS=1; 
	EA=1; 
	EX1=0; 
	ET0=1; 
	ES=1; 
	TR0=1; 
	TR1=1; 
	high_time=0; 
	low_time=100; 
	PIDInit (&spid);  
	spid.Proportion = 6; // Set PID Coefficients PIDϵ
	spid.Integral = 7; 
	spid.Derivative = 8; 
	spid.SetPoint = 100; // Set PID Setpoint 
	EA=1;
	EX0=1;                             //ж,ⲿж1
	IT0=1;                              //ⲿж1ѡ½
	COM8279 = 0xD3;//RAMFIFO  1101 0011
	delay(100);
	COM8279=0x00; //8279˫,ڱɨ裬,8ַʾ
	COM8279=0x32;//ʱӷƵ,ƵΪ18   0011 0010
	COM8279=0x70;	//öʾ              0111 0000
	COM8279=0x90;//дʾ              1001 0000	
    while(1)
	{
		ledclr();
		DATA8279=0x71;
        DATA8279=0x3E;
        DATA8279=0x5E;
        DATA8279=0x77;
        DATA8279=0x37;
        DATA8279=0x00;
        DATA8279=0x5E;
		DATA8279=0x6E;
		delay(10000);
		if(begin_judge1==1)
		{
			begin_judge2=0;
			break;
		}
		if(reset_judge==1)
		{
			reset_judge=0;
			((void(code *)(void))0x036f)();
		}
	}
	while(1)
	{	
			a[0]=read_temp();
			a[1]=read_temp();
			a[2]=read_temp();
			a[3]=read_temp();
			a[4]=read_temp();
			for(count_a=0,max=a[0];count_a<5;count_a++) //find the max temp and the min temp
				if(max<a[count_a])
					max=a[count_a];
			for(count_a=0,min=a[0];count_a<5;count_a++)
				if(min>a[count_a])
					min=a[count_a];
		a_final=(a[0]+a[1]+a[2]+a[3]+a[4]-max-min)/3; //ֵ˲ʹɼ¶ƽ

		work_temp(a_final);                        
		delay(10000);
		get_temper(); 
		compare_temper(); 
		disp();  
		if(reset_judge==1)
		{
			reset_judge=0;
			((void(code *)(void))0x036f)();
		}
	}
}