单片机 > 单片机程序设计 > 详情

51单片机温度PID算法(C程序)

发布时间:2024-07-09 发布时间:
|

#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=25; 


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


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<


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; 



}




『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
快速学Arm(37)--定时器和计数器(1)