1、/********************************************************************
模糊PID控制温控系统仿真设计C程序代码
********************************************************************/
#include
2、sbit SDO = P2^0; sbit SDI = P2^1; sbit CS = P2^2; sbit CLK = P2^3; sbit EOC = P2^4; sbit RS = P2^5; sbit RW = P2^6; sbit EN = P2^7; sbit KEY1= P3^0; sbit KEY2= P3^1; sbit KEY3= P3^2; sbit KEY4= P3^3; sbit KEY5= P3^4; sbit IN1 = P3^5; sbit IN2 = P3^6
3、 sbit ENA = P3^7; uchar flag; uchar flag_start; float S_temp=60.0; float P_temp=20.0; float Kp; float Ki; float Kd; float Err=0.0; float Last_Err=0.0; float D_Err=0.0; float Sum_Err=0.0; float U=0.0; /****************************** 函数功能:延时 *****
4、/ void delay_ms(uchar z) { uchar i; uchar j; for(i=z;i>0;i--) for(j=360;j>0;j--); } void delay_us(uchar z) { uchar i; for(i=z;i>0;i--); } void LCD_WriteData(uchar Dat) { RS = 1; P1 = Dat; delay_us(10); E
5、N = 1; delay_us(10); EN = 0; } void LCD_WriteCOM(uchar com) { RS = 0; P1 = com; delay_us(10); EN = 1; delay_us(10); EN = 0; } void Show_Num(uchar x,uchar y,uchar n,float num) { uchar a[3]; uchar i; uint Temp; Temp=(int)num;
6、 for(i=0;i
7、)num_Ki; Show_Num(10,2,1,Temp%10); Temp=Temp/10; Show_Num(9,2,1,Temp%10); Temp=Temp/10; Show_Num(7,2,1,Temp); } void Show_char(uchar x,uchar y,uchar ch) { if(y%2 == 1) LCD_WriteCOM(0x80+x); else LCD_WriteCOM(0x80+0x40+x); LCD_WriteData(ch); } v
8、oid LCD_Init(void) { RW = 0; EN = 0; LCD_WriteCOM(0x38); LCD_WriteCOM(0x0c); LCD_WriteCOM(0x06); LCD_WriteCOM(0x01); } /*********************************** 函数功能:显示函数 *************************************/ void LCD_display(void) { Show_char(1
9、1,'T'); delay_us(10); Show_char(0,1,'P'); delay_us(10); Show_char(1,1,'T'); delay_us(10); Show_char(2,1,':'); delay_us(10); Show_Num(3,1,3,P_temp); delay_us(10); Show_char(10,1,'S'); delay_us(10); Show_char(11,1,'T'); delay
10、us(10); Show_char(12,1,':'); delay_us(10); Show_Num(13,1,3,S_temp); delay_us(10); Show_char(0,2,'P'); delay_us(10); Show_char(1,2,':'); delay_us(10); Show_Num(2,2,2,Kp); delay_us(10); Show_char(5,2,'I');
11、 delay_us(10); Show_char(6,2,':'); delay_us(10); Show_char(8,2,'.'); delay_us(10); Show_Ki(Ki); delay_us(10); Show_char(12,2,'D'); delay_us(10); Show_char(13,2,':'); delay_us(10); Show_Num(14,2,2,Kd); delay_us(10); } /*****
12、 函数功能:定时器2初始化 *************************************/ void Timer2_Init() { RCAP2H =(65536-300)/256; RCAP2L =(65536-300)%256; TH2 = RCAP2H; TL2 = RCAP2L; ET2 = 1; TR2 = 1; EA = 1; } /************************************* 函数功能:键盘
13、扫描,调整设置温度 ****************************************/ void key_scan(void) { if(KEY1==0) { delay_ms(1); if(KEY1==0) { S_temp=S_temp+1; if(S_temp>=200) S_temp=200; while(!KEY1); } } if(KEY2==0) { delay_ms(1); if(KEY2==0) { if
14、S_temp>0) S_temp=S_temp-1; else if(S_temp<=0) S_temp=0; while(!KEY2); } } if(KEY3==0) { delay_ms(1); if(KEY3==0) { if(S_temp<=190) S_temp=S_temp+10; while(!KEY3); } } if(KEY4==0) { delay_ms(1
15、); if(KEY4==0) { if(S_temp>=10) S_temp=S_temp-10; while(!KEY4); } } if(KEY5==0) { delay_ms(1); if(KEY5==0) { flag_start=1; while(!KEY5); } } } /************************************ 函数功能:PID的计算 ********
16、/ void PID_Calculate() { Err = S_temp - P_temp; Sum_Err += Err; D_Err = Err - Last_Err; Last_Err = Err; U=Kp*Err+Ki*Sum_Err+Kd*D_Err; U=(int)U; if(U>=0) { if(U>=200) U=200; flag=1; } else
17、 { U=-U; if(U>=200) U=200; flag=0; } } /*********************************************** 函数功能:PID参数Kp的计算 ************************************************/ float fuzzy_kp(float e, float ec) //e,ec,表示误差,误差变化率 { float Kp_calcu; uchar num,pe,pec;
18、 float code eRule[7]={-3.0,-2.0,-1.0,0.0,1.0,2.0,3.0}; //误差E的模糊论域 float code ecRule[7]={-3.0,-2.0,-1.0,0.0,1.0,2.0,3.0}; //误差变化率EC的模糊论域 float eFuzzy[2]={0.0,0.0}; //隶属于误差E的隶属程度 float ecFuzzy[2]={0.0,0.0}; //隶属于误差变化率EC的隶属程度 float code kpRule[4]={0.0,8.0,16.0,24.0}; //Kp的
19、模糊子集
float KpFuzzy[4]={0.0,0.0,0.0,0.0}; //隶属于Kp的隶属程度
int code KpRule[7][7]= //Kp的模糊控制表
{
3,3,3,3,3,3,3,
2,2,2,2,1,2,2,
1,1,1,1,1,1,1,
1,1,0,1,0,1,1,
0,0,1,0,0,1,0,
0,1,0,1,0,0,2,
3,3,3,3,3,3,3
};
/*****误差E隶属函数描述*****/
if(e 20、eFuzzy[0] =1.0;
pe = 0;
}
else if(eRule[0]<=e && e 21、eRule[3] -e)/(eRule[3]-eRule[2]);
pe = 2;
}
else if(eRule[3]<=e && e 22、eRule[6])
{
eFuzzy[0] = (eRule[6]-e)/(eRule[6]-eRule[5]);
pe = 5;
}
else
{
eFuzzy[0] =0.0;
pe =5;
}
eFuzzy[1] =1.0 - eFuzzy[0];
/*****误差变化率EC隶属函数描述*****/
if(ec 23、 ecFuzzy[0] = (ecRule[1] - ec)/(ecRule[1]-ecRule[0]);
pec = 0 ;
}
else if(ecRule[1]<=ec && ec 24、 ;
}
else if(ecRule[3]<=ec && ec 25、 { ecFuzzy[0] = (ecRule[6]-ec)/(ecRule[6]-ecRule[5]);
pec=5;
}
else
{
ecFuzzy[0] =0.0;
pec = 5;
}
ecFuzzy[1] = 1.0 - ecFuzzy[0];
/*********查询模糊规则表*********/
num =KpRule[pe][pec];
KpFuzzy[num] += eFuzzy[0]*ecFuzzy[0];
num =KpRule[pe][pec+1];
KpFuzzy[num] 26、 += eFuzzy[0]*ecFuzzy[1];
num =KpRule[pe+1][pec];
KpFuzzy[num] += eFuzzy[1]*ecFuzzy[0];
num =KpRule[pe+1][pec+1];
KpFuzzy[num] += eFuzzy[1]*ecFuzzy[1];
/*********加权平均法解模糊*********/ Kp_calcu=KpFuzzy[0]*kpRule[0]+KpFuzzy[1]*kpRule[1]+KpFuzzy[2]*kpRule[2]
+KpFuzzy[3]*kpRule[3];
retur 27、n(Kp_calcu);
}
/***********************************************
函数功能:PID参数Ki的计算
************************************************/
float fuzzy_ki(float e, float ec)
{
float Ki_calcu;
uchar num,pe,pec;
float code eRule[7]={-3.0,-2.0,-1.0,0.0,1.0,2.0,3.0};
float co 28、de ecRule[7]={-3.0,-2.0,-1.0,0.0,1.0,2.0,3.0};
float eFuzzy[2]={0.0,0.0};
float ecFuzzy[2]={0.0,0.0};
float code kiRule[4]={0.00,0.01,0.02,0.03};
float KiFuzzy[4]={0.0,0.0,0.0,0.0};
int code KiRule[7][7]=
{
0,0,0,0,0,0,0,
0,0,0,0,0,0,0,
0,0, 29、0,0,0,0,0,
0,0,0,0,0,0,0,
0,0,0,0,0,0,0,
2,0,0,0,0,0,1,
3,3,3,3,3,3,3
};
/*****误差隶属函数描述*****/
if(e 30、e && e 31、 3;
}
else if(eRule[4]<=e && e 32、 /*****误差变化隶属函数描述*****/
if(ec 33、]-ecRule[1]);
pec = 1;
}
else if(ecRule[2]<=ec && ec 34、 ec 35、];
/***********查询模糊规则表***************/
num =KiRule[pe][pec];
KiFuzzy[num] += eFuzzy[0]*ecFuzzy[0];
num =KiRule[pe][pec+1];
KiFuzzy[num] += eFuzzy[0]*ecFuzzy[1];
num =KiRule[pe+1][pec];
KiFuzzy[num] += eFuzzy[1]*ecFuzzy[0];
num =KiRule[pe+1][pec+1];
KiFuzzy[num] += eFuzzy[1]*ec 36、Fuzzy[1];
/********加权平均法解模糊********/ Ki_calcu=KiFuzzy[0]*kiRule[0]+KiFuzzy[1]*kiRule[1]+KiFuzzy[2]*kiRule[2]
+KiFuzzy[3]*kiRule[3];
return(Ki_calcu);
}
/***********************************************
函数功能:PID参数Kd的计算
************************************************/
float 37、 fuzzy_kd(float e, float ec)
{
float Kd_calcu;
uchar num,pe,pec;
float code eRule[7]={-3.0,-2.0,-1.0,0.0,1.0,2.0,3.0};
float code ecRule[7]={-3.0,-2.0,-1.0,0.0,1.0,2.0,3.0};
float eFuzzy[2]={0.0,0.0};
float ecFuzzy[2]={0.0,0.0};
float code kdRule[ 38、4]={0.0,1.0,2.0,3.0};
float KdFuzzy[4]={0.0,0.0,0.0,0.0};
int code KdRule[7][7]=
{
3,3,3,2,2,2,2,
2,2,2,1,1,1,1,
1,1,2,1,1,2,1,
1,1,0,1,0,1,1,
1,1,0,0,0,1,1,
2,2,1,0 ,1,1,1,
3,3,3,3,2,3,2
};
/*****误差隶属函数描述*****/
if(e 39、1.0;
pe = 0;
}
else if(eRule[0]<=e && e 40、)/(eRule[3]-eRule[2]);
pe = 2;
}
else if(eRule[3]<=e && e 41、 {
eFuzzy[0] = (eRule[6]-e)/(eRule[6]-eRule[5]);
pe = 5;
}
else
{
eFuzzy[0] =0.0;
pe =5;
}
eFuzzy[1] =1.0 - eFuzzy[0];
/*****误差变化隶属函数描述*****/
if(ec 42、y[0] = (ecRule[1] - ec)/(ecRule[1]-ecRule[0]);
pec = 0 ;
}
else if(ecRule[1]<=ec && ec 43、 else if(ecRule[3]<=ec && ec 44、ecFuzzy[0] = (ecRule[6]-ec)/(ecRule[6]-ecRule[5]);
pec=5;
}
else
{
ecFuzzy[0] =0.0;
pec = 5;
}
ecFuzzy[1] = 1.0 - ecFuzzy[0];
/***********查询模糊规则表*************/
num =KdRule[pe][pec];
KdFuzzy[num] += eFuzzy[0]*ecFuzzy[0];
num =KdRule[pe][pec+1];
KdFuzzy[nu 45、m] += eFuzzy[0]*ecFuzzy[1];
num =KdRule[pe+1][pec];
KdFuzzy[num] += eFuzzy[1]*ecFuzzy[0];
num =KdRule[pe+1][pec+1];
KdFuzzy[num] += eFuzzy[1]*ecFuzzy[1];
/********加权平均法解模糊********/
Kd_calcu=KdFuzzy[0]*kdRule[0]+KdFuzzy[1]*kdRule[1]+KdFuzzy[2]*kdRule[2]
+KdFuzzy[3]*kdRule[3];
46、return(Kd_calcu);
}
/*****************************************
函数功能:AD将采集到的温度进行转化
********************************************/
uint read_tlc2543(uchar port)
{
static uchar PORT = 0;
uchar Temp,i,k=0;
uint AD_value=0;
Temp = port;
CS = 1;
CLK = 0;
Te 47、mp<<=4;
CS = 0;
while(1)
{
for(i=0;i<8;i++)
{
CLK = 0;
if(Temp&0x80)
SDI = 1;
else
SDI = 0;
AD_value<<=1;
if(SDO)
AD_value |= 0x01;
CLK = 1;
Temp<<=1;
}
for(i=8;i<12;i++)
{
CLK = 0;
48、AD_value<<=1;
if(SDO)
AD_value |= 0x01;
delay_us(10);
CLK = 1;
}
CLK = 0;
CS = 1;
if(PORT == port)
break;
else
{
Temp = port;
Temp<<=4;
delay_us(10);
CS = 0;
AD_value = 0;
}
k++;
i 49、f(k>2)
{
PORT = port;
}
}
return AD_value;
}
float AD_deal(void)
{
uint AD_value;
float temp;
AD_value = read_tlc2543(0x00);
temp = AD_value*number;
return temp;
}
/*********主函数**********/
void main(void)
{
uchar AD_value=0;
flag=0;
50、flag_start=0;
ENA=1;
IN1=0;
IN2=0;
LCD_Init();
LCD_display();
Timer2_Init();
while(1)
{
if(flag_start==0)
{
key_scan();
Show_Num(13,1,3,S_temp);
Show_Num(3,1,3,P_temp);
}
else if(flag_start==1)
{
P_temp=AD_deal();
Show_Num(3,1,3,P_temp);






