單片機(jī)PID溫控源代碼
CopyLeft(CL) FORVERE Wjj
All rights NOT reserved
版權(quán)所無,翻版不究,但請(qǐng)保留此處信息
http://blog.sina.com.cn/u/2150397142
any problem or suggestion mail to: 15258297408@163.com
*******************************************/
*文件名:PID_control
*文件說明: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è)試通過,溫度維持在33℃-35℃
*說明: 采用PID算法處理的溫控模擬系統(tǒng) ,ADC0809采集數(shù)據(jù),IN4148為溫度傳感器,LCD顯示
========================================*/
#includereg51.h> //加載C51核心庫文件
#includeintrins.h> //加載應(yīng)用型庫文件
#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)(P00x80);
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(rltempsettemp) // 如果實(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(uk0)
{
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(uk0)
{
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;i15;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;i6;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=======================================*/
評(píng)論