微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 51 温度PID经典算法

51 温度PID经典算法

时间:11-11 来源:互联网 点击:
#include51.h>
#include
#include
#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|=0x01delay(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)); //全部初始化为0
}
/*====================================================================================================
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);//微分项
}
/***********************************************************
温度比较处理子程序
***********************************************************/
voidcompare_temper()
{
unsignedchari;
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;//ReadInput
rout=PIDCalc(&spid,rin);//PerformPIDInteration
}
if(high_time<=100)
high_time=(unsignedchar)(rout/800);
else
high_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;//ReadInput
rout=PIDCalc(&spid,rin);//PerformPIDInteration
}
if(high_time<100)
high_time=(unsignedchar)(rout/10000);
else
high_time=0;
low_time=(100-high_time);
}
}
//else
//{}
}
/*****************************************************
T0中断服务子程序,用于控制电平的翻转,40us*100=4ms周期
******************************************************/
voidserve_T0()
上一篇:使用AVR Studio+Winavr
下一篇:stm32之NVIC

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top