视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
pid温度控制C程序
2025-09-27 23:39:57 责编:小OO
文档
PID温度控制程序

//PID算法温控C语言2008-08-17 18:58

#include

#include

#include

#include

struct PID { 

unsigned int SetPoint; // 设定目标 Desired Value 

unsigned int Proportion; // 比例常数 Proportional Const 

unsigned int Integral; // 积分常数 Integral Const 

unsigned int Derivative; // 微分常数 Derivative Const 

unsigned int LastError; // Error[-1] 

unsigned int PrevError; // Error[-2] 

unsigned int SumError; // Sums of Errors 

}; 

struct PID spid; // PID Control Structure 

unsigned int rout; // PID Response (Output) 

unsigned int rin; // PID Feedback (Input) 

sbit data1=P1^0; 

sbit clk=P1^1; 

sbit plus=P2^0; 

sbit subs=P2^1; 

sbit stop=P2^2; 

sbit output=P3^4; 

sbit DQ=P3^3; 

unsigned char flag,flag_1=0; 

unsigned char high_time,low_time,count=0;//占空比调节参数 

unsigned char set_temper=35; 

unsigned char temper; 

unsigned char i; 

unsigned char j=0; 

unsigned int s; 

/*********************************************************** 

延时子程序,延时时间以12M晶振为准,延时时间为30us×time 

***********************************************************/ 

void delay(unsigned char time) 

unsigned char m,n; 

for(n=0;nfor(m=0;m<2;m++){}

/*********************************************************** 

写一位数据子程序 

***********************************************************/ 

void write_bit(unsigned char bitval) 

EA=0; 

DQ=0; /*拉低DQ以开始一个写时序*/ 

if(bitval==1) 

_nop_(); 

DQ=1; /*如要写1,则将总线置高*/ 

delay(5); /*延时90us供DA18B20采样*/ 

DQ=1; /*释放DQ总线*/ 

_nop_(); 

_nop_(); 

EA=1; 

/*********************************************************** 

写一字节数据子程序 

***********************************************************/ 

void write_byte(unsigned char val) 

unsigned char i; 

unsigned char temp; 

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; /*开中断*/

/*********************************************************** 

读一位数据子程序 

***********************************************************/ 

unsigned char read_bit() 

unsigned char i,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); 

/*********************************************************** 

读一字节数据子程序 

***********************************************************/ 

unsigned char read_byte() 

unsigned char i,value=0; 

EA=0; 

for(i=0;i<8;i++)

if(read_bit()) /*读一字节数据,一个时序中读一次,并作移位处理*/ 

value|=0x01<delay(4); /*延时80us以完成此次都时序,之后再读下一数据*/ 

EA=1; 

return(value); 

/*********************************************************** 

复位子程序 

***********************************************************/ 

unsigned char reset() 

unsigned char presence; 

EA=0; 

DQ=0; /*拉低DQ总线开始复位*/ 

delay(30); /*保持低电平480us*/ 

DQ=1; /*释放总线*/ 

delay(3); 

presence=DQ; /*获取应答信号*/ 

delay(28); /*延时以完成整个时序*/ 

EA=1; 

return(presence); /*返回应答信号,有芯片应答返回0,无芯片则返回1*/ 

/*********************************************************** 

获取温度子程序 

***********************************************************/ 

void get_temper() 

unsigned char i,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=(unsigned int)(j&0x0f); 

s=(s*100)/16; 

j=j>>4;

temper=i|j; /*获取的温度放在temper中*/ 

/*==================================================================================================== 

Initialize PID Structure 

=====================================================================================================*/ 

void PIDInit (struct PID *pp) 

memset ( pp,0,sizeof(struct PID)); 

/*==================================================================================================== 

PID计算部分 

=====================================================================================================*/ 

unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint ) 

unsigned int dError,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() 

unsigned char i; 

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; // Read Input 

rout = PIDCalc ( &spid,rin ); // Perform PID Interation 

if (high_time<=100)

high_time=(unsigned char)(rout/800); 

else 

high_time=100; 

low_time= (100-high_time); 

else if(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; // Read Input 

rout = PIDCalc ( &spid,rin ); // Perform PID Interation 

if (high_time<100)

high_time=(unsigned char)(rout/10000); 

else 

high_time=0; 

low_time= (100-high_time); 

// else 

// {} 

/***************************************************** 

T0中断服务子程序,用于控制电平的翻转 ,40us*100=4ms周期 

******************************************************/ 

void serve_T0() interrupt 1 using 1 

if(++count<=(high_time))

output=1; 

else if(count<=100)

output=0; 

else 

count=0; 

TH0=0x2f; 

TL0=0xe0; 

/***************************************************** 

串行口中断服务程序,用于上位机通讯 

******************************************************/ 

void serve_sio() interrupt 4 using 2 

/* EA=0; 

RI=0; 

i=SBUF; 

if(i==2) 

while(RI==0){} 

RI=0; 

set_temper=SBUF; 

SBUF=0x02; 

while(TI==0){} 

TI=0; 

else if(i==3) 

TI=0; 

SBUF=temper; 

while(TI==0){} 

TI=0; 

EA=1; */ 

void disp_1(unsigned char disp_num1[6]) 

unsigned char n,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; 

else 

data1=0; 

_nop_(); 

clk=1; 

_nop_(); 

/***************************************************** 

显示子程序 

功能:将占空比温度转化为单个字符,显示占空比和测得到的温度 

******************************************************/ 

void display() 

unsigned char code number[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6}; 

unsigned char disp_num[6]; 

unsigned int k,k1; 

k=high_time; 

k=k%1000; 

k1=k/100; 

if(k1==0) 

disp_num[0]=0; 

else 

disp_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() 

unsigned char z; 

unsigned char a,b,flag_2=1,count1=0; 

unsigned char phil[]={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 ); // Initialize Structure 

spid.Proportion = 10; // Set PID Coefficients 

spid.Integral = 8; 

spid.Derivative =6; 

spid.SetPoint = 100; // Set PID Setpoint 

while(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; 

else if(subs==0) 

for(a=0;a<5;a++)

for(b=0;a<102;b++){}

if(subs==0) 

set_temper--; 

flag=0; 

else if(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; 

else 

temper=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; 

下载本文

显示全文
专题