新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 51 溫度PID經典算法

        51 溫度PID經典算法

        作者: 時間:2016-11-11 來源:網絡 收藏
        #include51.h>
        #include
        #include
        #include
        structPID{
        unsignedintSetPoint;//設定目標DesiredValue
        unsignedintProportion;//比例常數ProportionalConst
        unsignedintIntegral;//積分常數IntegralConst
        unsignedintDerivative;//微分常數DerivativeConst
        unsignedintLastError;//Error[-1]
        unsignedintPrevError;//Error[-2]
        unsignedintSumError;//SumsofErrors
        };
        structPIDspid;//PIDControlStructure
        unsignedintrout;//PIDResponse(Output)
        unsignedintrin;//PIDFeedback(Input)
        sbitdata1=P1^0;
        sbitclk=P1^1;
        sbitplus=P2^0;
        sbitsubs=P2^1;
        sbitstop=P2^2;
        sbitoutput=P3^4;
        sbitDQ=P3^3;
        unsignedcharflag,flag_1=0;
        unsignedcharhigh_time,low_time,count=0;//占空比調節參數
        unsignedcharset_temper=35;
        unsignedchartemper;
        unsignedchari;
        unsignedcharj=0;
        unsignedints;
        /***********************************************************
        延時子程序,延時時間以12M晶振為準,延時時間為30us×time
        ***********************************************************/
        voiddelay(unsignedchartime)
        {
        unsignedcharm,n;
        for(n=0;n for(m=0;m<2;m++){}
        }
        /***********************************************************
        寫一位數據子程序
        ***********************************************************/
        voidwrite_bit(unsignedcharbitval)
        {
        EA=0;
        DQ=0;/*拉低DQ以開始一個寫時序*/
        if(bitval==1)
        {
        _nop_();
        DQ=1;/*如要寫1,則將總線置高*/
        }
        delay(5);/*延時90us供DA18B20采樣*/
        DQ=1;/*釋放DQ總線*/
        _nop_();
        _nop_();
        EA=1;
        }
        /***********************************************************
        寫一字節數據子程序
        ***********************************************************/
        voidwrite_byte(unsignedcharval)
        {
        unsignedchari;
        unsignedchartemp;
        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;
        }
        /***********************************************************
        讀一位數據子程序
        ***********************************************************/
        unsignedcharread_bit()
        {
        unsignedchari,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);
        }
        /***********************************************************
        讀一字節數據子程序
        ***********************************************************/
        unsignedcharread_byte()
        {
        unsignedchari,value=0;
        EA=0;
        for(i=0;i<8;i++)
        {
        if(read_bit())/*讀一字節數據,一個時序中讀一次,并作移位處理*/
        value|=0x01<delay(4);/*延時80us以完成此次都時序,之后再讀下一數據*/
        }
        EA=1;
        return(value);
        }
        /***********************************************************
        復位子程序
        ***********************************************************/
        unsignedcharreset()
        {
        unsignedcharpresence;
        EA=0;
        DQ=0;/*拉低DQ總線開始復位*/
        delay(30);/*保持低電平480us*/
        DQ=1;/*釋放總線*/
        delay(3);
        presence=DQ;/*獲取應答信號*/
        delay(28);/*延時以完成整個時序*/
        EA=1;
        return(presence);/*返回應答信號,有芯片應答返回0,無芯片則返回1*/
        }
        /***********************************************************
        獲取溫度子程序
        ***********************************************************/
        voidget_temper()
        {
        unsignedchari,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=(unsignedint)(j&0x0f); //得到小數部分
        s=(s*100)/16;
        j=j>>4;
        temper=i|j;/*獲取的溫度放在temper中*/
        }
        /*====================================================================================================
        InitializePIDStructure
        =====================================================================================================*/
        voidPIDInit(structPID*pp)
        {
        memset(pp,0,sizeof(structPID)); //全部初始化為0
        }
        /*====================================================================================================
        PID計算部分
        =====================================================================================================*/
        unsignedintPIDCalc(structPID*pp,unsignedintNextPoint)
        {
        unsignedintdError,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->SumError//積分項
        +pp->Derivative*dError);//微分項
        }
        /***********************************************************
        溫度比較處理子程序
        ***********************************************************/
        voidcompare_temper()
        {
        unsignedchari;
        if(set_temper>temper)//是否設置的溫度大于實際溫度
        {
        if(set_temper-temper>1) //設置的溫度比實際的溫度是否是大于1度
        {
        high_time=100; //如果是,則全速加熱
        low_time=0;
        }
        else //如果是在1度范圍內,則運行PID計算
        {
        for(i=0;i<10;i++)
        {
        get_temper(); //獲取溫度
        rin=s;//ReadInput
        rout=PIDCalc(&spid,rin);//PerformPIDInteration
        }
        if(high_time<=100)
        high_time=(unsignedchar)(rout/800);
        else
        high_time=100;
        low_time=(100-high_time);
        }
        }
        elseif(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;//ReadInput
        rout=PIDCalc(&spid,rin);//PerformPIDInteration
        }
        if(high_time<100)
        high_time=(unsignedchar)(rout/10000);
        else
        high_time=0;
        low_time=(100-high_time);
        }
        }
        //else
        //{}
        }
        /*****************************************************
        T0中斷服務子程序,用于控制電平的翻轉,40us*100=4ms周期
        ******************************************************/
        voidserve_T0()interrupt1using1
        {
        if(++count<=(high_time))
        output=1;
        elseif(count<=100)
        {
        output=0;
        }
        else
        count=0;
        TH0=0x2f;
        TL0=0xe0;
        }
        /*****************************************************
        串行口中斷服務程序,用于上位機通訊
        ******************************************************/
        voidserve_sio()interrupt4using2
        {
        /*EA=0;
        RI=0;
        i=SBUF;
        if(i==2)
        {
        while(RI==0){}
        RI=0;
        set_temper=SBUF;
        SBUF=0x02;
        while(TI==0){}
        TI=0;
        }
        elseif(i==3)
        {
        TI=0;
        SBUF=temper;
        while(TI==0){}
        TI=0;
        }
        EA=1;*/
        }
        voiddisp_1(unsignedchardisp_num1[6])
        {
        unsignedcharn,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_();
        }
        }
        }
        /*****************************************************
        顯示子程序
        功能:將占空比溫度轉化為單個字符,顯示占空比和測得到的溫度
        ******************************************************/
        voiddisplay()
        {
        unsignedcharcodenumber[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6};
        unsignedchardisp_num[6];
        unsignedintk,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);
        }
        /***********************************************************
        主程序
        ***********************************************************/
        voidmain()
        {
        unsignedcharz;
        unsignedchara,b,flag_2=1,count1=0;
        unsignedcharphil[]={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);//InitializeStructure
        spid.Proportion=10;//SetPIDCoefficients比例常數ProportionalConst
        spid.Integral=8;//積分常數IntegralConst
        spid.Derivative=6;//微分常數DerivativeConst
        spid.SetPoint=100;//SetPIDSetpoint設定目標DesiredValue
        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;
        }
        }
        elseif(subs==0)
        {
        for(a=0;a<5;a++)
        for(b=0;a<102;b++){}
        if(subs==0)
        {
        set_temper--;
        flag=0;
        }
        }
        elseif(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;
        }
        }


        關鍵詞: 51溫度PID經典算

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 朝阳区| 牙克石市| 大宁县| 临漳县| 乡城县| 松溪县| 美姑县| 府谷县| 阜南县| 昭通市| 拉萨市| 桃园县| 黄陵县| 图片| 湾仔区| 宁夏| 余庆县| 巴楚县| 安徽省| 平顺县| 五家渠市| 石屏县| 连平县| 农安县| 页游| 蓬安县| 木兰县| 华坪县| 北安市| 宜州市| 铁岭市| 武宣县| 离岛区| 栾川县| 叶城县| 视频| 泰兴市| 漳州市| 平度市| 柘荣县| 惠安县|