/*=========================================================================== CopyLeft(CL) FORVERE Wjj All rights NOT reserved 版權(quán)所無(wú),翻版不究,但請(qǐng)保留此處信息 http://blog.sina.com.cn/u/2150397142 any problem or suggestion mail to: 15258297408@163.com **************************************************************************************************************************/ *文件名:PID_control *文件說(shuō)明:PID溫控源代碼,采用PID算法處理的溫控模擬系統(tǒng) ,ADC0809采集數(shù)據(jù),IN4148為溫度傳感器 *版本: The final version *芯片: STC89C52RC *晶振: (外)內(nèi)部12MHz晶振 *作者: Wang Jian Jun *日期: 2010年5月27日 *編譯環(huán)境: keil3+proteus7 *結(jié)果: 實(shí)物測(cè)試通過(guò),溫度維持在33℃-35℃ *說(shuō)明: 采用PID算法處理的溫控模擬系統(tǒng) ,ADC0809采集數(shù)據(jù),IN4148為溫度傳感器,LCD顯示 =============================================================================*/ #include<reg51.h> //加載C51核心庫(kù)文件 #include<intrins.h> //加載應(yīng)用型庫(kù)文件 #include"config.h" //加載用戶自配置可文件,此處未給出 #define N0 40536 #define nop() _nop_() #define uchar unsigned char #define uint unsigned int //以上宏定義,方便寫代碼 /*程序中變量 數(shù)組定義*/ uchar idata table[]={"Real-time Temp:"}; //第一行顯示"Real-time Temp:" uchar idata table1[5]; uchar data1; uchar kp; uchar ki; uchar kd; //以上為PID算法的比例,積分,微分系數(shù) uint t,hightime,count; //占空比調(diào)節(jié)參數(shù) uint rltemp,settemp=350; int e1,e2,e3,duk,uk; /*引腳定義*/ sbit EOC=P2^6; sbit OE=P2^5; sbit START=P2^7; sbit lcden=P3^2; sbit lcdrw=P3^1; sbit lcdrs=P3^0; sbit pwm=P3^3; /****************************** 延時(shí)子程序 *******************************/ void delay(uint z) { uint x,y; for(x=z;x>0;x--) for(y=29;y>0;y--); } /****************************** LCD忙檢測(cè) *******************************/ bit lcd_busy() { bit result; lcdrw = 1; lcdrs = 0; lcden = 1; nop();nop();nop();nop(); result = (bit)(P0&0x80); lcden = 0; return(result); } /****************************** LCD寫命令子程序 *******************************/ void write_com(uchar com) { while(lcd_busy());//忙等待 lcdrs = 0; lcdrw = 0; P1 = com; delay(5); lcden = 1; delay(5); lcden = 0; } /****************************** LCD寫數(shù)據(jù)子程序 *******************************/ void write_data(uchar date) { while(lcd_busy()); //忙等待 lcdrs = 1; lcdrw = 0; P1=date; delay(5); lcden = 1; delay(5); lcden = 0; } /****************************** LCD初始化 *******************************/ void lcd_init() { lcden = 0; write_com(0x38); delay(5); write_com(0x0f); delay(5); write_com(0x06); delay(5); write_com(0x01); delay(5); write_com(0x80); delay(5); write_com(0x01); } /****************************** 定時(shí)器初始化 *******************************/ void time_init() { EA = 1; ET0 = 1; ET1 = 1; TR0 = 1; TR1 = 1; TMOD = 0x11; TH0 = N0/256; TL0 = N0%256; TH1 = 0X3C; TL1 = 0XB0; } /****************************** PID算法系數(shù)設(shè)置 *******************************/ void Pid_init() { hightime= 0; e1 = 0; e2 = 0; e3 = 0; kp = 10; ki = 5; kd = 5; } /****************************** 溫度比較 PID算法 *******************************/ void pid_ys() { if(rltemp<settemp) // 如果實(shí)際溫度小于設(shè)定值 { if(settemp-rltemp>20) // 如果相差2度 { hightime=100; //全速加熱 } else //否則運(yùn)行PID算法進(jìn)行平滑加熱 { e1 = settemp-rltemp; duk=(kp*(e1-e2)+ki*e1+kd*(e1-e2*2+e3))/10; uk = uk+duk; if(uk>100) uk = 100; else if(uk<-100) uk = -100; if(uk<0) { hightime=-uk; } else { hightime=uk; } e3 = e2; e2 = e1; } } if(rltemp>=settemp) // 如果實(shí)際溫度大于設(shè)定值 { if(rltemp-settemp>0) //只要實(shí)際溫度與設(shè)定值有偏差 { hightime=0; //停止加熱 } else //其他情況運(yùn)行PID算法,但參數(shù)與前面的剛好相反 { e1 = rltemp-settemp; duk=(kp*(e1-e2)+ki*e1+kd*(e1-e2*2+e3))/10; uk = uk+duk; if(uk>100) uk = 100; else if(uk<-100) uk = -100; if(uk<0) { hightime=100-(-uk); } else { hightime=100-uk; } e3 = e2; e2 = e1; } } } /****************************** 主函數(shù) *******************************/ void main() { uint i; time_init();//定時(shí)器初始化 Pid_init(); // PID初始化 lcd_init(); // LCD初始化 table1[5]=0x43; table1[4]=0xdf; table1[2]=0x2e; //小數(shù)點(diǎn) 攝氏度符號(hào)ASCII碼 for(i=0;i<15;i++) //帶循環(huán)第一行顯示"Real-time Temp:" { write_data(table[i]); delay(20); } while(1) { t=data1*196/100; table1[3]=(t%100)%10+0x30; table1[1]=(t%100)/10+0x30; table1[0]=t/100+0x30; //以上溫度數(shù)據(jù)轉(zhuǎn)化 rltemp = t; //給PID算法裝載實(shí)際值 write_com(0x80+0x45);//寫LCD第二行的初地址 for(i=0;i<6;i++) //該循環(huán)顯示溫度值 { write_data(table1[i]); delay(20); } pid_ys();//運(yùn)行溫度比較 PID算法 } } /****************************** 溫度采集轉(zhuǎn)換的定時(shí)中斷 0.5s刷新一次數(shù)據(jù) *******************************/ void timer0() interrupt 1 { uint j; j++; if(j==20) { OE = 0; START = 0; _nop_(); START = 1; _nop_(); START = 0; while(EOC==0); OE = 1; _nop_(); data1 = P0; _nop_(); OE = 0; j = 0; } TH0=N0/256; TL0=N0%256; } /****************************** PWM波輸出的定時(shí)中斷 *******************************/ void timer1() interrupt 3 { if(++count<=(hightime)) pwm=0; else if(count<=100) { pwm=1; } else count=0; TH1=0x3c; TL1=0xb0; } /*==============================end of file=======================================*/