標(biāo)題:
STC單片機(jī)關(guān)于PID控制氣壓的算法,led數(shù)據(jù)碼顯示
[打印本頁]
作者:
niping321
時(shí)間:
2017-6-14 15:39
標(biāo)題:
STC單片機(jī)關(guān)于PID控制氣壓的算法,led數(shù)據(jù)碼顯示
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)先級
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é)精度,副作用是會導(dǎo)致超調(diào);
gpid.Ki=0.2;//作用是消除穩(wěn)態(tài)誤差,副作用是導(dǎo)致積分飽和現(xiàn)象
gpid.Kd=0.2;//作用是改善系統(tǒng)的動態(tài)性能,副作用是延長系統(tǒng)的調(diào)節(jié)時(shí)間
……………………
…………限于本文篇幅 余下代碼請從51黑下載附件…………
復(fù)制代碼
所有資料51hei提供下載:
軟件.rar
(112.24 KB, 下載次數(shù): 71)
2017-6-14 15:39 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
作者:
10149151
時(shí)間:
2023-10-10 22:55
學(xué)習(xí)pid
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1