<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 51單片機(jī)-溫度控制-PID算法-DS18B20-C語(yǔ)言

          51單片機(jī)-溫度控制-PID算法-DS18B20-C語(yǔ)言

          作者: 時(shí)間:2016-11-13 來(lái)源:網(wǎng)絡(luò) 收藏
          #include

          #include

          本文引用地址:http://www.ex-cimer.com/article/201611/316095.htm

          #include

          #include

          struct PID {

          unsigned int SetPoint; // 設(shè)定目標(biāo) Desired Value

          unsigned int Proportion; // 比例常數(shù) Proportional Const

          unsigned int Integral; // 積分常數(shù) Integral Const

          unsigned int Derivative; // 微分常數(shù) Derivative Const

          unsigned int LastError; // Error[-1]

          unsigned int PrevError; // Error[-2]

          unsigned int SumError; // Sums of Errors

          };

          struct PID spid; // PID Control Structure

          unsigned int rout; // PID Response (Output)

          unsigned int rin; // PID Feedback (Input)

          sbit data1=P1^0;

          sbit clk=P1^1;

          sbit plus=P2^0;

          sbit subs=P2^1;

          sbit stop=P2^2;

          sbit output=P3^4;

          sbit DQ=P3^3;

          unsigned char flag,flag_1=0;

          unsigned char high_time,low_time,count=0;//占空比調(diào)節(jié)參數(shù)

          unsigned char set_temper=35;

          unsigned char temper;

          unsigned char i;

          unsigned char j=0;

          unsigned int s;

          /***********************************************************

          延時(shí)子程序,延時(shí)時(shí)間以12M晶振為準(zhǔn),延時(shí)時(shí)間為30us×time

          ***********************************************************/

          void delay(unsigned char time)

          {

          unsigned char m,n;

          for(n=0;n

          for(m=0;m<2;m++){}

          }

          /***********************************************************

          寫(xiě)一位數(shù)據(jù)子程序

          ***********************************************************/

          void write_bit(unsigned char bitval)

          {

          EA=0;

          DQ=0; /*拉低DQ以開(kāi)始一個(gè)寫(xiě)時(shí)序*/

          if(bitval==1)

          {

          _nop_();

          DQ=1; /*如要寫(xiě)1,則將總線置高*/

          }

          delay(5); /*延時(shí)90us供DS18B20采樣*/

          DQ=1; /*釋放DQ總線*/

          _nop_();

          _nop_();

          EA=1;

          }

          /***********************************************************

          寫(xiě)一字節(jié)數(shù)據(jù)子程序

          ***********************************************************/

          void write_byte(unsigned char val)

          {

          unsigned char i;

          unsigned char temp;

          EA=0;

          TR0=0;

          for(i=0;i<8;i++) /*寫(xiě)一字節(jié)數(shù)據(jù),一次寫(xiě)一位*/

          {

          temp=val>>i; /*移位操作,將本次要寫(xiě)的位移到最低位*/

          temp=temp&1;

          write_bit(temp); /*向總線寫(xiě)該位*/

          }

          delay(7); /*延時(shí)120us后*/

          // TR0=1;

          EA=1;

          }

          /***********************************************************

          讀一位數(shù)據(jù)子程序

          ***********************************************************/

          unsigned char read_bit()

          {

          unsigned char i,value_bit;

          EA=0;

          DQ=0; /*拉低DQ,開(kāi)始讀時(shí)序*/

          _nop_();

          _nop_();

          DQ=1; /*釋放總線*/

          for(i=0;i<2;i++){}

          value_bit=DQ;

          EA=1;

          return(value_bit);

          }

          /***********************************************************

          讀一字節(jié)數(shù)據(jù)子程序

          ***********************************************************/

          unsigned char read_byte()

          {

          unsigned char i,value=0;

          EA=0;

          for(i=0;i<8;i++)

          {

          if(read_bit()) /*讀一字節(jié)數(shù)據(jù),一個(gè)時(shí)序中讀一次,并作移位處理*/

          value|=0x01<

          delay(4); /*延時(shí)80us以完成此次都時(shí)序,之后再讀下一數(shù)據(jù)*/

          }

          EA=1;

          return(value);

          }

          /***********************************************************

          復(fù)位子程序

          ***********************************************************/

          unsigned char reset()

          {

          unsigned char presence;

          EA=0;

          DQ=0; /*拉低DQ總線開(kāi)始復(fù)位*/

          delay(30); /*保持低電平480us*/

          DQ=1; /*釋放總線*/

          delay(3);

          presence=DQ; /*獲取應(yīng)答信號(hào)*/

          delay(28); /*延時(shí)以完成整個(gè)時(shí)序*/

          EA=1;

          return(presence); /*返回應(yīng)答信號(hào),有芯片應(yīng)答返回0,無(wú)芯片則返回1*/

          }

          /***********************************************************

          獲取溫度子程序

          ***********************************************************/

          void get_temper()

          {

          unsigned char i,j;

          do

          {

          i=reset(); /*復(fù)位*/

          }while(i!=0); /*1為無(wú)反饋信號(hào)*/

          i=0xcc; /*發(fā)送設(shè)備定位命令*/

          write_byte(i);

          i=0x44; /*發(fā)送開(kāi)始轉(zhuǎn)換命令*/

          write_byte(i);

          delay(180); /*延時(shí)*/

          do

          {

          i=reset(); /*復(fù)位*/

          }while(i!=0);

          i=0xcc; /*設(shè)備定位*/

          write_byte(i);

          i=0xbe; /*讀出緩沖區(qū)內(nèi)容*/

          write_byte(i);

          j=read_byte();

          i=read_byte();

          i=(i<<4)&0x7f;

          s=(unsigned int)(j&0x0f);

          s=(s*100)/16;

          j=j>>4;

          temper=i|j; /*獲取的溫度放在temper中

          */

          }

          /*=========================================================================

          ===========================

          Initialize PID Structure

          ===========================================================================

          ==========================*/

          void PIDInit (struct PID *pp)

          {

          memset ( pp,0,sizeof(struct PID));

          }

          /*=========================================================================

          ===========================

          PID計(jì)算部分

          ===========================================================================

          ==========================*/

          unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint )

          {

          unsigned int dError,Error;

          Error = pp->SetPoint - NextPoint; // 偏差

          pp->SumError += Error; // 積分

          dError = pp->LastError - pp->PrevError; // 當(dāng)前微分

          pp->PrevError = pp->LastError;

          pp->LastError = Error;

          return (pp->Proportion * Error // 比例項(xiàng)

          + pp->Integral * pp->SumEror // 積分項(xiàng)

          + pp->Derivative * dError); // 微分項(xiàng)

          }

          /***********************************************************

          溫度比較處理子程序

          ***********************************************************/

          compare_temper()

          {

          unsigned char i;

          if(set_temper>temper)

          {

          if(set_temper-temper>1)

          {

          high_time=100;

          low_time=0;

          }

          else

          {

          for(i=0;i<10;i++)

          { get_temper();

          rin = s; // Read Input

          rout = PIDCalc ( &spid,rin ); // Perform PID Interation

          }

          if (high_time<=100)

          high_time=(unsigned char)(rout/800);

          else

          high_time=100;

          low_time= (100-high_time);

          }

          }

          else if(set_temper<=temper)

          {

          if(temper-set_temper>0)

          {

          high_time=0;

          low_time=100;

          }

          else

          {

          for(i=0;i<10;i++)

          { get_temper();

          rin = s; // Read Input

          rout = PIDCalc ( &spid,rin ); // Perform PID Interation

          }

          if (high_time<100)

          high_time=(unsigned char)(rout/10000);

          else

          high_time=0;

          low_time= (100-high_time);

          }

          }

          // else

          // {}

          }

          /*****************************************************

          T0中斷服務(wù)子程序,用于控制電平的翻轉(zhuǎn) ,40us*100=4ms周期

          ******************************************************/

          void serve_T0() interrupt 1 using 1

          {

          if(++count<=(high_time))

          output=1;

          else if(count<=100)

          {

          output=0;

          }

          else

          count=0;

          TH0=0x2f;

          TL0=0xe0;

          }

          /*****************************************************

          串行口中斷服務(wù)程序,用于上位機(jī)通訊

          ******************************************************/

          void serve_sio() interrupt 4 using 2

          {

          /* EA=0;

          RI=0;

          i=SBUF;

          if(i==2)

          {

          while(RI==0){}

          RI=0;

          set_temper=SBUF;

          SBUF=0x02;

          while(TI==0){}

          TI=0;

          }

          else if(i==3)

          {

          TI=0;

          SBUF=temper;

          while(TI==0){}

          TI=0;

          }

          EA=1; */

          }

          void disp_1(unsigned char disp_num1[6])

          {

          unsigned char n,a,m;

          for(n=0;n<6;n++)

          {

          // k=disp_num1[n];

          for(a=0;a<8;a++)

          {

          clk=0;

          m=(disp_num1[n]&1);

          disp_num1[n]=disp_num1[n]>>1;

          if(m==1)

          data1=1;

          else

          data1=0;

          _nop_();

          clk=1;

          _nop_();

          }

          }

          }

          /*****************************************************

          顯示子程序

          功能:將占空比溫度轉(zhuǎn)化為單個(gè)字符,顯示占空比和測(cè)得到的溫度

          ******************************************************/

          void display()

          {

          unsigned char code number[]=

          {0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6};

          unsigned char disp_num[6];

          unsigned int k,k1;

          k=high_time;

          k=k%1000;

          k1=k/100;

          if(k1==0)

          disp_num[0]=0;

          else

          disp_num[0]=0x60;

          k=k%100;

          disp_num[1]=number[k/10];

          disp_num[2]=number[k%10];

          k=temper;

          k=k%100;

          disp_num[3]=number[k/10];

          disp_num[4]=number[k%10]+1;

          disp_num[5]=number[s/10];

          disp_1(disp_num);

          }

          /***********************************************************

          主程序

          ***********************************************************/

          main()

          {

          unsigned char z;

          unsigned char a,b,flag_2=1,count1=0;

          unsigned char phil[]={2,0xce,0x6e,0x60,0x1c,2};;

          TMOD=0x21;

          TH0=0x2f;

          TL0=0x40;

          SCON=0x50;

          PCON=0x00;

          TH1=0xfd;

          TL1=0xfd;

          PS=1;

          EA=1;

          EX1=0;

          ET0=1;

          ES=1;

          TR0=1;

          TR1=1;

          high_time=50;

          low_time=50;

          PIDInit ( &spid ); // Initialize Structure

          spid.Proportion = 10; // Set PID Coefficients

          spid.Integral = 8;

          spid.Derivative =6;

          spid.SetPoint = 100; // Set PID Setpoint

          while(1)

          {

          if(plus==0)

          {

          EA=0;

          for(a=0;a<5;a++)

          for(b=0;b<102;b++){}

          if(plus==0)

          {

          set_temper++;

          flag=0;

          }

          }

          else if(subs==0)

          {

          for(a=0;a<5;a++)

          for(b=0;a<102;b++){}

          if(subs==0)

          {

          set_temper--;

          flag=0;

          }

          }

          else if(stop==0)

          {

          for(a=0;a<5;a++)

          for(b=0;b<102;b++){}

          if(stop==0)

          {

          flag=0;

          break;

          }

          EA=1;

          }

          get_temper();

          b=temper;

          if(flag_2==1)

          a=b;

          if((abs(a-b))>5)

          temper=a;

          else

          temper=b;

          a=temper;

          flag_2=0;

          if(++count1>30)

          {

          display();

          count1=0;

          }

          compare_temper();

          }

          TR0=0;

          z=1;

          while(1)

          {

          EA=0;

          if(stop==0)

          {

          for(a=0;a<5;a++)

          for(b=0;b<102;b++){}

          if(stop==0)

          disp_1(phil);

          // break;

          }

          EA=1;

          }

          }



          評(píng)論


          技術(shù)專(zhuān)區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();