⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 采用18b20的温度pid控制程序.txt

📁 利用18B20结合PID技术达到自动控制温度的效果
💻 TXT
字号:
采用18B20的温度PID控制程序(C51)


#include "reg52.h"
#define uchar unsigned char
#define uint  unsigned int


void sendbyte(char);
uchar  timecnt=0;
/************************PID******************************/
bit  dealCS=0;
uchar Ctrltab[20]={8,15,20,40,50,60,70,80,100,120,140,160,180,200};
            
//###########################
sbit PWM=P3^2;
#define tim0 65536-5000      
#define tim1 65536-10000
uchar tm=0,tx=0;              //记数两个定时中断的
enum{Y,U,R,Ts,Kd,Kp};//Y采集量 U控制量 R 设定量 Ts 采样时间 Kd 微分 Kp比例
int para[6],ptr,out;          //out 是从PID()得到的控制量
int wd=300,r,kp,kd,ts,e2,e1,e0,u; //wd 是从DS18B20采到的数据
//###########################
void  initTimer0_Timer1()     //初始化定时器0,定时器1
{
TMOD=0x11;
TH0=tim0>>8; TL0=tim0; 
TH1=tim1>>8; TL1=tim1;
TR0=1;
ET0=1;
TR1=1;
ET1=1;
EA=1;
}
void  initPID()               //初始化PID函参数
{
  para[R]=40;
  para[Kp]=200; 
  para[Kd]=3;   
  para[Ts]=10;  
}

void PID()                   //PID服务程序
{  
  para[Y]=wd; 
  r=para[R];  
  e0=e1;e1=e2;e2=r-para[Y]/10; 
  kp=para[Kp]; kd=para[Kd]; ts=para[Ts];
  u=r+kp*(e2+kd*(e2-e1));
  if(u<0) u=0;
  if(u>2559) u=2559;
  para[U]=u/10;
  out=para[U];
}

void PWM_timer0() interrupt 1     //定时器0中断服务子程序
{
  TH0=tim0>>8; TL0=tim0; 
  if(tm++>out) PWM=1;             //通过变量out控制PWM脉冲宽度
          else PWM=0;
  if(tm>255) tm=0;                //通过变量tm控制PWM的周期
  if(out<10)PWM=1;    

  if(timecnt++==180)
  {
    timecnt=0;
sendbyte(0xA5);
sendbyte(para[R]);   //设定温度
sendbyte(wd/10);     //当前温度
sendbyte(para[Kp]);          //P
sendbyte(0xa5);      //I 现在没有用、
sendbyte(para[Kd]);          //D
    sendbyte(0xCD);
  }
}

int  wdCtrl;
void timer1() interrupt 3        //定时器1中断服务子程序 
{
  TH1=tim1>>8; TL1=tim1;
  if(dealCS==0)                  ///模糊控制
   {
      wdCtrl=para[R];
      if((wdCtrl-wd/10)>10)out=225;
      else if((wd/10-wdCtrl)>2)out=0;
   else out=Ctrltab[wdCtrl+2-wd/10]; 
   }
else if(tx++>=ts)              //dealCS为1,选择的是PID();
  {
   PID(); 
   tx=0;
  }
}
/********************end PID******************************/
/****************LCD程序*******************/
#define dataport P0      
sbit RS=P3^4;
sbit RW=P3^5;
sbit ET=P3^6;

void Wait()               //延时程序
{uint j;  
for(j=0;j<300;j++){;}
}       
void WriCom(uchar comm)     //发送命令字节到LCD
{   RS=0;
     RW=0;
     ET=0;
     dataport=comm;
     ET=1;
     Wait();
     ET=0;
    }
void WriData(uchar wdata)   //写数据到LCD
    {      
      RS=1;
      RW=0;
      ET=0;   
      dataport=wdata;
      ET=1;    
      Wait();
      ET=0;           
     }
void InitLcd()               //初始化LCD
{ 
   Wait();
   WriCom(0x38);
   Wait();
   WriCom(0x38);
   Wait();
   WriCom(0x38);
   Wait();
   WriCom(0x38);
   Wait();
   WriCom(0x08);
   WriCom(0x01);
   WriCom(0x06);
   WriCom(0x0C);
}
void SetCursor(uchar row)     //设置光标插入点(写入的数据插入点
{  if(row>15)
   row+=(0x40-16);
   WriCom(row | 0x80);
}
void ClrLCD()                //清屏LCD
{
   WriCom(0x01);
}
void WriStr(char *ch)          //发送一串数据
{
   while(*ch!='#')WriData(*ch++);
}
/*****************LCD程序END****************/ 
/*************************DS18B20 子程序 *********************/
sbit  DQ=P2^4;
sbit  DQ1=P2^5;
sbit  DQ2=P3^3;
typedef unsigned char byte;
typedef unsigned int  word;
                               
void delay(word useconds)        //延时
{
  for(;useconds>0;useconds--);
}

byte ow_reset(void)             //复位
{
  byte presence;
  DQ = 0;             //pull DQ line low
delay(29);          // leave it low for 480us
  DQ = 1;             // allow line to return high
  delay(3);           // wait for presence
  presence = DQ;      // get presence signal
  delay(25);          // wait for end of timeslot
  return(presence);   // presence signal returned
}                     // 0=presence, 1 = no part


byte read_byte(void)    //从 1-wire 总线上读取一个字节
{
  byte i;
  byte value = 0;
  for (i=8;i>0;i--)
  {
    value>>=1;
    DQ = 0;          // pull DQ low to start timeslot
    DQ = 1;          // then return high
    delay(1);        //for (i=0; i<3; i++); 
    if(DQ)value|=0x80;
    delay(6);        // wait for rest of timeslot
  }
  return(value);
}

void write_byte(char val)   //向 1-WIRE 总线上写一个字节
{
  byte i;
  for (i=8; i>0; i--) // writes byte, one bit at a time
  {
    DQ = 0;           // pull DQ low to start timeslot
    DQ = val&0x01;
    delay(5);         // hold value for remainder of timeslot
    DQ = 1;
    val=val/2;
  }
  delay(5);
}

uchar Read_Temperature(void)//读取温度
{
  union{
    byte c[2];
    uint X;         //  X的值为 FFFF xxxx_xxxx ZZZZ   
        //  其中 FFFF为符号位,xxxx_xxxx 为温度整数位,ZZZZ为小数部分,
     // 小数值=ZZZZ*0.0625
  }temp;
ow_reset();
  write_byte(0xCC); // Skip ROM
  write_byte(0xBE); // Read Scratch Pad
  temp.c[1]=read_byte();
  temp.c[0]=read_byte();
  ow_reset();
  write_byte(0xCC); //Skip ROM
  write_byte(0x44); // Start Conversion
return  temp.X>>4; //这里只取出温度整数部分
}
/********************************************************/ 
byte ow_reset1(void)
{
  byte presence;
  DQ1 = 0;             //pull DQ line low
  delay(29);          // leave it low for 480us
  DQ1 = 1;             // allow line to return high
  delay(3);           // wait for presence
  presence = DQ1;      // get presence signal
  delay(25);          // wait for end of timeslot
  return(presence);   // presence signal returned
}                     // 0=presence, 1 = no part


byte read_byte1(void)//从 1-wire 总线上读取一个字节
{
  byte i;
  byte value = 0;
  for (i=8;i>0;i--)
  {
    value>>=1;
    DQ1 = 0;          // pull DQ low to start timeslot
    DQ1 = 1;          // then return high
    delay(1);        //for (i=0; i<3; i++); 
    if(DQ1)value|=0x80;
    delay(6);        // wait for rest of timeslot
  }
  return(value);
}

void write_byte1(char val)//向 1-WIRE 总线上写一个字节
{
  byte i;
  for (i=8; i>0; i--) // writes byte, one bit at a time
  {
    DQ1 = 0;           // pull DQ low to start timeslot
    DQ1 = val&0x01;
    delay(5);         // hold value for remainder of timeslot
    DQ1 = 1;
    val=val/2;
  }
  delay(5);
}

