温度pid控制.docx
《温度pid控制.docx》由会员分享,可在线阅读,更多相关《温度pid控制.docx(21页珍藏版)》请在冰豆网上搜索。
![温度pid控制.docx](https://file1.bdocx.com/fileroot1/2023-1/11/0cf4bba0-3af2-4f0a-87da-c6785c3071f2/0cf4bba0-3af2-4f0a-87da-c6785c3071f21.gif)
温度pid控制
温度pid控制
#include"SST89x5x4.H"#include#include
#include
sbitdp1=P2^4;
sbitdp2=P2^5;
sbitdp3=P2^6;
sbitdp4=P2^7;//数码管位选
sbitkey1=P2^0;
sbitkey2=P2^1;
sbitkey3=P2^2;
sbitkey4=P2^3;//按键位选
sbitP13=P1^3;//控制端口
sbitP34=P3^4;//测温DQ
sbitP35=P3^5;//发声端口
chardplib[11]={0x018,0x07B,0x02C,0x029,0x04B,0x089,0x088,0x03B,0x08,0x09,0x0EF};//数
码管表
chardpbuf[4];//每个数码管显示的数字缓冲区
intt=0;//控制循环次数或标志位
ints0=0;//用于延时或循环或标志位
ints1=0;//用于延时或循环或标志位
unsignedcharacc=0;//用于对温度芯片的读写操作
inthigh_time,low_time,count=0;//占空比调节参数floattemper;
intTTL=1,huansuan,TH1Z1,TL1Z1,TH1Z0,TL1Z0;//用于脉宽调制
intsign=0;//sign为1,则小数点显示,否则小数点不显示intdnt=0;//用于位选挨个点亮
intcnt=0;//用于控制是否一直按着加键或者减键intshujua;//读出温度数据的高位
intshujub;//温度低位
intzancun=0;//临时数据存放
intwatchdog=0;//软件看门狗,无操作定时返回退出
/***********************************************************
PID类
***********************************************************/
structPID{
intSetPoint;//设定目标DesiredValue
intProportion;//比例常数ProportionalConst
intIntegral;//积分常数IntegralConst
intDerivative;//微分常数DerivativeConst
floatLastError;//Error[-1]
floatPrevError;//Error[-2]
floatSumError;//SumsofErrors};
structPIDspid;//PIDControlStructure
floatrout;//PIDResponse(Output)
floatrin;//PIDFeedback(Input)
voidkeyprogram();//键盘参数设置子程序
voidobserve();//运行中观察设置参数子程序
voidsettingmode();//选择要设定的参数子程序
voidaddmode();//参数加
voidsubmode();//参数减
voiddisplaysetting(intmode);//键盘操作时显示的设置
voidINIT18B20();//初始芯片
voidWRBYTE(unsignedchara);//写字
voidRDBYTE();//读字
voiddelay10ms(void);//10MS延时,用于显示2S
voidget_temper();//温度测量子程序
voidchange(inta,intb);//对读出数据处理,与汇编原理一样
/***********************************************************
T0中断服务程序
***********************************************************/
voidtimer0(void)interrupt1using2//T0中断
{
TH0=0xEE;
TL0=0x00;
dp2=dp4=dp3=dp1=1;
if(dnt>3)
{dnt=0;}
if((dnt==1)&&(sign==1))
P0=dplib[dpbuf[dnt]]&0XF7;
else{
P0=dplib[dpbuf[dnt]];
watchdog++;
}
switch(dnt++)
{
case0:
dp1=0;
break;
case1:
dp2=0;
break;
case2:
dp3=0;
break;
case3:
dp4=0;
}
}
/***********************************************************
T1中断服务程序
***********************************************************/
voidserve_T1()interrupt3using3//T1
{
if(TTL==1)
{
P13=1;
TH1=TH1Z1;
TL1=TL1Z1;
TTL=0;
}
else{
P13=0;
TH1=TH1Z0;
TL1=TL1Z0;
TTL=1;
}
if(count==9)
count=0;
elsecount++;
}
/*====================================================================
================================
初始化PID类
======================================================================
===============================*/
voidPIDInit(structPID*pp)
{
memset(pp,0,sizeof(structPID));
}
/*====================================================================
================================
PID计算部分
======================================================================
===============================*/
floatPIDCalc(structPID*pp,floatNextPoint){
floatdError,Error;
Error=pp->SetPoint-NextPoint;//偏差
pp->SumError+=Error;//积分
dError=pp->LastError-pp->PrevError;//当前微分
pp->PrevError=pp->LastError;
pp->LastError=Error;
if(abs(spid.SetPoint-temper)<0.5)
pp->SumError=0;
return(pp->Proportion*Error//比例
+pp->Integral*pp->SumError//积分项
+pp->Derivative*dError);//微分项
}
/***********************************************************
温度控制子程序
***********************************************************/
voidcontrol_temper()
{if(spid.SetPoint-temper>4)
{
high_time=high_time+100;//高电平份数累加
}
elseif(temper-spid.SetPoint>4)
{
high_time=high_time-110;//高电平份数累减
}
elseif(abs(temper-spid.SetPoint)<4)
{
rin=temper;
rout=PIDCalc(&spid,rin);//进入PID计算
high_time=high_time+rout;
}
if(high_time>=1000)//防止过热过冷
high_time=999;
if(high_time<0)
high_time=1;
low_time=1000-high_time;//得到低电平份数
huansuan=65536-high_time*46;//换算得到T1定时器初值
TH1Z1=(huansuan&0xFF00>>8);
TL1Z1=huansuan&0x00FF;
huansuan=65536-low_time*46;
TH1Z0=(huansuan&0xFF00>>8);
TL1Z0=huansuan&0x00FF;}
/***********************************************************
温度测量子程序
***********************************************************/
voidget_temper()
{
EA=0;
INIT18B20();
acc=0xCC;
WRBYTE(acc);
acc=0x44;
WRBYTE(acc);
INIT18B20();
acc=0xCC;
WRBYTE(acc);
acc=0xBE;
WRBYTE(acc);
RDBYTE();
shujub=(int)acc;
RDBYTE();
shujua=(int)acc;
change(shujua,shujub);
EA=1;
}
/***********************************************************
初始化DS18B20
***********************************************************/
voidINIT18B20(){
t=4;
P34=0;
s0=62;
for(s0;s0>0;s0--);//延时500us
P34=1;
CY=0;
s0=6;
while(t--)
{
while(s0--)
{
if(P34==1)
{
t=0;
s1=1;
break;
}
}
}
if(s1==1)
{
s0=111;
while(s0--)
{
CY=CY|P34;
}
}
}
/***********************************************************
向DS18B20写字
***********************************************************/
voidWRBYTE(unsignedchara)
{
t=8;
CY=0;
while(t--)
{
a=(a>>1);
P34=0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
P34=CY;
s0=3;
for(s0;s0>0;s0--);
P34=1;
}
}
/***********************************************************
向DS18B20读字
***********************************************************/
voidRDBYTE()
{acc=0;
t=8;
while(t--)
{
P34=0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
P34=1;
CY=P34;
_nop_();
_nop_();
_nop_();
_nop_();
s0=5;
for(s0;s0>0;s0--);
P34=1;
if(CY==1)
{
acc=acc|0x80;
if(t)
{
acc=(acc>>1);
}
}
elseif(t)
{
acc=(acc>>1);
}
}
}
/***********************************************************
处理从DS18B20上读到的数值子程序
***********************************************************/
voidchange(a,b)
{
intzheng;
intxiaoshu;
zheng=((shujua&(0x07))<<4)+((shujub&(0xF0))>>4);//处理整数,转换BCD
temper=zheng;
xiaoshu=shujub&0x0F;//处理小数,转换BCD
zancun=((xiaoshu*10)&0xF0);
temper=temper+(float)(zancun>>4)/10;
if(sign==1)
{
dpbuf[3]=zheng/100;
zheng=zheng%100;
dpbuf[2]=zheng/10;
zheng=zheng%10;
dpbuf[1]=zheng;
dpbuf[0]=(zancun>>4);
}
}
/***********************************************************
延时子程序
***********************************************************/
voiddelay10ms(void)//10ms
{
unsignedchari0,j0;
for(i0=20;i0>0;i0--)
for(j0=248;j0>0;j0--);
}
/***********************************************************
参数设定子程序
***********************************************************/
voidkeyprogram()
{
if(key1==0)//判断是否进入设置
{//A
delay10ms();
if(key1==0)//进入设置了
{
P13=0;
while(!
key1);
sign=0;//B
dpbuf[2]=spid.SetPoint/100;
zancun=(int)spid.SetPoint%100;
dpbuf[1]=zancun/10;
zancun=zancun%10;
dpbuf[0]=zancun;
dpbuf[3]=1;//从模式一开始选择
while
(1)
{
if(key2==0)//判断是否进行参数选择
{
settingmode();//参数选择子程序
}
if(key3==0)//判断是否进行参数加
{
addmode();//参数加子程序
}
if(key4==0)//判断是否进行参数减减
{
submode();//参数减子程序
}
if(key1==0)//判断是否进行参数加加
{
delay10ms();
if(key1==0)
{while(!
key1);
break;
}
}
if((key3==1)&&(key4==1))//
{
delay10ms();
if((key3==1)&&(key4==1))
cnt=0;
}
if(watchdog==2000)
{
watchdog=0;
break;
}
}
}//B
}//A
watchdog=0;
sign=1;
}
/***********************************************************
观察参数子程序
***********************************************************/
voidobserve()
{
if(key4==0)//判断是否进入设置
{//A
delay10ms();
if(key4==0)//进入设置了
{
while(!
key4);
sign=0;//B
dpbuf[2]=spid.SetPoint/100;
zancun=(int)spid.SetPoint%100;
dpbuf[1]=zancun/10;
zancun=zancun%10;
dpbuf[0]=zancun;
dpbuf[3]=1;//从模式一开始观察
while
(1)
{
if(key2==0)//判断是否进行参数选择
{
settingmode();//参数选择子程序
}
if(key4==0)//判断是否结束观察
{
delay10ms();
if(key4==0)
{while(!
key4);
break;
}
}
if(watchdog==2000)
{
watchdog=0;
break;
}
if(count==10)
{
get_temper();//温度测量子程序
control_temper();//温度控制子程序
}
}
}//B
}//A
sign=1;
watchdog=0;
}
/***********************************************************
设置模式子程序
***********************************************************/
voidsettingmode()
{
delay10ms();
if(key2==0)//进入了模式选择
{
while(!
key2);
if(++dpbuf[3]==5)
{
dpbuf[3]=1;
}
displaysetting
(1);
dpbuf[2]=zancun/100;
zancun=zancun%100;
dpbuf[1]=zancun/10;
zancun=zancun%10;
dpbuf[0]=zancun;
}
}
/***********************************************************
参数加子程序
***********************************************************/
voidaddmode()
{
delay10ms();
displaysetting
(1);
if(key3==0)
{
if(cnt==0)
{
t=70;
while((--t)&&(!
key3))
{delay10ms();}
if(t==0)
cnt++;
zancun++;
}
elseif(cnt<10)
{
cnt++;
t=30;
while(t--)
{delay10ms();}
zancun++;
}
elseif(cnt==19)
{cnt=19;
t=30;
while(t--)
{delay10ms();}
zancun+=100;
}
elseif(cnt>=10)
{
cnt++;
t=30;
while(t--)
{delay10ms();}
zancun+=10;
}
}
if(dpbuf[3]==1)
{
if(zancun>100)
zancun=30;
}
elseif(zancun>800)
zancun=0;
displaysetting
(2);}
/***********************************************************
参数减子程序
***********************************************************/
voidsubmode()
{
delay10ms();
displaysetting
(1);
if(key4==0)
{
if(cnt==0)
{
t=75;
while((--t)&&(!
key4))
{delay10ms();}
if(t==0)
cnt++;
zancun--;
}
elseif(cnt<10)
{
cnt++;
t=30;
while(t--)
{delay10ms();}
zancun--;
}
elseif(cnt==19)
{cnt=19;
t=30;