51控制温度简单的PID算法Word格式.docx
《51控制温度简单的PID算法Word格式.docx》由会员分享,可在线阅读,更多相关《51控制温度简单的PID算法Word格式.docx(14页珍藏版)》请在冰豆网上搜索。
//占空比调节参数
unsignedcharset_temper=35;
unsignedchartemper;
unsignedchari;
unsignedcharj=0;
unsignedints;
/***********************************************************
延时子程序,延时时间以12M晶振为准,延时时间为30us×
time
***********************************************************/
voiddelay(unsignedchartime)
{
unsignedcharm,n;
for(n=0;
nfor(m=0;
m<
2;
m++){}
}
写一位数据子程序
voidwrite_bit(unsignedcharbitval)
EA=0;
DQ=0;
/*拉低DQ以开始一个写时序*/
if(bitval==1)
_nop_();
DQ=1;
/*如要写1,则将总线置高*/
delay(5);
/*延时90us供DA18B20采样*/
/*释放DQ总线*/
_nop_();
EA=1;
写一字节数据子程序
voidwrite_byte(unsignedcharval)
unsignedchari;
unsignedchartemp;
TR0=0;
for(i=0;
i<
8;
i++)/*写一字节数据,一次写一位*/
temp=val>
>
i;
/*移位操作,将本次要写的位移到最低位*/
temp=temp&
1;
write_bit(temp);
/*向总线写该位*/
delay(7);
/*延时120us后*/
//TR0=1;
EA=1;
读一位数据子程序
unsignedcharread_bit()
unsignedchari,value_bit;
EA=0;
DQ=0;
/*拉低DQ,开始读时序*/
DQ=1;
/*释放总线*/
i++){}
value_bit=DQ;
return(value_bit);
读一字节数据子程序
unsignedcharread_byte()
unsignedchari,value=0;
i++)
if(read_bit())/*读一字节数据,一个时序中读一次,并作移位处理*/
value|=0x01<
delay(4);
/*延时80us以完成此次都时序,之后再读下一数据*/
return(value);
复位子程序
unsignedcharreset()
unsignedcharpresence;
/*拉低DQ总线开始复位*/
delay(30);
/*保持低电平480us*/
delay(3);
presence=DQ;
/*获取应答信号*/
delay(28);
/*延时以完成整个时序*/
return(presence);
/*返回应答信号,有芯片应答返回0,无芯片则返回1*/
获取温度子程序
voidget_temper()
unsignedchari,j;
do
i=reset();
/*复位*/
}while(i!
=0);
/*1为无反馈信号*/
i=0xcc;
/*发送设备定位命令*/
write_byte(i);
i=0x44;
/*发送开始转换命令*/
delay(180);
/*延时*/
/*设备定位*/
i=0xbe;
/*读出缓冲区内容*/
j=read_byte();
i=read_byte();
i=(i<
<
4)&
0x7f;
s=(unsignedint)(j&
0x0f);
//得到小数部分
s=(s*100)/16;
j=j>
4;
temper=i|j;
/*获取的温度放在temper中*/
/*====================================================================================================
InitializePIDStructure
=====================================================================================================*/
voidPIDInit(structPID*pp)
memset(pp,0,sizeof(structPID));
//全部初始化为0
PID计算部分
unsignedintPIDCalc(structPID*pp,unsignedintNextPoint)
unsignedintdError,Error;
Error=pp->
SetPoint-NextPoint;
//偏差
pp->
SumError+=Error;
//积分
dError=pp->
LastError-pp->
PrevError;
//当前微分
PrevError=pp->
LastError;
LastError=Error;
return(pp->
Proportion*Error//比例项
+pp->
Integral*pp->
SumError//积分项
Derivative*dError);
//微分项
温度比较处理子程序
voidcompare_temper()
if(set_temper>
temper)//是否设置的温度大于实际温度
if(set_temper-temper>
1)//设置的温度比实际的温度是否是大于1度
{
high_time=100;
//如果是,则全速加热
low_time=0;
}
else//如果是在1度范围内,则运行PID计算
for(i=0;
10;
get_temper();
//获取温度
rin=s;
//ReadInput
rout=PIDCalc(&
spid,rin);
//PerformPIDInteration
if(high_time<
=100)
high_time=(unsignedchar)(rout/800);
else
low_time=(100-high_time);
elseif(set_temper<
=temper)
if(temper-set_temper>
0)
high_time=0;
low_time=100;
100)
high_time=(unsignedchar)(rout/10000);
//else
//{}
/*****************************************************
T0中断服务子程序,用于控制电平的翻转,40us*100=4ms周期
******************************************************/
voidserve_T0()interrupt1using1
if(++count<
=(high_time))
output=1;
elseif(count<
output=0;
else
count=0;
TH0=0x2f;
TL0=0xe0;
串行口中断服务程序,用于上位机通讯
voidserve_sio()interrupt4using2
/*EA=0;
RI=0;
i=SBUF;
if(i==2)
while(RI==0){}
set_temper=SBUF;
SBUF=0x02;
while(TI==0){}
TI=0;
elseif(i==3)
SBUF=temper;
*/
voiddisp_1(unsignedchardisp_num1[6])
unsignedcharn,a,m;
for(n=0;
n<
6;
n++)
//k=disp_num1[n];
for(a=0;
a<
a++)
clk=0;
m=(disp_num1[n]&
1);
disp_num1[n]=disp_num1[n]>
if(m==1)
data1=1;
data1=0;
clk=1;
显示子程序
功能:
将占空比温度转化为单个字符,显示占空比和测得到的温度
voiddisplay()
unsignedcharcodenumber[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6};
unsignedchardisp_num[6];
unsignedintk,k1;
k=high_time;
k=k%1000;
k1=k/100;
if(k1==0)
disp_num[0]=0;
disp_num[0]=0x60;
k=k%100;
disp_num[1]=number[k/10];
disp_num[2]=number[k%10];
k=temper;
disp_num[3]=number[k/10];
disp_num[4]=number[k%10]+1;
disp_num[5]=number[s/10];
disp_1(disp_num);
主程序
voidmain()
unsignedcharz;
unsignedchara,b,flag_2=1,count1=0;
unsignedcharphil[]={2,0xce,0x6e,0x60,0x1c,2};
TMOD=0x21;
TL0=0x40;
SCON=0x50;
PCON=0x00;
TH1=0xfd;
TL1=0xfd;
PS=1;
EX1=0;
ET0=1;
ES=1;
TR0=1;
TR1=1;
high_time=50;
low_time=50;
PIDInit(&
spid);
//InitializeStructure
spid.Proportion=10;
//SetPIDCoefficients比例常数ProportionalConst
spid.Integral=8;
//积分常数IntegralConst
spid.Derivative=6;
//微分常数DerivativeConst
spid.SetPoint=100;
//SetPIDSetpoint设定目标DesiredValue
while
(1)
if(plus==0)
for(a=0;
5;
for(b=0;
b<
102;
b++){}
set_temper++;
flag=0;
elseif(subs==0)
if(subs==0)
set_temper--;
flag=0;
elseif(stop==0)
for(b=0;
if(stop==0)
break;
b=temper;
if(flag_2==1)
a=b;
if((abs(a-b))>
5)
temper=a;
temper=b;
a=temper;
flag_2=0;
if(++count1>
30)
display();
count1=0;
compare_temper();
z=1;
if(stop==0)
disp_1(phil);
//break;
}