|
基于51單片機的DS18B20水溫PID控制調(diào)節(jié)系統(tǒng)設(shè)計C語言程序,通過51單片機控制可控硅驅(qū)動加過零檢測電路作為功率控制電路來控制加熱過程,通過鍵盤掃描來設(shè)定水溫,DS18B20實時測量水的溫度,將實際水溫與設(shè)定水溫比較,通過PID控制算法調(diào)節(jié),是實際水溫與設(shè)定水溫接近。從而達(dá)到控制水溫的目的。
電路原理圖如下:
1.jpg (55.38 KB, 下載次數(shù): 59)
下載附件
2018-11-19 18:25 上傳
單片機源程序如下:
- #include ‘reg52.h’
- #include ‘stdio.h’
- #define uchar unsigned char
- #define uint unsigned int
- sbit s1=P2^0;
- sbit s2=P2^1;
- sbit s3=P2^2;
- sbit s4=P2^3;
- sbit s5=P2^4;
- sbit ds=P2^5;
- sbit beep=P2^6;
- sbit rd=P1^0;
- sbit rs=P1^1;
- sbit wr=P1^2;
- sbit lcden=P1^3;
- sbit PWM=P1^6;
- sbit led1=P1^4;
- sbit led2=P1^5;
- uchar set_temp,keytemp;
- uint temp;
- uchar c;
- bit flag,flag1,flag2;
- float f_temp,t;
- int timecount,z;
- float KP,KI,KD;
- float e1,e2,e3;
- float uk,duk;
- uchar HighL,HighH,PWMH;
- float k;
- uchar code table[]={"設(shè)定溫度:"};
- uchar code table1[]={"實測溫度:"};
- uchar code table2[]={"加熱"};
- uchar code table3[]={"保溫"};
- uchar code table4[]={"作者:0903鋒仔@"};
- uchar code table5[]={"系統(tǒng)初始化"};
- uchar code table6[]={"measured Temperature"};
- uchar code table7[]={"水溫控制系統(tǒng)設(shè)計"};
- uchar code table8[]={" "};
- void delay(uint z)//延時函數(shù),延時5ms
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
- }
- void keyscan()
- {
- if(set_temp>=100)//將設(shè)定溫度限定在0-100度之間
- set_temp=100;
- if(set_temp<=0)
- set_temp=0;
- if(s5==0)//此鍵按下設(shè)定溫度加5
- {
- delay(10);
- if(s5==0)
- {
- flag1=0;
- set_temp+=5;
- if(set_temp>=100)
- {
- set_temp=100;
- beep=0;
- delay(1000);
- beep=1;
- }
- }while(s5==0);
- }
- if(s4==0)//此鍵按下設(shè)定溫度減5
- {
- delay(10);
- if(s4==0)
- {
- flag1=0;
- set_temp-=5;
- if(set_temp<=0)
- {
- set_temp=0;
- beep=0;
- delay(1000);
- beep=1;
- }
- }while(s4==0);
- }
- if(s3==0)//此鍵按下設(shè)定溫度加1
- {
- delay(10);
- if(s3==0)
- {
- flag1=0;
- set_temp++;
- if(set_temp==100)
- {
- set_temp=100;
- beep=0;
- delay(1000);
- beep=1;
- }
- }while(s3==0);
- }
- if(s2==0)//此鍵按下設(shè)定溫度減1
- {
- delay(10);
- if(s2==0)
- {
- flag1=0;
- set_temp--;
- if(set_temp==0)
- {
- set_temp=0;
- beep=0;
- delay(1000);
- beep=1;
- }
- }while(s2==0);
- }
- if(s1==0)//確定加熱狀態(tài)(加熱與不加熱)
- {
- delay(10);
- if(s1==0)
- {
- flag1=1;
- }
- while(s1==0);
- }
- }
- void dsreset()//DS18B20復(fù)位函數(shù)
- {
- uint i;
- ds=0;
- i=103;
- while(i>0)i--;
- ds=1;
- i=4;
- while(i>0)i--;
- }
- bit tempreadbit()//從DS18B20 RAM讀一位數(shù)據(jù)
- {
- uint i;
- bit dat;
- ds=0;i++;
- ds=1;i++;i++;
- dat=ds;
- i=8;while(i>0)i--;
- return(dat);
- }
- uchar tempread()//從DS18B20 RAM讀一字節(jié)數(shù)據(jù)
- {
- uchar i,j,dat;
- dat=0;
- for(i=1;i<=8;i++)
- {
- j=tempreadbit();
- dat=(j<<7)|(dat>>1);
- }
- return(dat);
- }
- void tempwritebyte(uchar dat)//向DS18B20寫以字節(jié)的數(shù)據(jù)
- {
- uint i,j;
- bit testb;
- for(j=1;j<=8;j++)
- {
- testb=dat&0x01;
- dat=dat>>1;
- if(testb)//寫1
- {
- ds=0;
- i++;i++;
- ds=1;
- i=8;while(i>0)i--;
- }
- else//寫0
- {
- ds=0;
- i=8;while(i>0)i--;
- ds=1;
- i++;i++;
- }
- }
- }
- void tempchange()//啟動溫度轉(zhuǎn)換
- {
- dsreset();
- delay(1);
- tempwritebyte(0xcc);
- tempwritebyte(0x44);
- }
- float get_temp()//溫度值讀取與處理函數(shù)
- {
- uchar a,b;
- dsreset();
- delay(1);
- tempwritebyte(0xcc);
- tempwritebyte(0xbe);
- a=tempread();
- b=tempread();
- temp=b;
- temp<<=8;
- temp=temp|a;
- f_temp=(float)(temp*0.0625);
- f_temp=f_temp*10;
- return(f_temp);
- }
- void write_com(uchar com)//向12864寫指令
- {
- rs=0;
- wr=0;
- delay(1);
- P0=com;
- lcden=1;
- delay(1);
- lcden=0;
- delay(1);
- }
- void write_date(uchar date)//向12864寫數(shù)據(jù)
- {
- rs=1;
- wr=0;
- delay(1);
- P0=date;
- lcden=1;
- delay(1);
- lcden=0;
- delay(1);
- }
- void display(float m,uchar n)//顯示設(shè)定溫度、實測溫度、加熱狀態(tài)
- {
- uint i,j;
- float b;
- float p;
- uchar a1,a2,a3;
- uchar b1,b2,b3,b4;
- if(n<100)
- {
- a1=0;
- a2=n/10;
- a3=n;
- }
- else
- {
- a1=1;
- a2=0;
- a3=0;
- }
- p=m;
- j=(uint)(p*10);
- b1=(uchar)(j/1000);
- b2=(uchar)(j00/100);
- b3=(uchar)(j0/10);
- b4=(uchar)(j);
- write_com(0x90+5);//顯示設(shè)定溫度
- write_date(0x30+a1);
- write_date(0x30+a2);
- write_date(0x30+a3);
- write_com(0x88+5);//顯示實測溫度
- write_date(0x30+b1);
- write_date(0x30+b2);
- write_date(0x2e);
- write_date(0x30+b3);
- write_date(0x30+b4);
- b=((float)(b1*100+b2*10+b3))/10.0;
- i=0;
- if((b+0.2)
- {
- led1=0;
- write_com(0x98+1);
- while(table2[i]!='\0')
- {
- write_date(table2[i]);
- i++;
- }
- flag2=1;
- }
- else
- {
- led1=1;
- i=0;
- write_com(0x98+1);
- while(table8[i]!='\0')
- {
- write_date(table8[i]);
- i++;
- }
- i=0;
- if((b=n)||((b>n)&&((b-0.2)<=n))||((b=n)))
- {
- led2=0;
- write_com(0x98+4);
- while(table3[i]!='\0')
- {
- write_date(table3[i]);
- i++;
- }
- }
- }
- if(flag2==1)
- {
- flag2=0;
- led2=1;
- i=0;
- write_com(0x98+4);
- while(table8[i]!='\0')
- {
- write_date(table8[i]);
- i++;
- }
- }
- }
- void conversion()//定時器2初值處理函數(shù)
- {
- uint temp2;
- temp2=65536-PWMH*10;
- HighH=temp2/256;
- HighL=temp2%6;
- }
- void senddate(float y)
- {
- // uint i;
- if(flag==1)
- {
- ES=0;
- flag=0;
- c=0;
- TI=1;
- printf("The measured temp:%f",y);
- // SBUF=1;
- while(!TI);
- TI=0;
- ES=1;
- }
- }
- void init()//初始化函數(shù)
- {
- uint i,j;
- TMOD=0x21;
- TH1=0xfd;
- TL1=0xfd;
- TH0=(65536-50000)/256;
- TL0=(65536-50000)%6;
- PWMH=0;
- conversion();
- TH2=(65536-50000)/256;
- TL2=(65536-50000)%6;
- rd=1;
- lcden=0;
- write_com(0x30);
- write_com(0x0c);
- write_com(0x01);
- write_com(0x90);
- while(table5[i]!='\0')//系統(tǒng)初始化
- {
- write_date(table5[i]);
- i++;
- delay(20);
- }
- for(j=0;j<=1;j++)//6個點的三次循環(huán)
- {
- write_com(0x88+4);
- for(i=0;i<=5;i++)
- {
- write_date(0x2e);
- delay(200);
- }
- delay(100);
- write_com(0x88+4);
- for(i=0;i<=5;i++)
- {
- write_date(0x20);
- }
- delay(100);
- }
- i=0;
- write_com(0x80);//顯示 水溫控制系統(tǒng)設(shè)計標(biāo)題
- while(table7[i]!='\0')
- {
- write_date(table7[i]);
- i++;
- }
- i=0;
- write_com(0x90);//顯示 設(shè)定溫度
- while(table[i]!='\0')
- {
- write_date(table[i]);
- i++;
- }
- i=0;
- write_com(0x88);//顯示 實測溫度
- while(table1[i]!='\0')
- {
- write_date(table1[i]);
- i++;
- }
- // tempwritebyte(0x4e);//設(shè)定DS18B20的分辨率為11位
- // tempwritebyte(0x5f);
- PWM=0;
- e1=0;
- e2=0;
- e3=0;
- duk=0;
- uk=0;
- KP=20;//PID控制算法參數(shù)
- KI=0.061;
- KD=30;
- REN=1;//串口通信設(shè)置
- SM0=0;
- SM1=1;
- ET0=1;
- ET2=1;
- TR0=1;
- TR1=1;
- TR2=1;//啟動定時器2
- EA=1;
- ES=1;
- }
- void main()
- {
- init();
- while(1)
- {
- keyscan();//調(diào)用鍵盤掃描函數(shù)
- tempchange();//啟動溫度轉(zhuǎn)換
- t=get_temp();//提取實測溫度
- display(t,set_temp);//顯示設(shè)定溫度和實測溫度
- senddate(t);//向上位機發(fā)送數(shù)據(jù)函數(shù)
- if((flag1==1))
- {
- if(timecount>=375)
- {
- timecount=0;
- e1=set_temp-t;
- duk=(KP*(e1-e2)+KI*e1+KD*(e1-2*e2+e3));//PID控制算法式
- uk=uk+duk;
- if(e1>=75)
- {
- z=4;
- }
- else if(e1>=50)
- {
- z=3;
- }
- else if(e1>=10)
- {
- z=2;
- }
- else
- z=1;
- }
- if(uk>=2500)uk=2500;
- if(uk<=0)uk=0;
- if(uk<=0)
- {
- ET0=0;
- ET2=0;
- PWM=0;
- }
- else
- {
- ET0=1;
- ET2=1;
- PWMH=(uchar)uk;
- k=(float)uk;
- }
- e3=e2;
- e2=e1;
- conversion();//調(diào)用定時器2初值處理函數(shù)
- }
- else
- {
- ET0=0;
- ET2=0;
- PWM=0;
- }
- }
- }
- void timer0() interrupt 1//定時器1中斷
- {
- TH1=(65536-50000)/256;
- TL1=(65536-50000)%6;
- timecount++;
- TH2=HighH;
- TL2=HighL;
- PWM=1;
- }
- void ser() interrupt 4//串口中斷
- {
- RI=0;
- c=SBUF;
- flag=1;
- }
- void Timer2() interrupt 5//用定時器2控制PWM占空比
- {
- TF2=0;
- PWM=0;
- }
復(fù)制代碼
|
評分
-
查看全部評分
|