|  | 
 
| 51单片机温度PID控制程序1602显示 以下是部分代码
 
 复制代码/******************************************************************
Main.C  file
作者:颜强
建立日期: 2011.12.23
版本:V1.0
Copyright(C) bg8wj
/*******************************************************************/
#include "ioconfig.h" 
#include "includes.h"
#include "datacomm.h"
/************************************************
              PID函数
*************************************************/ 
void PIDInit (struct PID *pp) 
{ 
  memset ( pp,0,sizeof(struct PID)); 
} 
/************************************************
              增量控制PID函数体 
51单片机最不擅长浮点数计算,转换成int型计算
*************************************************/
unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint ) 
{ 
  unsigned int dError,Error,pError; 
  //增量法计算公式:
  //Pdt=Kp*[E(t)-E(t-1)]+Ki*E(t)+Kd*[E(t)-2*E(t-1)+E(t-2)]
  Error = set_temper - NextPoint;       // 偏差E(t) 
  pError=Error-pp->LastError;         //E(t)-E(t-1)
  dError=Error-2*pp->LastError+pp->PrevError; //E(t)-2*E(t-1)+E(t-2) 
  pp->PrevError = pp->LastError; 
  pp->LastError = Error; 
  return ( 
            pp->Proportion * pError        //比例 
            + pp->Integral *Error  //积分项 
            + pp->Derivative * dError          // 微分项
                        );  
} 
/************************************************
                                PID函数初始化
*************************************************/
void PIDBEGIN() 
{ 
  PIDInit(&spid); // Initialize Structure 
  spid.Proportion = 10; // Set PID Coefficients 
  spid.Integral = 5; 
  spid.Derivative =4; 
}
/************************************************
                         实时温度读取函数
从DS18b20中读取实时温度
返回值放大10倍便于PID计算
*************************************************/
int ReadTemperature(void)
{
        unsigned char TPL=0;
        unsigned char TPH=0;
        unsigned int temperture=0;
        //EA = 0;                 
        Init_DS18B20();
        WriteOneChar(0xCC); //跳过读序号列号的操作
        WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
        TPL=ReadOneChar();        //读温度低字节
        TPH=ReadOneChar();        //读温度高字节
        //启动下一次温度转换
        Init_DS18B20();
        WriteOneChar(0xCC); // 跳过读序号列号的操作
        WriteOneChar(0x44); // 启动温度转换
         //temperture=(TPH*256+TPL)*0.0625   //真实温度值 范围(+125,-55)
        if(TPH&0xfc)
         {
           tp_flag=1;    //负温度标记
           temperture=((TPH<<8)|TPL);
           temperture=((~temperture)+1);
           temperture*=0.625+0.5;
         }
        else
         {
           tp_flag=0;
           //temperture=((TPH<<8)|TPL)*0.0625 //温度输出值范围(125.00,-55.00)
           temperture=((TPH<<8)|TPL)*0.625+0.5;//温度值放大10倍 范围(+1250.00,-550.00)
         }                                                                        //         +0.5四舍五入 精度只到小数后一位
        return(temperture);         
}
/************************************************
                                  lcd1602显示函数
*************************************************/
void xianshi(void)
{
    LCD_Write_String(0,0,"NOW TMP:");
        LCD_Write_String(0,1,"SET TMP:");
}
/************************************************
                        lcd1602显示实时温度
*************************************************/
void view(unsigned int tmp)
{
        LCD_Write_Char(15,0,'C');
        LCD_Write_Char(14,0,0xdf);//摄氏温度符号
        LCD_Write_Char(13,0,zhi[tmp%10]);//小数点后第1位
        LCD_Write_Char(12,0,'.');                 
        LCD_Write_Char(11,0,zhi[tmp%100/10]);//        个位
        LCD_Write_Char(10,0,zhi[tmp/100]);         //十位
        if(0==tmp/1000)LCD_Write_Char(9,0,' ');//百位 如果为零显示空格
        else
         LCD_Write_Char(9,0,zhi[tmp/1000]);
        if(1==tp_flag)LCD_Write_Char(8,0,'-');//正负温度符号显示 负温度显示- 0上显示空格
         else
         LCD_Write_Char(8,0,' ');
}
/*********************************************************** 
             PID温度控制做动函数
***********************************************************/ 
void compare_temper()                 //PID温度控制输出函数
{ 
  unsigned char i; 
  
  if(set_temper>temper) 
   { 
    if(set_temper-temper>50)//如果控制目标温度温与实时温度差大于5度,(放大10倍)是50
     { 
       
           PWM0_set(10); //PWM 输出高电平占空比最大。即全速加温
           PWM1_set(10);
     }
        else 
    { 
     for(i=0;i<10;i++) //5度范围内PID增量控制,10次周期 即PID积分式中T=10
     { 
      rin=ReadTemperature();//PID输入实时温度采样值
      rout = PIDCalc ( &spid,rin ); // PID增量输出 
     }//PID增量输出范围(0-255)配合pwm取值范围 
     send_string_com("pid out:"); //串口输出监视数据 
         send_char_com(rin); //实时温度值
         send_char_com(rout);//PID增量输出值
         send_char_com(0x0d);//输出回车,换行间隔控制字符
         send_char_com(0x0a);//
         
         if(rout>=240)rout=240;        //保障PWM输入值10-240 防止pwm出现失调。stc单片机特性。
         if(rout<=20)rout=20;
         
         PWM0_set(255-rout); 
         PWM1_set(255-rout);
          
    } 
   } 
  else if(set_temper<=temper) //目标温度小于实时温度pwm输出低电平最高占空比,关闭加热。
   { 
     PWM0_set(250); 
         PWM1_set(250);
   } 
}
/************************************************
                        系统初始化函数
*************************************************/
void Sys_Init()                                                                
{
 PWM_init();
 PIDBEGIN();
 LCD_Init();
 Init_DS18B20();
 LCD_Clear();
 InitUart1();
}
/*************************************************
                  主函数
**************************************************/
void main(void)
{         
 Sys_Init();                //系统初始化
 xianshi();                        //显示字符
 PWM0_set(250);                //初始化PWM两路输出最高低电平占空比,不要加热
 PWM1_set(250);
 delay500ms();                //延时稍等芯片初始化
 while(1)
  {  
           EA=0;
          k=KeyPro();            //键盘扫描
          if(k!=0xff)
           {
           if(k==15){i=0;shu[0]=0;shu[1]=0;shu[2]=0;shu[3]=0;}
           else{shu[i]=k;i++;if(i>3)i=0;}//键值15对应清除设定温度显示及数组为0
         }
         if(k==14)//键值14键 置入设定温度并确定 输入格式xxx+确定键 第一位是百度 为0需要输入0
         { 
          EA=1;
          set_temper=1000*(shu[0])+100*shu[1]+10*shu[2];
          compare_temper();        //启动PID温度控制作动函数
         } 
        LCD_Write_Char(15,1,'C');        //显示设定温度值百位为0时 显示空格 但是输入必须输入0
           LCD_Write_Char(14,1,0xdf); //温标符号
        LCD_Write_Char(13,1,zhi[0]);
        LCD_Write_Char(12,1,'.');
        LCD_Write_Char(11,1,zhi[shu[2]]);
        LCD_Write_Char(10,1,zhi[shu[1]]);
        
        if(shu[0]==0)LCD_Write_Char(9,1,' ');
        else LCD_Write_Char(9,1,zhi[shu[0]]);    
        
        if(counter-- == 0) //温度联系读5次 
         {
          temper=ReadTemperature();                         
          counter =5;
         }
        view(temper);    //温度显示;
        if(!set_temper==0)compare_temper();//只有设置目标温度后才启动PID温控作动函数        
 } 
}
 
 | 
 
×本帖子中包含更多资源您需要 登录 才可以下载或查看,没有账号?立即注册 
  |