实现了升温,降温控制,用了pid算法
单片机源程序如下:
- #include <REG51.H>
- #define Kp 18 //比例系数 18
- #define Ki 13 //积分系数 13
- #define Kd 0.8 //微分系数 0.3
- unsigned char m,n,p; //温度的十位 个位 小数
- unsigned char test_temp; //温度检定标志
- unsigned char key_set_flag; //按键设定进入标志
- unsigned char flag=1; //按键保持标志
- unsigned char Change_step=1; //温度设置步进
- unsigned char T0_H = 0,T0_L = 0,T1_H=0,T1_L=0,T0h=0,T0l=0;
- unsigned char t0=0,t1=0;
- int Real_temp; //实际温度值
- int Set_temp; //设置温度
- int Disp_temp; //显示温度
- int last_error; //上次误差
- float I_term; //前面温差和
- bit key_hold;
- int PID_MAX;
- unsigned int out,PWMT,counter,kk,outp;
- int time; //脉冲触发时刻
- sbit DQ=P1^0; //定义DS18b20的管脚 1.0
- sbit L1=P2^0; //定义控制数码管的管脚
- sbit L2=P2^2;
- sbit L3=P2^4;
- sbit L4=P2^6;
- sbit k1=P3^3;
- sbit k2=P3^4;
- sbit k3=P3^5;
- sbit PWM=P2^7; //PWM控制脚
- //sbit jia=P2^5;
- unsigned char table[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x7F,0xbF,0xC6};//0-9数字,后面为". - C"
- /*****延时子程序*****/
- void delay(unsigned int t)
- {
- for(;t>0;t--);
- }
- void delay_50us(unsigned int t)
- {
- unsigned char j;
- for(;t>0;t--)
- for(j=19;j>0;j--);
- }
- /*****初始化DS18B20*****/
- unsigned char Init_DS18B20(void)
- {
- unsigned char x=0;
- DQ = 1; //DQ复位
- delay(8); //稍做延时
- DQ = 0; //单片机将DQ拉低
- delay(80); //精确延时,大于480us
- DQ = 1; //拉高总线
- delay(8);
- x = DQ; //稍做延时后,如果x=0则初始化成功,x=1则初始化失败
- delay(4);
- return x;
- }
- /*****读一个字节*****/
- unsigned char ReadOneChar(void)
- {
- unsigned char i=0;
- unsigned char dat = 0;
- for (i=8;i>0;i--)
- {
- DQ = 0; // 给脉冲信号
- dat>>=1;
- DQ = 1; // 给脉冲信号
- if(DQ)
- dat|=0x80;
- delay(4);
- }
- return(dat);
- }
- /*****写一个字节*****/
- void WriteOneChar(unsigned char dat)
- {
- unsigned char i=0;
- for (i=8; i>0; i--)
- {
- DQ = 0;
- DQ = dat&0x01;
- delay(4);
- DQ = 1;
- dat>>=1;
- }
- delay(4);
- }
- /*****读取温度*****/
- int ReadTemperature(void)
- {
- unsigned char a=0;
- unsigned char b=0;
- unsigned int t=0;
- t=Init_DS18B20();
- if(t) return Real_temp;
- WriteOneChar(0xCC); //跳过读序号列号的操作
- WriteOneChar(0x44); //启动温度转换
- t=Init_DS18B20();
- if(t) return Real_temp;
- WriteOneChar(0xCC); //跳过读序号列号的操作
- WriteOneChar(0xBE); //读取温度寄存器
- a=ReadOneChar(); //读低8位
- b=ReadOneChar(); //读高8位
- t=b;
- t<<=8;
- t=t|a;
- if(t<=0||t>0x900)
- return Real_temp;
- t=t*0.625+0.5;
- return(t);
- }
- void display(signed int dd)//数码管扫描函数
- {
- int tt=0;
- tt= dd; //放大10倍输出并四舍五入
- m=tt/100; //分离出十位
- n=(tt%100)/10; //分离出个位
- p=tt%10; //分离出小数位
- //m
- P0=table[12];
- L1=0; //暂未1,如用三极管驱动要改为0 L1
- delay(300);
- L1=1; //后关闭显示
- P0=table[n]; //n
- L3=0; //L2
- delay(300);
- L3=1;
- P0=table[10]; //10
- L3=0; //L2
- delay(300);
- L3=1;
- P0=table[p]; //小数部分p
- L2=0; //L3
- delay(300);
- L2=1;
- P0=table[m]; //12
- L4=0;
- delay(300);
- L4=1;
- }
- void key_set(void)
- {
- if(k1==0)
- {
- delay(10);
- while(!k1);
- key_hold=~key_hold;
- }
- if(key_hold==0)
- {
- if(k2==0)
- {
- delay(10);
- while(!k2);
- Set_temp=Set_temp+1;
- if(Set_temp>99)
- Set_temp=99;
- }
- }
- if(key_hold==0)
- {
- if(k3==0)
- {
- delay(10);
- while(!k3);
- Set_temp=Set_temp-1;
- if(Set_temp<1)
- Set_temp=1;
- }
- }
- }
- int PID(int Set_value,int Real_value) //标准PID温度控制算法
- {
- float uk ,uk1 ,duk;
- int pid_out,e ,e1 ,e2;
- e=Set_value-Real_value;//误差量
- duk=Kp*(e-e1)+Ki*e+Kd*(e-2*e1+e2); //+Kd*(e-2e1+e2)
- uk=uk1+duk;
- pid_out=(int)uk;
- uk1=uk;
- e2=e1;
- e1=e;
- if(pid_out>1000) //1000
- {
- pid_out=990;// 990
- }
- else if(pid_out<10) //10
- {
- pid_out=10; //10
- }
- outp=pid_out;
- return(pid_out);
-
- }
- void T0_int(void) interrupt 1
- {
- T0_H = (65535-2000)/256; //PWM=1高位初值计算
- T0_L = (65535-2000)%256; //PWM=1低位初值计算
- TH0 = T0_H; //通的初值高位
- TL0= T0_L; //通的初值低位
- kk++;
- if(kk>1000)
- kk=0;
- if(kk>outp)
- {PWM=1;
- // jia=1;
- }
- else {PWM=0;
- //jia=0;
- }
-
-
- }
-
- void main()
- {
- PWMT=128; //128级步进PWM控制
- PID_MAX=PWMT;
- counter=0;
- out=0;
- PWM=1;
- // jia=1;
- I_term=0;
- last_error=0;
- Set_temp=40; //初始设定温度为41度
- Real_temp=Set_temp*10;
- key_hold=1;
- Init_DS18B20();
- WriteOneChar(0xCC); //跳过读序号列号的操作
- WriteOneChar(0x44); //启动温度转换
- delay_50us(15000); //等待温度测量 15000
- TMOD=0x01; //定时器0模式1
- TR0=1;
- ET0=1;
- IT0=1;
- EX0=1;
- EA=1;
-
- while(1)
- {
- counter++;
- if(counter>40) //if(counter>40)
- {
- test_temp=1; //进行一次温度检定
- counter=0;
- }
- if(test_temp) //温度检定标志置位,进入温度PID调节
- {
- Real_temp=ReadTemperature(); //采集当前实际温度
- if(Real_temp>Set_temp*10)
- PWM=1;
- else
- PID(Set_temp*10,Real_temp); //PID程序
- test_temp=0; //检定完成,清温度检定标志
- }
- if(key_hold)
- Disp_temp=Real_temp;
- else Disp_temp=Set_temp;
- display(Disp_temp);
- key_set(); //按键温度设置
- }
- }
复制代码
所有资料51hei提供下载:
水温控制系统1.zip
(338.66 KB, 下载次数: 532)
|