×
单片机 > 单片机程序设计 > 详情

单片机PID温控源代码

发布时间:2020-06-23 发布时间:
|
/*=============================================
                                               CopyLeft(CL) FORVERE Wjj
                                                  All rights NOT reserved
                                       版权所无,翻版不究,但请保留此处信息
                                       http://blog.sina.com.cn/u/2150397142  
                       any problem or suggestion mail to:  15258297408@163.com
*******************************************/
*文件名:PID_control
*文件说明:PID温控源代码,采用PID算法处理的温控模拟系统 ,ADC0809采集数据,IN4148为温度传感器
*版本:  The final version
*芯片:  STC89C52RC
*晶振:  (外)内部12MHz晶振
*作者:  Wang Jian Jun
*日期:  2010年5月27日 
*编译环境: keil3+proteus7
*结果:  实物测试通过,温度维持在33℃-35℃
*说明:   采用PID算法处理的温控模拟系统 ,ADC0809采集数据,IN4148为温度传感器,LCD显示

========================================*/
#include     //加载C51核心库文件
#include   //加载应用型库文件
#include"config.h"    //加载用户自配置可文件,此处未给出
#define N0 40536
#define nop() _nop_()
#define uchar unsigned char
#define uint unsigned int     //以上宏定义,方便写代码

/*程序中变量 数组定义*/
uchar idata table[]={"Real-time Temp:"};   //第一行显示"Real-time Temp:"
uchar idata table1[5];
uchar data1;
uchar kp;
uchar ki;
uchar kd;    //以上为PID算法的比例,积分,微分系数 
uint t,hightime,count;  //占空比调节参数
uint rltemp,settemp=350;
int e1,e2,e3,duk,uk;

/*引脚定义*/
sbit EOC=P2^6;
sbit OE=P2^5;
sbit START=P2^7;
sbit lcden=P3^2;
sbit lcdrw=P3^1;
sbit lcdrs=P3^0;
sbit pwm=P3^3;

/******************************
         延时子程序
*******************************/
void delay(uint z)
{    
uint x,y;
for(x=z;x>0;x--)
for(y=29;y>0;y--);
}

/******************************
         LCD忙检测
*******************************/
bit lcd_busy()
{
bit result;
lcdrw = 1;
lcdrs = 0;
lcden = 1;
nop();nop();nop();nop();
result = (bit)(P0&0x80);
lcden = 0;
return(result);
}

/******************************
      LCD写命令子程序
*******************************/
void write_com(uchar com)
{
    while(lcd_busy());//忙等待
lcdrs = 0;
lcdrw = 0;
P1 = com;
delay(5);
lcden = 1;
delay(5);
lcden = 0;
}

/******************************
      LCD写数据子程序
*******************************/
void write_data(uchar date)
{
    while(lcd_busy()); //忙等待
lcdrs = 1;
lcdrw = 0;
P1=date;
delay(5);
lcden = 1;
delay(5);
lcden = 0;
}

/******************************
         LCD初始化
*******************************/
void lcd_init()
{
lcden = 0;
write_com(0x38);
delay(5);
write_com(0x0f);
delay(5);
write_com(0x06);
delay(5);
write_com(0x01);
delay(5);
write_com(0x80);
delay(5);
write_com(0x01);
}

/******************************
      定时器初始化
*******************************/
void time_init() 
{
EA = 1;
ET0 = 1;
ET1 = 1;
TR0 = 1;
TR1 = 1;
TMOD = 0x11;
    TH0 = N0/256;
    TL0 = N0%256;
TH1 = 0X3C;
TL1 = 0XB0;
}

/******************************
     PID算法系数设置
*******************************/
void Pid_init()
{
hightime= 0;
e1 = 0;
e2 = 0;
e3 = 0;
kp = 10;
ki = 5;
kd = 5;
}

/******************************
     温度比较  PID算法
*******************************/
void pid_ys()
{
if(rltemp {
  if(settemp-rltemp>20) // 如果相差2度
  {
   hightime=100;  //全速加热
  }
  else       //否则运行PID算法进行平滑加热
  {       
   e1 = settemp-rltemp;
   duk=(kp*(e1-e2)+ki*e1+kd*(e1-e2*2+e3))/10;
   uk = uk+duk;
   if(uk>100)
   uk = 100;
   else if(uk   uk = -100;
   if(uk<0)
   {
    hightime=-uk;
   }
   else
   {
    hightime=uk;
   }
   e3 = e2;
   e2 = e1;
  }
}
if(rltemp>=settemp) // 如果实际温度大于设定值
{
  if(rltemp-settemp>0)  //只要实际温度与设定值有偏差
  {
   hightime=0;    //停止加热
  }
  else      //其他情况运行PID算法,但参数与前面的刚好相反
  {
   e1 = rltemp-settemp;
   duk=(kp*(e1-e2)+ki*e1+kd*(e1-e2*2+e3))/10;
   uk = uk+duk;
   if(uk>100)
   uk = 100;
   else if(uk   uk = -100;
   if(uk<0)
   {
    hightime=100-(-uk);
   }
   else
   {
    hightime=100-uk;
   }
   e3 = e2;
   e2 = e1;
  }
}

}

/******************************
           主函数
*******************************/
void main()
{
    uint i;
time_init();//定时器初始化
Pid_init(); // PID初始化
lcd_init(); // LCD初始化
table1[5]=0x43;
table1[4]=0xdf;
table1[2]=0x2e; //小数点 摄氏度符号ASCII码
    for(i=0;i<15;i++)  //带循环第一行显示"Real-time Temp:"
    {   
  write_data(table[i]);
  delay(20);
}
while(1)
{
     t=data1*196/100;
  table1[3]=(t%100)%10+0x30;
  table1[1]=(t%100)/10+0x30;
  table1[0]=t/100+0x30; //以上温度数据转化
  rltemp = t;  //给PID算法装载实际值
     write_com(0x80+0x45);//写LCD第二行的初地址
  for(i=0;i<6;i++) //该循环显示温度值
  {
   write_data(table1[i]);
   delay(20);
  }
  pid_ys();//运行温度比较 PID算法
}
}

/******************************
   温度采集转换的定时中断
     0.5s刷新一次数据
*******************************/
void  timer0() interrupt 1
{
    uint j;
j++;
if(j==20)
{
  OE = 0;
  START = 0;
  _nop_();
  START = 1;
  _nop_();
  START = 0; 
  while(EOC==0);
  OE = 1;
  _nop_();
  data1 = P0;
  _nop_();
  OE = 0;
  j = 0;
    }
    TH0=N0/256;
    TL0=N0%256;
}

/******************************
     PWM波输出的定时中断
*******************************/
void  timer1() interrupt 3
{
if(++count<=(hightime))
  pwm=0;
else if(count<=100)
{
  pwm=1;
}
else
  count=0;
TH1=0x3c;
TL1=0xb0;
}

/*==============================end of file=======================================*/
关键字:单片机  PID温控  STC89C52RC 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
AVR熔丝位操作时的要点和需要注意的相关事项