#include #include #define nop() _nop_() #define uchar unsigned char #define uint unsigned int /*程序中变量数组定义*/ uchar idata table[]={" Real-time Temp:"};//第一行显示"Real-time Temp:" uchar idata table1[7]; uint data1,kp,ki,kd; uint t,hightime,count; //占空比调节参数 uint rltemp,settemp=512; //50度512 75度768 5v输入为1024 int e1,e2,e3,uk; int duk; /*引脚定义*/ sbit ADIN=P1^7; sbit key50=P3^3; sbit key75=P3^4; sbit lcdrs=P3^7; sbit lcdrw=P1^0; sbit lcden=P1^1; sbit pwm=P3^5; /****************************** 延时子程序 *******************************/ void delay(uint z) { uint x,y; for(x=z;x>0;x--) for(y=29;y>0;y--); } //延时31*z us /****************************** LCD忙检测 *******************************/ 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; P2 = com; delay(5); lcden = 1; delay(5); lcden = 0; } /****************************** LCD写数据子程序 *******************************/ void write_data(uchar date) { while(lcd_busy()); //忙等待 lcdrs = 1; lcdrw = 0; P2=date; delay(5); lcden = 1; delay(5); lcden = 0; } /****************************** LCD初始化 *******************************/ void lcd_init() { lcden = 0; write_com(0x38); delay(5); write_com(0x0c); delay(5); write_com(0x06); delay(5); write_com(0x01); delay(5); write_com(0x80); delay(5); write_com(0x01); } /*************************** AD转换函数 ***************************/ unsigned int ADC_Conversion() { unsigned int temp; unsigned char temp1; ADC_CONTR=0x87; delay(32);//延时1ms //通道P1^7,设定转换时间840*1.085us=911.4us ADC_CONTR=0x8f; //启动转换 delay(50); ADC_CONTR=0x87; delay(32); temp=ADC_DATA; temp1=ADC_LOW2; temp1=temp1&0x03; temp=temp*4+temp1; return temp; } /****************************** 定时器初始化 *******************************/ void time_init() { EA = 1; ET0 = 1; ET1 = 1; TR0 = 1; TR1 = 1; TMOD = 0x11; TH0 = 0X9E; TL0 = 0X58; TH1 = 0XFF; TL1 = 0XB0; } /*两个定时器均为方式1 timer0温度采集定时中断11.0592 xtal 0.025s timer1PWM波输出的定时中断 11.0592 xtal 0.05s */ /****************************** PID算法系数装载 *******************************/ void Pid_init() { hightime= 0; e1 = 0; e2 = 0; e3 = 0; kp = 10; ki = 3; kd = 1; duk = 0; } /****************************** 温度比较 PID算法 *******************************/ void pid_ys() { if(rltemp20) // 如果相差2度 { hightime=100; //全速加热 } else //否则运行PID算法进行平滑加热 { e1 = settemp-rltemp; duk=(kp*(e1-e2)+ki*e1+kd*(e1-e2*2+e3))/44; uk = uk+duk; // uk=50; 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) // 如果实际温度不小于设定值 { if((rltemp-settemp)>0) //只要实际温度大于设定值 { hightime=0; //停止加热 ; //???? } else //其他情况运行PID算法,但参数与前面的刚好相反 { e1 = rltemp-settemp; duk=(kp*(e1-e2)+ki*e1+kd*(e1-e2*2+e3))/44; 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; } } } /****************************** 主函数 *******************************/ void main() { uint i; P1M0=0x80; P1M1=0x00; lcd_init(); // LCD初始化 Pid_init(); //PID参数初始化 time_init();//定时器初始化 table1[6]=0x43; table1[5]=0xdf; table1[3]=0x2e; for(i=0;i<16;i++) { write_data(table[i]); delay(20); } while(1) { t=(unsigned long)data1*500/512; table1[4]=t%10+0x30; table1[2]=(t/10)%10+0x30; table1[1]=(t/100)%10+0x30; table1[0]=(t/1000)%10+0x30; rltemp =data1; //给PID算法装载实际值 write_com(0x80+0x45); //写LCD第二行的初地址 for(i=0;i<7;i++) //该循环显示温度值 { write_data(table1[i]); delay(20); } if (key50==0) { delay(100);//延时3ms if (key50==0) settemp=512; } if (key75==0) { delay(100); if (key75==0) settemp=768; } pid_ys();//运行温度比较PID算法 } } /****************************** 温度采集转换的定时中断 0.5s刷新一次数据 *******************************/ void timer0() interrupt 1 { uint j; j++; if(j==20) { data1=ADC_Conversion(); j=0; } TH0=0x9E; TL0=0X58; } /****************************** PWM波输出的定时中断 *******************************/ void timer1() interrupt 3 { if(++count<=(hightime)) pwm=0; else if(count<=100) { pwm=1; } else count=0; TH1=0xFF; TL1=0xB0; } //pwm=0加热