pid温度参数整定.docx
《pid温度参数整定.docx》由会员分享,可在线阅读,更多相关《pid温度参数整定.docx(17页珍藏版)》请在冰豆网上搜索。
pid温度参数整定
我的题目是:
基于PID算法的温度控制系统
89C51单片机,通过键盘输入预设值,与DS18B20测得的实际值做比较,然后驱动制冷或加热电路。
用keilC语言来实现PID的控制。
最佳答案
//PID算法温控C语言2008-08-1718:
58
#include
structPID{
unsignedintSetPoint;//设定目标DesiredValue
unsignedintProportion;//比例常数ProportionalConst
unsignedintIntegral;//积分常数IntegralConst
unsignedintDerivative;//微分常数DerivativeConst
unsignedintLastError;//Error[-1]
unsignedintPrevError;//Error[-2]
unsignedintSumError;//SumsofErrors
};
structPIDspid;//PIDControlStructure
unsignedintrout;//PIDResponse(Output)
unsignedintrin;//PIDFeedback(Input)
sbitdata1=P1^0;
sbitclk=P1^1;
sbitplus=P2^0;
sbitsubs=P2^1;
sbitstop=P2^2;
sbitoutput=P3^4;
sbitDQ=P3^3;
unsignedcharflag,flag_1=0;
unsignedcharhigh_time,low_time,count=0;//占空比调节参数
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=1;/*释放DQ总线*/_nop_();_nop_();EA=1;}/***********************************************************写一字节数据子程序***********************************************************/voidwrite_byte(unsignedcharval){unsignedchari;unsignedchartemp;EA=0;/*关中断*/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,开始读时序*/_nop_();_nop_();DQ=1;/*释放总线*/for(i=0;i<2;i++){}value_bit=DQ;EA=1;return(value_bit);}/***********************************************************读一字节数据子程序***********************************************************/unsignedcharread_byte(){unsignedchari,value=0;EA=0;for(i=0;i<8;i++){if(read_bit())/*读一字节数据,一个时序中读一次,并作移位处理*/value|=0x01<delay(4);/*延时80us以完成此次都时序,之后再读下一数据*/}EA=1;return(value);}/***********************************************************复位子程序***********************************************************/unsignedcharreset(){unsignedcharpresence;EA=0;DQ=0;/*拉低DQ总线开始复位*/delay(30);/*保持低电平480us*/DQ=1;/*释放总线*/delay(3);presence=DQ;/*获取应答信号*/delay(28);/*延时以完成整个时序*/EA=1;return(presence);/*返回应答信号,有芯片应答返回0,无芯片则返回1*/}/***********************************************************获取温度子程序***********************************************************/voidget_temper(){unsignedchari,j;do{i=reset();/*复位*/}while(i!=0);/*1为无反馈信号*/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=(unsignedint)(j&0x0f);s=(s*100)/16;j=j>>4;temper=i|j;/*获取的温度放在temper中*/}/*====================================================================================================InitializePIDStructure=====================================================================================================*/voidPIDInit(structPID*pp){memset(pp,0,sizeof(structPID));}/*====================================================================================================PID计算部分=====================================================================================================*/unsignedintPIDCalc(structPID*pp,unsignedintNextPoint){unsignedintdError,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(){unsignedchari;if(set_temper>temper){if(set_temper-temper>1){high_time=100;low_time=0;}else{for(i=0;i<10;i++){get_temper();rin=s;//ReadInputrout=PIDCalc(&spid,rin);//PerformPIDInteration}if(high_time<=100)high_time=(unsignedchar)(rout/800);elsehigh_time=100;low_time=(100-high_time);}}elseif(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;//ReadInputrout=PIDCalc(&spid,rin);//PerformPIDInteration}if(high_time<100)high_time=(unsignedchar)(rout/10000);elsehigh_time=0;low_time=(100-high_time);}}//else//{}}/*****************************************************T0中断服务子程序,用于控制电平的翻转,40us*100=4ms周期******************************************************/voidserve_T0()interrupt1using1{if(++count<=(high_time))output=1;elseif(count<=100){output=0;}elsecount=0;TH0=0x2f;TL0=0xe0;}/*****************************************************串行口中断服务程序,用于上位机通讯******************************************************/voidserve_sio()interrupt4using2{/*EA=0;RI=0;i=SBUF;if(i==2){while(RI==0){}RI=0;set_temper=SBUF;SBUF=0x02;while(TI==0){}TI=0;}elseif(i==3){TI=0;SBUF=temper;while(TI==0){}TI=0;}EA=1;*/}voiddisp_1(unsignedchardisp_num1[6]){unsignedcharn,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;elsedata1=0;_nop_();clk=1;_nop_();}}}/*****************************************************显示子程序功能:将占空比温度转化为单个字符,显示占空比和测得到的温度******************************************************/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;elsedisp_num[0]=0x60;k=k%100;disp_num[1]=number[k/10];disp_num[2]=number[k%10];k=temper;k=k%100;disp_num[3]=number[k/10];disp_num[4]=number[k%10]+1;disp_num[5]=number[s/10];disp_1(disp_num);}/***********************************************************主程序***********************************************************/main(){unsignedcharz;unsignedchara,b,flag_2=1,count1=0;unsignedcharphil[]={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);//InitializeStructurespid.Proportion=10;//SetPIDCoefficientsspid.Integral=8;spid.Derivative=6;spid.SetPoint=100;//SetPIDSetpointwhile(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;}}elseif(subs==0){for(a=0;a<5;a++)for(b=0;a<102;b++){}if(subs==0){set_temper--;flag=0;}}elseif(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;elsetemper=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;}}//DS18b20子程序#includesbitDQ=P2^1;//定义端口typedefunsignedcharbyte;typedefunsignedintword;//延时voiddelay(worduseconds){for(;useconds>0;useconds--);}//复位byteow_reset(void){bytepresence;DQ=0;//DQ低电平delay(29);//480usDQ=1;//DQ高电平delay(3);//等待presence=DQ;//presence信号delay(25);return(presence);}//0允许,1禁止//从1-wire总线上读取一个字节byteread_byte(viod){bytei;bytevalue=0;for(i=8;i>0;i--){value>>=1;DQ=0;DQ=1;delay(1);if(DQ)value|=0x80;delay(6);}return(value);}//向1-wire总线上写一个字节voidwrite_byte(charval){bytei;for(i=8;i>0;i--)//一次写一个字节{DQ=0;DQ=val&0x01;delay(5);DQ=1;val=val/2;}delay(5);}//读取温度charRead_Temperature(void){union{bytec[2];intx;}temp;ow_reset();write_byte(0xcc);write_byte(0xBE);temp.c[1]=read_byte();temp.c[0]=read_byte();ow_reset();write_byte(0xCC);write_byte(0x44);returntemp.x/2;}
for(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=1;/*释放DQ总线*/
EA=1;
写一字节数据子程序
voidwrite_byte(unsignedcharval)
unsignedchartemp;
EA=0;/*关中断*/
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;
DQ=0;/*拉低DQ,开始读时序*/
DQ=1;/*释放总线*/
for(i=0;i<2;i++){}
value_bit=DQ;
return(value_bit);
读一字节数据子程序
unsignedcharread_byte()
unsignedchari,value=0;
for(i=0;i<8;i++)
if(read_bit())/*读一字节数据,一个时序中读一次,并作移位处理*/
value|=0x01<
delay(4);/*延时80us以完成此次都时序,之后再读下一数据*/
return(value);
复位子程序
unsignedcharreset()
unsignedcharpresence;
DQ=0;/*拉低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);/*延时*/
=0);
i=0xcc;/*设备定位*/
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));
PID计算部分
unsignedintPIDCalc(structPID*pp,unsignedintNextPoint)
unsignedintdError,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>1)
high_time=100;
low_time=0;
else
for(i=0;i<10;i++)
{get_temper();
rin=s;//ReadInput
rout=PIDCalc(&spid,rin);//PerformPIDInteration
if(high_time<=100)
high_time=(unsignedchar)(rout/800);
low_time=(100-high_time);
elseif(set_temper<=temper)
if(temper-set_temper>0)
high_time=0;
low_time=100;
if(high_time<100)
high_time=(unsignedchar)(rout/10000);
//else
//{}
/*****************************************************
T0中断服务子程序,用于控制电平的翻转,40us*100=4ms周期
******************************************************/
voidserve_T0()interrupt1using1
if(++count<=(high_time))
output=1;
elseif(count<=100)
output=0;
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;
EA=1;*/
voiddisp_1(unsignedchardisp_num1[6])
unsignedcharn,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;
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);
主程序
main()
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
spid.Integral=8;
spid.Derivative=6;
spid.SetPoint=100;//SetPIDSetpoint
while
(1)
if(plus==0)
for(a=0;a<5;a++)
for(b=0;b<102;b++){}
set_temper++;
flag=0;
elseif(subs==0)
for(b=0;a<102;b++){}
if(subs==0)
set_temper--;
elseif(stop==0)
if(stop==0)
break;
get_temper();
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;
disp_1(phil);
//break;
//DS18b20子程序
sbitDQ=P2^1;//定义端口
typedefunsignedcharbyte;
typedefunsignedintword;
//延时
voiddelay(worduseconds)
for(;useconds>0;useconds--);
//复位
byteow_reset(void)
bytepresence;
DQ=0;//DQ低电平
delay(29);//480us
DQ=1;//DQ高电平
delay(3);//等待
presence=DQ;//presence信号
delay(25);
return(presence);
}//0允许,1禁止
//从1-wire总线上读取一个字节
byteread_byte(viod)
bytei;
bytevalue=0;
for(i=8;i>0;i--)
value>>=1;
DQ=0;
DQ=1;
delay
(1);
if(DQ)value|=0x80;
delay(6);
//向1-wire总线上写一个字节
voidwrite_byte(charval)
for(i=8;i>0;i--)//一次写一个字节
DQ=val&0x01;
delay(5);
val=val/2;
//读取温度
charRead_Temperature(void)
union{
bytec[2];
intx;
}temp;
ow_reset();
write_byte(0xcc);
write_byte(0xBE);
temp.c[1]=read_byte();
temp.c[0]=read_byte();
write_byte(0xCC);
write_byte(0x44);
returntemp.x/2;
下载文档到电脑,查找使用更方便
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
copyright@ 2008-2022 冰点文档网站版权所有
经营许可证编号:鄂ICP备2022015515号-1