新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 51單片機-溫度控制-PID算法-DS18B20-C語言

        51單片機-溫度控制-PID算法-DS18B20-C語言

        作者: 時間:2016-11-13 來源:網絡 收藏
        #include

        #include

        本文引用地址:http://www.104case.com/article/201611/316095.htm

        #include

        #include

        struct PID {

        unsigned int SetPoint; // 設定目標 Desired Value

        unsigned int Proportion; // 比例常數 Proportional Const

        unsigned int Integral; // 積分常數 Integral Const

        unsigned int Derivative; // 微分常數 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;//占空比調節參數

        unsigned char set_temper=35;

        unsigned char temper;

        unsigned char i;

        unsigned char j=0;

        unsigned int s;

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

        延時子程序,延時時間以12M晶振為準,延時時間為30us×time

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

        void delay(unsigned char time)

        {

        unsigned char m,n;

        for(n=0;n

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

        }

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

        寫一位數據子程序

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

        void write_bit(unsigned char bitval)

        {

        EA=0;

        DQ=0; /*拉低DQ以開始一個寫時序*/

        if(bitval==1)

        {

        _nop_();

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

        }

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

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

        _nop_();

        _nop_();

        EA=1;

        }

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

        寫一字節數據子程序

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

        void write_byte(unsigned char val)

        {

        unsigned char i;

        unsigned char temp;

        EA=0;

        TR0=0;

        for(i=0;i<8;i++) /*寫一字節數據,一次寫一位*/

        {

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

        temp=temp&1;

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

        }

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

        // TR0=1;

        EA=1;

        }

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

        讀一位數據子程序

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

        unsigned char read_bit()

        {

        unsigned char i,value_bit;

        EA=0;

        DQ=0; /*拉低DQ,開始讀時序*/

        _nop_();

        _nop_();

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

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

        value_bit=DQ;

        EA=1;

        return(value_bit);

        }

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

        讀一字節數據子程序

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

        unsigned char read_byte()

        {

        unsigned char i,value=0;

        EA=0;

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

        {

        if(read_bit()) /*讀一字節數據,一個時序中讀一次,并作移位處理*/

        value|=0x01<

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

        }

        EA=1;

        return(value);

        }

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

        復位子程序

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

        unsigned char reset()

        {

        unsigned char presence;

        EA=0;

        DQ=0; /*拉低DQ總線開始復位*/

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

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

        delay(3);

        presence=DQ; /*獲取應答信號*/

        delay(28); /*延時以完成整個時序*/

        EA=1;

        return(presence); /*返回應答信號,有芯片應答返回0,無芯片則返回1*/

        }

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

        獲取溫度子程序

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

        void get_temper()

        {

        unsigned char i,j;

        do

        {

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

        }while(i!=0); /*1為無反饋信號*/

        i=0xcc; /*發送設備定位命令*/

        write_byte(i);

        i=0x44; /*發送開始轉換命令*/

        write_byte(i);

        delay(180); /*延時*/

        do

        {

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

        }while(i!=0);

        i=0xcc; /*設備定位*/

        write_byte(i);

        i=0xbe; /*讀出緩沖區內容*/

        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計算部分

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

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

        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; // 當前微分

        pp->PrevError = pp->LastError;

        pp->LastError = Error;

        return (pp->Proportion * Error // 比例項

        + pp->Integral * pp->SumEror // 積分項

        + pp->Derivative * dError); // 微分項

        }

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

        溫度比較處理子程序

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

        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中斷服務子程序,用于控制電平的翻轉 ,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;

        }

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

        串行口中斷服務程序,用于上位機通訊

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

        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_();

        }

        }

        }

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

        顯示子程序

        功能:將占空比溫度轉化為單個字符,顯示占空比和測得到的溫度

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

        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;

        }

        }



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 临漳县| 台前县| 盘山县| 望谟县| 沅江市| 涿鹿县| 双峰县| 阿克苏市| 玉环县| 孝感市| 永兴县| 同心县| 改则县| 罗甸县| 共和县| 奇台县| 平陆县| 河间市| 昌黎县| 图们市| 宁都县| 繁峙县| 定西市| 华安县| 永寿县| 东安县| 饶阳县| 弥渡县| 辽中县| 石屏县| 额尔古纳市| 文昌市| 榆社县| 博罗县| 陕西省| 铜陵市| 沈丘县| 巫溪县| 荔浦县| 醴陵市| 会东县|