温度pid控制
#include "SST89x5x4.H" #include
#include
#include
sbit dp1=P2^4;
sbit dp2=P2^5;
sbit dp3=P2^6;
sbit dp4=P2^7;//数码管位选
sbit key1=P2^0;
sbit key2=P2^1;
sbit key3=P2^2;
sbit key4=P2^3;//按键位选
sbit P13=P1^3;//控制端口
sbit P34=P3^4;//测温DQ
sbit P35=P3^5;//发声端口
char dplib[11]={0x018,0x07B,0x02C,0x029,0x04B,0x089,0x088,0x03B,0x08,0x09,0x0EF};//数
码管
表
关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf
char dpbuf[4];//每个数码管显示的数字缓冲区
int t=0;//控制循环次数或标志位
int s0=0;//用于延时或循环或标志位
int s1=0;//用于延时或循环或标志位
unsigned char acc=0;//用于对温度芯片的读写操作
int high_time,low_time,count=0;//占空比调节参数 float temper;
int TTL=1,huansuan,TH1Z1,TL1Z1,TH1Z0,TL1Z0;//用于脉宽调制
int sign=0;//sign为1,则小数点显示,否则小数点不显示 int dnt=0;//用于位选挨个点亮
int cnt=0;//用于控制是否一直按着加键或者减键 int shujua;//读出温度数据的高位
int shujub;//温度低位
int zancun=0;//临时数据存放
int watchdog=0;//软件看门狗,无操作定时返回退出
/***********************************************************
PID类
***********************************************************/
struct PID {
int SetPoint; // 设定目标 Desired Value
int Proportion; // 比例常数 Proportional Const
int Integral; // 积分常数 Integral Const
int Derivative; // 微分常数 Derivative Const
float LastError; // Error[-1]
float PrevError; // Error[-2]
float SumError; // Sums of Errors };
struct PID spid; // PID Control Structure
float rout; // PID Response (Output)
float rin; // PID Feedback (Input)
void keyprogram();//键盘参数设置子程序
void observe();//运行中观察设置参数子程序
void settingmode();//选择要设定的参数子程序
void addmode();//参数加
void submode();//参数减
void displaysetting(int mode);//键盘操作时显示的设置
void INIT18B20();//初始芯片
void WRBYTE(unsigned char a);//写字
void RDBYTE( );//读字
void delay10ms(void);//10MS延时,用于显示2S
void get_temper();//温度测量子程序
void change(int a,int b);//对读出数据处理,与汇编原理一样
/***********************************************************
T0中断服务程序
***********************************************************/
void timer0(void)interrupt 1 using 2//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++)
{
case 0:
dp1=0;
break;
case 1:
dp2=0;
break;
case 2:
dp3=0;
break;
case 3:
dp4=0;
}
}
/***********************************************************
T1中断服务程序
***********************************************************/
void serve_T1() interrupt 3 using 3 //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;
else count++;
}
/*====================================================================
================================
初始化PID类
======================================================================
===============================*/
void PIDInit (struct PID *pp)
{
memset ( pp,0,sizeof(struct PID));
}
/*====================================================================
================================
PID计算部分
======================================================================
===============================*/
float PIDCalc( struct PID *pp, float NextPoint ) {
float dError,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); // 微分项
}
/***********************************************************
温度控制子程序
***********************************************************/
void control_temper()
{ if(spid.SetPoint-temper>4)
{
high_time=high_time+100;//高电平份数累加
}
else if(temper-spid.SetPoint>4)
{
high_time=high_time-110;//高电平份数累减
}
else if(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; }
/***********************************************************
温度测量子程序
***********************************************************/
void get_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
***********************************************************/
void INIT18B20() {
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写字
***********************************************************/
void WRBYTE(unsigned char a)
{
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读字
***********************************************************/
void RDBYTE( )
{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);
}
}
else if(t)
{
acc=(acc>>1);
}
}
}
/***********************************************************
处理从DS18B20上读到的数值子程序
***********************************************************/
void change(a,b)
{
int zheng;
int xiaoshu;
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);
}
}
/***********************************************************
延时子程序
***********************************************************/
void delay10ms(void)//10ms
{
unsigned char i0,j0;
for(i0=20;i0>0;i0--)
for(j0=248;j0>0;j0--);
}
/***********************************************************
参数设定子程序
***********************************************************/
void keyprogram()
{
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;
}
/***********************************************************
观察参数子程序
***********************************************************/
void observe()
{
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;
}
/***********************************************************
设置模式子程序
***********************************************************/
void settingmode()
{
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;
}
}
/***********************************************************
参数加子程序
***********************************************************/
void addmode()
{
delay10ms();
displaysetting(1);
if(key3==0)
{
if(cnt==0)
{
t=70;
while((--t)&&(!key3))
{ delay10ms();}
if(t==0)
cnt++;
zancun++;
}
else if(cnt<10)
{
cnt++;
t=30;
while(t--)
{ delay10ms();}
zancun++;
}
else if(cnt==19)
{cnt=19;
t=30;
while(t--)
{ delay10ms();}
zancun+=100;
}
else if(cnt>=10)
{
cnt++;
t=30;
while(t--)
{ delay10ms();}
zancun+=10;
}
}
if(dpbuf[3]==1)
{
if(zancun>100)
zancun=30;
}
else if(zancun>800)
zancun=0;
displaysetting(2); }
/***********************************************************
参数减子程序
***********************************************************/
void submode()
{
delay10ms();
displaysetting(1);
if(key4==0)
{
if(cnt==0)
{
t=75;
while((--t)&&(!key4))
{ delay10ms();}
if(t==0)
cnt++;
zancun--;
}
else if(cnt<10)
{
cnt++;
t=30;
while(t--)
{ delay10ms();}
zancun--;
}
else if(cnt==19)
{cnt=19;
t=30;
while(t--)
{ delay10ms();}
zancun-=100;
}
else if(cnt>=10)
{
cnt++;
t=30;
while(t--)
{ delay10ms();}
zancun-=10;
}
}
if(dpbuf[3]==1)
{
if(zancun<30)
zancun=100;
}
else if(zancun<0)
zancun=800;
displaysetting(2);
}
/***********************************************************
按键时显示设置子程序
***********************************************************/
void displaysetting(int mode) {
if(mode==1)
{
switch(dpbuf[3])
{
case 1:zancun=spid.SetPoint;break;
case 2:zancun=spid.Proportion;break;
case 3:zancun=spid.Integral;break;
case 4:zancun=spid.Derivative;
}
}
else {
switch(dpbuf[3])
{
case 1:spid.SetPoint=zancun;break;
case 2:spid.Proportion=zancun;break;
case 3:spid.Integral=zancun;break;
case 4:spid.Derivative=zancun;
}
dpbuf[2]=zancun/100;
zancun=zancun%100;
dpbuf[1]=zancun/10;
zancun=zancun%10;
dpbuf[0]=zancun;
}
watchdog=0;
}
/***********************************************************
主程序
***********************************************************/
void main()
{
dpbuf[0]=0;
dpbuf[1]=0;
dpbuf[2]=0;
dpbuf[3]=0;
TMOD=0X11;
TH0=0XEE;
TL0=0X00;
TH1=0x00;
TL1=0x00;
ET0=1;
ET1=1;
PT1=1;
PT0=0;
EA=1;
TR0=1;
TR1=1;
high_time=500;
low_time=500; PIDInit ( &spid ); spid.SetPoint=30; //初始化各个参数,定时器等 while(1)
{
keyprogram();
observe();
if(count==9)
{
get_temper();
control_temper();
}
}
}