51 温度PID经典算法

#include<reg51.h>  
#include<intrins.h>  
#include<math.h>  
#include<string.h>  
struct PID {  
    unsigned int SetPoint; // 设定目标 Desired Value  
    unsigned int Proportion; // 比例常数 Proportional Const  
    unsigned int Integral; // 积分常数 Integral Const  
    unsigned int Derivative; // 微分常数 Derivative Const  
    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)  
sbit data1=P1^0;  
sbit clk=P1^1;  
sbit plus=P2^0;  
sbit subs=P2^1;  
sbit stop=P2^2;  
sbit output=P3^4;  
sbit DQ=P3^3;  
unsigned char flag,flag_1=0;  
unsigned char high_time,low_time,count=0;//占空比调节参数  
unsigned char set_temper=35;  
unsigned char temper;  
unsigned char i;  
unsigned char j=0;  
unsigned int s;  

void delay(unsigned char time)  
{  
    unsigned char m,n;  
    for(n=0;n<time;n++)  
	for(m=0;m<2;m++){}  
}  

void write_bit(unsigned char bitval)  
{  
    EA=0;  
    DQ=0;  
    if(bitval==1)  
    {  
	_nop_();  
	DQ=1;  
    }  
    delay(5);  
    DQ=1;  
    _nop_();  
    _nop_();  
    EA=1;  
}  

void write_byte(unsigned char val)  
{  
    unsigned char i;  
    unsigned char temp;  
    EA=0;  
    TR0=0;  
    for(i=0;i<8;i++)  
    {  
	temp=val>>i;  
	temp=temp&1;  
	write_bit(temp);  
    }  
    delay(7);  
    // TR0=1;  
    EA=1;  
}  

unsigned char read_bit()  
{  
    unsigned char i,value_bit;  
    EA=0;  
    DQ=0;  
    _nop_();  
    _nop_();  
    DQ=1;  
    for(i=0;i<2;i++){}  
    value_bit=DQ;  
    EA=1;  
    return(value_bit);  
}  

unsigned char read_byte()  
{  
    unsigned char i,value=0;  
    EA=0;  
    for(i=0;i<8;i++)  
    {  
	if(read_bit())  
	    value|=0x01<<i;  
	delay(4);  
    }  
    EA=1;  
    return(value);  
}  

unsigned char reset()  
{  
    unsigned char presence;  
    EA=0;  
    DQ=0;  
    delay(30);  
    DQ=1;  
    delay(3);  
    presence=DQ;  
    delay(28);  
    EA=1;  
    return(presence);  
}  

void get_temper()  
{  
    unsigned char i,j;  
    do  
    {  
	i=reset();  
    }  while(i!=0);  
    i=0xcc;  
    write_byte(i);  
    i=0x44;  
    write_byte(i);  
    delay(180);  
    do  
    {  
	i=reset();  
    }  while(i!=0);  
    i=0xcc;  
    write_byte(i);  
    i=0xbe;  
    write_byte(i);  
    j=read_byte();    
    i=read_byte();  
    i=(i<<4)&0x7f;  
    s=(unsigned int)(j&0x0f);     //得到小数部分 
    s=(s*100)/16;  
    j=j>>4;  
    temper=i|j;  
}  

void PIDInit (struct PID *pp)  
{  
    memset ( pp,0,sizeof(struct PID));    //全部初始化为0 
}  

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);                // 微分项  
}  

void compare_temper()  
{  
    unsigned char i;  
    if(set_temper>temper)      //是否设置的温度大于实际温度 
    {  
	if(set_temper-temper>1)  //设置的温度比实际的温度是否是大于1度 
	{  
	    high_time=100;      //如果是,则全速加热 
	    low_time=0;  
	}  
	else  //如果是在1度范围内,则运行PID计算 
	{  
	    for(i=0;i<10;i++)  
	    {  
		get_temper();   //获取温度 
		rin = s; // Read Input  
		rout = PIDCalc ( &spid,rin ); // Perform PID Interation  
	    }  
	    if (high_time<=100)  
		high_time=(unsigned char)(rout/800);  
	    else  
		high_time=100;  
	    low_time= (100-high_time);  
	}  
    }  
    else if(set_temper<=temper)  
    {  
	if(temper-set_temper>0)  
	{  
	    high_time=0;  
	    low_time=100;  
	}  
	else  
	{  
	    for(i=0;i<10;i++)  
	    { 
		get_temper();  
		rin = s; // Read Input  
		rout = PIDCalc ( &spid,rin ); // Perform PID Interation  
	    }  
	    if (high_time<100)  
		high_time=(unsigned char)(rout/10000);  
	    else  
		high_time=0;  
	    low_time= (100-high_time);  
	}  
    }  
    // else  
    // {}  
}  

