📄 叶风 - 利用pid算法和pwm调制实现温度自动控制的源程序.htm
字号:
delay(5); /*延时90us供DA18B20采样*/<BR>
DQ=1; /*释放DQ总线*/<BR>
_nop_();<BR> _nop_();<BR>
EA=1;<BR>
}<BR>/***********************************************************<BR>写一字节数据子程序<BR>***********************************************************/<BR>void
write_byte(unsigned char val)<BR> {<BR> unsigned char
i;<BR> unsigned char temp;<BR> EA=0;<BR>
TR0=0;<BR>
for(i=0;i<8;i++) /*写一字节数据,一次写一位*/<BR>
{<BR>
temp=val>>i; /*移位操作,将本次要写的位移到最低位*/<BR>
temp=temp&1;<BR>
write_bit(temp); /*向总线写该位*/<BR>
}<BR>
delay(7); /*延时120us后*/<BR> // TR0=1;<BR>
EA=1;<BR>
}<BR>/***********************************************************<BR>读一位数据子程序<BR>***********************************************************/<BR>unsigned
char read_bit()<BR> {<BR> unsigned char
i,value_bit;<BR> EA=0;<BR>
DQ=0; /*拉低DQ,开始读时序*/<BR> _nop_();<BR>
_nop_();<BR> DQ=1; /*释放总线*/<BR>
for(i=0;i<2;i++){} </P>
<P> value_bit=DQ;<BR> EA=1;<BR>
return(value_bit);<BR>
}<BR>/***********************************************************<BR>读一字节数据子程序<BR>***********************************************************/<BR>unsigned
char read_byte()<BR> {<BR> unsigned char
i,value=0;<BR> EA=0;<BR>
for(i=0;i<8;i++)<BR>
{<BR>
if(read_bit()) /*读一字节数据,一个时序中读一次,并作移位处理*/<BR>
value|=0x01<<i;<BR>
delay(4); /*延时80us以完成此次都时序,之后再读下一数据*/<BR>
}<BR> EA=1;<BR> return(value);<BR>
}<BR>/***********************************************************<BR>复位子程序<BR>***********************************************************/<BR>unsigned
char reset()<BR> {<BR> unsigned char
presence;<BR> EA=0;<BR>
DQ=0; /*拉低DQ总线开始复位*/<BR>
delay(30); /*保持低电平480us*/<BR>
DQ=1; /*释放总线*/<BR>
delay(3); </P>
<P>
presence=DQ; /*获取应答信号*/<BR>
delay(28); /*延时以完成整个时序*/<BR>
EA=1;<BR>
return(presence); /*返回应答信号,有芯片应答返回0,无芯片则返回1*/<BR>
}<BR>/***********************************************************<BR>获取温度子程序<BR>***********************************************************/<BR>void
get_temper()<BR> {<BR> unsigned char i,j;<BR>
do<BR> {<BR>
i=reset(); /*复位*/<BR>
}while(i!=0); /*1为无反馈信号*/<BR>
i=0xcc; /*发送设备定位命令*/<BR> write_byte(i);<BR>
i=0x44; /*发送开始转换命令*/<BR> write_byte(i);<BR>
delay(180); /*延时*/<BR> do<BR> {<BR>
i=reset(); /*复位*/<BR>
}while(i!=0); <BR>
i=0xcc; /*设备定位*/<BR> write_byte(i);<BR>
i=0xbe; /*读出缓冲区内容*/<BR> write_byte(i);<BR>
j=read_byte(); <BR>
i=read_byte(); <BR>
i=(i<<4)&0x7f; <BR> s=(unsigned
int)(j&0x0f);<BR> s=(s*100)/16;<BR>
j=j>>4;<BR> temper=i|j;<BR>
}<BR>/*====================================================================================================<BR>Initialize
PID
Structure<BR>=====================================================================================================*/<BR>void
PIDInit (struct PID *pp)<BR>{<BR> memset ( pp,0,sizeof(struct
PID));<BR>}<BR>/*====================================================================================================<BR>PID计算部分<BR>=====================================================================================================*/</P>
<P>unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint
)<BR>{<BR>unsigned int dError,Error;</P>
<P>Error = pp->SetPoint - NextPoint; // 偏差<BR>pp->SumError +=
Error; // 积分<BR>dError = pp->LastError - pp->PrevError; //
当前微分<BR>pp->PrevError = pp->LastError;<BR>pp->LastError =
Error;<BR>return (pp->Proportion * Error // 比例项<BR>+
pp->Integral * pp->SumError // 积分项<BR>+ pp->Derivative *
dError); // 微分项<BR>}</P>
<P>/***********************************************************<BR>温度比较处理子程序<BR>***********************************************************/<BR>compare_temper()<BR>{<BR>
unsigned char i;<BR>
if(set_temper>temper)<BR>
{<BR>
if(set_temper-temper>1) <BR>
{<BR>
high_time=100;<BR>
low_time=0;<BR>
}<BR>
else<BR>
{<BR>
for(i=0;i<10;i++)<BR>
{
get_temper();<BR>
rin = s; // Read
Input<BR>
rout = PIDCalc ( &spid,rin ); // Perform PID
Interation<BR>
}<BR>
if
(high_time<=100)<BR>
high_time=(unsigned
char)(rout/800);<BR>
else<BR>
high_time=100;<BR>
low_time=
(100-high_time);<BR>
}<BR>
}<BR> else
if(set_temper<=temper)<BR>
{<BR>
if(temper-set_temper>0)<BR>
{<BR>
high_time=0;<BR>
low_time=100;<BR>
}<BR>
else<BR>
{<BR>
for(i=0;i<10;i++)<BR>
{
get_temper();<BR>
rin = s; // Read
Input<BR>
rout = PIDCalc ( &spid,rin ); // Perform PID
Interation<BR>
}<BR>
if
(high_time<100)<BR>
high_time=(unsigned
char)(rout/10000);<BR>
else<BR>
high_time=0;<BR>
low_time=
(100-high_time);<BR>
}<BR>
}<BR> //
else<BR> //
{}<BR>
}<BR>/*****************************************************<BR>T0中断服务子程序,用于控制电平的翻转 ,40us*100=4ms周期<BR>******************************************************/<BR>void
serve_T0() interrupt 1 using 1<BR> {<BR>
if(++count<=(high_time))<BR>
output=1;<BR> else
if(count<=100)<BR>
{<BR>
output=0;<BR> }<BR>
else<BR> count=0;<BR>
TH0=0x2f;<BR> TL0=0xe0;<BR>
}<BR>/*****************************************************<BR>串行口中断服务程序,用于上位机通讯<BR>******************************************************/<BR>void
serve_sio() interrupt 4 using 2<BR> {<BR>/*
EA=0;<BR> RI=0; <BR>
i=SBUF;<BR> if(i==2)<BR>
{<BR>
while(RI==0){} <BR>
RI=0;<BR>
set_temper=SBUF; <BR>
SBUF=0x02; <BR>
while(TI==0){}<BR>
TI=0;<BR>
}<BR> else
if(i==3) <BR>
{<BR>
TI=0;<BR>
SBUF=temper;<BR>
while(TI==0){}<BR>
TI=0;<BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -