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

📄 18b20温度pid.txt

📁 温度控制PID 经过调试
💻 TXT
字号:
#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!=&#39;#&#39;)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(&#39; &#39;);

⌨️ 快捷键说明

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