void serve_T0() interrupt 1 using 1  
{  
    if(++count<=(high_time))  
	output=1;  
    else if(count<=100)  
    {  
	output=0;  
    }  
    else  
	count=0;  
    TH0=0x2f;  
    TL0=0xe0;  
}  

void serve_sio() interrupt 4 using 2  
{  

}  
void disp_1(unsigned char disp_num1[6])  
{  
    unsigned char n,a,m;  
    for(n=0;n<6;n++)  
    {  
	// k=disp_num1[n];  
	for(a=0;a<8;a++)  
	{  
	    clk=0;  
	    m=(disp_num1[n]&1);  
	    disp_num1[n]=disp_num1[n]>>1;  
	    if(m==1)  
		data1=1;  
	    else  
		data1=0;  
	    _nop_();  
	    clk=1;  
	    _nop_();  
	}  
    }  
}  

void display()  
{  
    unsigned char code number[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6};  
    unsigned char disp_num[6];  
    unsigned int k,k1;  
    k=high_time;  
    k=k00;  
    k1=k/100;  
    if(k1==0)  
	disp_num[0]=0;  
    else  
	disp_num[0]=0x60;  
    k=k0;  
    disp_num[1]=number[k/10];  
    disp_num[2]=number[k];  
    k=temper;  
    k=k0;  
    disp_num[3]=number[k/10];  
    disp_num[4]=number[k]+1;  
    disp_num[5]=number[s/10];  
    disp_1(disp_num);  
}  

void main()  
{  
    unsigned char z; 
    unsigned char a,b,flag_2=1,count1=0;  
    unsigned char phil[]={2,0xce,0x6e,0x60,0x1c,2}; 
    TMOD=0x21;  
    TH0=0x2f;  
    TL0=0x40;  
    SCON=0x50;  
    PCON=0x00;  
    TH1=0xfd;  
    TL1=0xfd;  
    PS=1;  
    EA=1;  
    EX1=0;  
    ET0=1;  
    ES=1;  
    TR0=1;  
    TR1=1;  
    high_time=50;  
    low_time=50;  
    PIDInit ( &spid );    // Initialize Structure  
    spid.Proportion = 10; // Set PID Coefficients  比例常数 Proportional Const  
    spid.Integral = 8;    //积分常数 Integral Const  
    spid.Derivative =6;   //微分常数 Derivative Const  
    spid.SetPoint = 100; // Set PID Setpoint 设定目标 Desired Value  
    while(1)  
    {  
	if(plus==0)  
	{ 
	    EA=0;  
	    for(a=0;a<5;a++)  
		for(b=0;b<102;b++){}  
	    if(plus==0)  
	    { 
		set_temper++;  
		flag=0;  
	    } 
	}  
	else if(subs==0)  
	{  
	    for(a=0;a<5;a++)  
		for(b=0;a<102;b++){}  
	    if(subs==0)  
	    {  
		set_temper--;  
		flag=0;  
	    }  
	}  
	else if(stop==0)  
	{  
	    for(a=0;a<5;a++)  
		for(b=0;b<102;b++){}  
	    if(stop==0)  
	    {  
		flag=0;  
		break;  
	    }  
	    EA=1;  
	}  
	get_temper();  
	b=temper;  
	if(flag_2==1)  
	    a=b;  
	if((abs(a-b))>5)  
	    temper=a;  
	else  
	    temper=b;  
	a=temper;  
	flag_2=0;  
	if(++count1>30)  
	{  
	    display();  
	    count1=0;  
	}  
	compare_temper();  
    }  
    TR0=0;  
    z=1;  
    while(1)  
    {  
	EA=0;  
	if(stop==0)  
	{  
	    for(a=0;a<5;a++)  
		for(b=0;b<102;b++){}  
	    if(stop==0)  
		disp_1(phil);  
	    // break;  
	}  
	EA=1;  
    }  
} 

  • 15
    点赞
  • 103
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值