|
STC單片機(jī)做了一個(gè)關(guān)于PID控制氣壓的算法,led數(shù)據(jù)碼顯示
0.png (42.7 KB, 下載次數(shù): 83)
下載附件
2017-6-14 16:34 上傳
0.png (45.87 KB, 下載次數(shù): 68)
下載附件
2017-6-14 16:34 上傳
單片機(jī)源程序如下:
- #include "config.h"
- #include <math.h>
- #define ADC_POWER 0x80
- #define ADC_FLAG 0x10
- #define ADC_START 0x08
- #define ADC_SPEEDLL 0x00
- #define ADC_SPEEDL 0x20
- #define ADC_SPEEDH 0x40
- #define ADC_SPEEDHH 0x60
- unsigned char idata RsBuf[MAC_RX_BUF];
- unsigned char data guc_RsPoint=0;
- //unsigned char xdata Time0L1;
- //unsigned char xdata Time0H1;
- unsigned char xdata led_step=0;
- unsigned char xdata led_show1;
- unsigned char xdata led_show2;
- unsigned char xdata led_show3;
- unsigned char xdata led_show4;
- unsigned int xdata Time_Show=0;
- unsigned int xdata TimeMotor=0;
- unsigned int xdata PwmBitVat=0;
- //unsigned short xdata ADC_VAL[3];
- //unsigned char xdata ADC_ch=0;
- bit led_dian1;
- bit led_dian2;
- bit led_dian3;
- bit led_dian4;
- bit RsOver=0;
- typedef struct _pid_t
- {
- float SetSpeed;//定義設(shè)定值
- float ActualSpeed;//定義實(shí)際值
- float err;//定義偏差值
- float err_last;//定義上一個(gè)偏差值
- float Kp,Ki,Kd;//定義比例、積分、微分系數(shù)
- float voltage;//定義電壓值(控制執(zhí)行器的變量)
- float integral;//定義積分值
- float umax;
- float umin;
- } pid_t;
- unsigned char code ledTab[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x27,0x7f,0x6f};
- void PID_init(pid_t *npid)
- {
- npid->SetSpeed=0.0;
- npid->ActualSpeed=0.0;
- npid->err=0.0;
- npid->err_last=0.0;
- npid->voltage=0.0;
- npid->integral=0.0;
- npid->Kp=0.2;
- npid->Ki=0.015;
- npid->Kd=0.2;
-
- npid->umax=127;
- npid->umin=-127;
- }
- float PID_realize(pid_t *npid ,float speed,float ActualSpeed)
- {
- float index;
- npid->SetSpeed=speed;
- npid->ActualSpeed=ActualSpeed;
- npid->err=npid->SetSpeed-npid->ActualSpeed;
- if(npid->voltage>npid->umax)
- {
- if(abs(npid->err)>200)//變積分過程
- {
- index=0.0;
- }
- else if(abs(npid->err)<180)
- {
- index=1.0;
- if(npid->err<0)
- {
- npid->integral+=npid->err;
- }
- }
- else
- {
- index=(200-abs(npid->err))/20;
- if(npid->err<0)
- {
- npid->integral+=npid->err;
- }
- }
- }
- else if(npid->voltage<npid->umin)
- {
- if(abs(npid->err)>200)//變積分過程
- {
- index=0.0;
- }
- else if(abs(npid->err)<180)
- {
- index=1.0;
- if(npid->err>0)
- {
- npid->integral+=npid->err;
- }
- }
- else
- {
- index=(200-abs(npid->err))/20;
- if(npid->err>0)
- {
- npid->integral+=npid->err;
- }
- }
- }
- else
- {
- if(abs(npid->err)>200)//變積分過程
- {
- index=0.0;
- }
- else if(abs(npid->err)<180)
- {
- index=1.0;
- npid->integral+=npid->err;
- }
- else
- {
- index=(200-abs(npid->err))/20;
- npid->integral+=npid->err;
- }
- }
- npid->voltage=npid->Kp*npid->err+index*npid->Ki*npid->integral+npid->Kd*(npid->err-npid->err_last);
- npid->err_last=npid->err;
- return npid->voltage;
- }
- void Delay_n_ms(unsigned int dly)
- {
- unsigned int j;
- do
- {
- j = MAIN_Fosc / 13000; //延時(shí)1ms, 主程序在此節(jié)拍下運(yùn)行
- while(--j) ;
- }while(--dly);
- }
- void InitUart(void)
- {
- SCON = 0x50;//工作在串口模式
- T2L = (65536 - (MAIN_Fosc/4/BAUD)); //設(shè)置波特率為重新裝值
- T2H = (65536 - (MAIN_Fosc/4/BAUD))>>8;
- AUXR |= 0x14; //啟用定時(shí)器T2為1T模式, 并啟用定時(shí)器2
- AUXR |= 0x01; //選擇定時(shí)器2為串口1的波特率發(fā)生器
- ES = 1; //使能串口1為中斷
- }
- void InitTime0(void)
- {
- // #if 0
- // AUXR |= (1<<7); // Timer0 set as 1T mode
- // TMOD = 0x01; //16位,
- // //Timer0_16bit();
- // Time0L1=(65536-(MAIN_Fosc/1000000)*(TIME0_us1))%256;
- // Time0H1=(65536-(MAIN_Fosc/1000000)*(TIME0_us1))/256;
- // TL0=Time0L1;
- // TH0=Time0H1;
- // #endif
- T0_Load_us_12T(TIME0_us1);
- ET0 = 1; //Timer0 Interrupt Enable
- PT0 = 1; //高優(yōu)先級(jí)
- TR0 = 1; //Timer0 Run
- }
- // ADC初始化函數(shù)
- void ADC_Init(void)
- {
- // ADC_ch=0;
- // P1ASF=0x30;//設(shè)置P1為ADC
- // //P1ASF|=(1<<4)|(1<<5);
- // ADC_RES=0; // 清除結(jié)果寄存器
- // ADC_CONTR=ADC_POWER|ADC_SPEEDLL|ADC_START|4;
- // Delay_n_ms(20);
- // EADC=1;// EADC=1 允許ADC中斷
-
- //查詢方式
- P1ASF=0x30;//設(shè)置P1為ADC
- ADC_RES=0;
- ADC_RESL=0;
- ADC_CONTR=ADC_POWER|ADC_SPEEDLL;
- Delay_n_ms(20);
- }
- void SendTxdBuf(unsigned char ASC) //發(fā)送-個(gè)ASCII
- {
- ES = 0; //關(guān)閉串口中斷
- SBUF = ASC;
- while(TI ==0); //
- TI = 0; //
- ES = 1; //允許串口中斷
- }
- void Rs_Do(void) interrupt 4 using 1 // 通訊中斷接收程序
- {
- unsigned char data luc_temp;
- if(RI==1)
- {
- RI=0;
- luc_temp = SBUF;
- if(guc_RsPoint>=MAC_RX_BUF)
- guc_RsPoint=0;
- if(luc_temp==0x0d)
- {
- RsBuf[guc_RsPoint] = 0x0d;
- guc_RsPoint = 0;
- RsOver = 1;
- }
- else
- {
- RsBuf[guc_RsPoint++]=luc_temp;
- }
- }
- }
- void ledTime()
- {
- switch(led_step)
- {
- case 0:
- DIG1=1;
- DIG2=0;
- DIG3=0;
- DIG4=0;
- P2=ledTab[led_show1];
- led_di=led_dian1;
- led_step=1;
- break;
- case 1:
- DIG1=0;
- DIG2=1;
- DIG3=0;
- DIG4=0;
- P2=ledTab[led_show2];
- led_di=led_dian2;
- led_step=2;
- break;
- case 2:
- DIG1=0;
- DIG2=0;
- DIG3=1;
- DIG4=0;
- P2=ledTab[led_show3];
- led_di=led_dian3;
- led_step=3;
- break;
- case 3:
- DIG1=0;
- DIG2=0;
- DIG3=0;
- DIG4=1;
- P2=ledTab[led_show4];
- led_di=led_dian4;
- led_step=0;
- break;
- }
- }
- void Time0Interrupt(void) interrupt 1 using 3
- {
- //TR0=0;
- ledTime();
- if(Time_Show>0)
- Time_Show--;
-
- if(PwmBitVat>TimeMotor)
- {
- MOTOR1=1;
- }
- else
- {
- MOTOR1=0;//低電平打開電機(jī)
- }
- if(PwmBitVat++>256)
- {
- PwmBitVat=0;
- }
- //TL0=Time0L1;
- //TH0=Time0H1;
- //TR0=1;
- }
- //void ADC_ISR() interrupt 5
- //{
- // ADC_CONTR &= ~ADC_FLAG;
- // switch(ADC_ch)
- // {
- // case 0:
- // ADC_ch=1;
- // ADC_VAL[0]=(ADC_RES<<2)|(ADC_RESL&0x03);
- //
- // ADC_CONTR = ADC_POWER | ADC_SPEEDLL | 5 | ADC_START;
- // break;
- // case 1:
- // ADC_ch=0;
- // ADC_VAL[1]=(ADC_RES<<2)|(ADC_RESL&0x03);
- //
- // ADC_CONTR = ADC_POWER | ADC_SPEEDLL | 4 | ADC_START;
- // break;
- // }
- //}
- void led_showP(float fshowPa)
- {
- static float tmp_showPa=-1;
- float tmp_show=fshowPa;
- float temp_dian;
- unsigned char shorteger,shordian;
- if(fshowPa==tmp_showPa)
- return;
- tmp_showPa=fshowPa;
-
- shorteger=(unsigned char)abs((int)fshowPa);
- temp_dian=tmp_show-(float)shorteger;
-
- led_show1=shorteger/10;
- led_show2=shorteger%10;
- led_dian1=0;
- led_dian2=1;
-
- //小數(shù)點(diǎn)后兩位
- shordian=(unsigned char)(temp_dian*100.0);
- led_show3=shordian/10;
- led_show4=shordian%10;
- led_dian3=0;
- led_dian4=0;
- }
- unsigned short GetADCResult(unsigned char ch)
- {
- ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;
- while(!(ADC_CONTR&ADC_FLAG));
- ADC_CONTR &= ~ADC_FLAG;
-
- return (ADC_RES<<2)|(ADC_RESL&0x03);
- }
- //-20-0 0.5=4.5(102.4-921.6)
- void main(void)
- {
- unsigned short xdata sensorV;
- unsigned short xdata RtV;
- unsigned char xdata TimeShowRt=0;
- float xdata Actual;
- float xdata tmp_TimeMotor;
- float xdata SetSpeed;
- char xdata tmp_SetSpeed=-128;
- float xdata getSpeed;
- pid_t xdata gpid;
- //GPIO1
- PP1(0);//輸出
- PP1(1);//輸出
- PP1(2);//輸出
- PP1(3);//輸出
- RP1(4);//輸入
- RP1(5);//輸入
- //GPIO2
- PP2(0);//輸出
- PP2(1);//輸出
- PP2(2);//輸出
- PP2(3);//輸出
- PP2(4);//輸出
- PP2(5);//輸出
- PP2(6);//輸出
- PP2(7);//輸出
- //GPIO3
- PP3(2);//輸出
- PP3(3);//輸出
- PP3(4);//輸出
- PP3(5);//輸出
- RP3(6);//輸入
- PP3(7);//輸出
- InitUart();
- InitTime0();
- ADC_Init();
- EA = 1; // 打開總中斷
- SendTxdBuf(0x89);
- RtV=GetADCResult(4);
- SetSpeed=0.019531*RtV-20.0;
- tmp_SetSpeed=(char)SetSpeed;
- PID_init(&gpid);
- gpid.Kp=0.4;//作用是加快系統(tǒng)的響應(yīng)速度,提高系統(tǒng)的調(diào)節(jié)精度,副作用是會(huì)導(dǎo)致超調(diào);
- gpid.Ki=0.2;//作用是消除穩(wěn)態(tài)誤差,副作用是導(dǎo)致積分飽和現(xiàn)象
- gpid.Kd=0.2;//作用是改善系統(tǒng)的動(dòng)態(tài)性能,副作用是延長(zhǎng)系統(tǒng)的調(diào)節(jié)時(shí)間
- ……………………
- …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼
所有資料51hei提供下載:
軟件.rar
(112.24 KB, 下載次數(shù): 71)
2017-6-14 15:39 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|
|