STC单片机做了一个关于PID控制气压的算法,led数据码显示
单片机源程序如下:
- #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;//定义设定值
- float ActualSpeed;//定义实际值
- float err;//定义偏差值
- float err_last;//定义上一个偏差值
- float Kp,Ki,Kd;//定义比例、积分、微分系数
- float voltage;//定义电压值(控制执行器的变量)
- 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; //延时1ms, 主程序在此节拍下运行
- while(--j) ;
- }while(--dly);
- }
- void InitUart(void)
- {
- SCON = 0x50;//工作在串口模式
- T2L = (65536 - (MAIN_Fosc/4/BAUD)); //设置波特率为重新装值
- T2H = (65536 - (MAIN_Fosc/4/BAUD))>>8;
- AUXR |= 0x14; //启用定时器T2为1T模式, 并启用定时器2
- AUXR |= 0x01; //选择定时器2为串口1的波特率发生器
- 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; //高优先级
- TR0 = 1; //Timer0 Run
- }
- // ADC初始化函数
- void ADC_Init(void)
- {
- // ADC_ch=0;
- // P1ASF=0x30;//设置P1为ADC
- // //P1ASF|=(1<<4)|(1<<5);
- // ADC_RES=0; // 清除结果寄存器
- // ADC_CONTR=ADC_POWER|ADC_SPEEDLL|ADC_START|4;
- // Delay_n_ms(20);
- // EADC=1;// EADC=1 允许ADC中断
-
- //查询方式
- P1ASF=0x30;//设置P1为ADC
- ADC_RES=0;
- ADC_RESL=0;
- ADC_CONTR=ADC_POWER|ADC_SPEEDLL;
- Delay_n_ms(20);
- }
- void SendTxdBuf(unsigned char ASC) //发送-个ASCII
- {
- ES = 0; //关闭串口中断
- 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;//低电平打开电机
- }
- 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;
-
- //小数点后两位
- 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;//作用是加快系统的响应速度,提高系统的调节精度,副作用是会导致超调;
- gpid.Ki=0.2;//作用是消除稳态误差,副作用是导致积分饱和现象
- gpid.Kd=0.2;//作用是改善系统的动态性能,副作用是延长系统的调节时间
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
软件.rar
(112.24 KB, 下载次数: 71)
|