uchar Read_Temperature1(void)//读取温度
{
  union{
    byte c[2];
    uint X;         //  X的值为 FFFF xxxx_xxxx ZZZZ   
//  其中 FFFF为符号位,xxxx_xxxx 为温度整数位,ZZZZ为小数部分,
     // 小数值=ZZZZ*0.0625
  }temp;
ow_reset1();
  write_byte1(0xCC); // Skip ROM
  write_byte1(0xBE); // Read Scratch Pad
  temp.c[1]=read_byte1();
  temp.c[0]=read_byte1();
  ow_reset1();
  write_byte1(0xCC); //Skip ROM
  write_byte1(0x44); // Start Conversion
return  temp.X>>4; //这里只取出温度整数部分
}
/********************************************************/ 
byte ow_reset2(void)
{
  byte presence;
  DQ2 = 0;             //pull DQ line low
  delay(29);          // leave it low for 480us
  DQ2 = 1;             // allow line to return high
  delay(3);           // wait for presence
  presence = DQ2;      // get presence signal
  delay(25);          // wait for end of timeslot
  return(presence);   // presence signal returned
}                     // 0=presence, 1 = no part


byte read_byte2(void)//从 1-wire 总线上读取一个字节
{
  byte i;
  byte value = 0;
  for (i=8;i>0;i--)
  {
    value>>=1;
    DQ2 = 0;          // pull DQ low to start timeslot
    DQ2 = 1;          // then return high
    delay(1);        //for (i=0; i<3; i++); 
    if(DQ2)value|=0x80;
    delay(6);        // wait for rest of timeslot
  }
  return(value);
}

void write_byte2(char val)//向 1-WIRE 总线上写一个字节
{
  byte i;
  for (i=8; i>0; i--) // writes byte, one bit at a time
  {
    DQ2 = 0;           // pull DQ low to start timeslot
    DQ2 = val&0x01;
    delay(5);         // hold value for remainder of timeslot
    DQ2 = 1;
    val=val/2;
  }
  delay(5);
}

uchar Read_Temperature2(void)//读取温度
{
  union{
    byte c[2];
    uint X;         //  X的值为 FFFF xxxx_xxxx ZZZZ   
  //  其中 FFFF为符号位,xxxx_xxxx 为温度整数位,ZZZZ为小数部分,
     // 小数值=ZZZZ*0.0625
  }temp;
ow_reset2();
  write_byte2(0xCC); // Skip ROM
  write_byte2(0xBE); // Read Scratch Pad
  temp.c[1]=read_byte2();
  temp.c[0]=read_byte2();
  ow_reset2();
  write_byte2(0xCC); //Skip ROM
  write_byte2(0x44); // Start Conversion
return  temp.X>>4; //这里只取出温度整数部分
}
/*************************end DS18B20 子程序 ****************/ 
uchar funkey()      //按键识别子程序
{
   uint timecnt;
   uint key;
   P1=0xff;
   key=P1;
   if(key!=0xff)
   { 
     for(timecnt=0;timecnt<200;timecnt++);    //延时去抖
     if(key!=0xff)
  {
    while(P1!=0xff);   //等待键放开
       return key;
  }
  return 0;
   }
   return 0;
}   
uint key;    
int wd1,wd2,wd3; 

void  sendbyte(char ch)
{
  TI=0;
  SBUF=ch;
  while(TI==0);
  TI=0;
}    

void main(void)                        //主程序
{   
    //////////////////开串口中断
    SCON=0X50;    
    T2CON=0X34;                    // RCLK=1; TCLK=1; TR2=1;  
    RCAP2H=0XFF;   RCAP2L=0XDB;   TR2=1;        // 9600 b/s
    EA=1;
//////////////////
       InitLcd();      //初始化LCD       
    initTimer0_Timer1();   //初始化定时器0,定时器1
    initPID();            //初始化PID 参数
       ClrLCD();             //清屏LCD
    {

     SetCursor(0); 
     wd1=Read_Temperature()*10;           //读温度
  WriData(wd1/100+0x30);
     WriData((wd1%100)/10+0x30);
  WriData(' ');

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -