水溫控制系統設計
單片機源程序如下:
- /***************************************************************
- 項目名稱:水溫控制系統設計;
- 功 能:通過STC89C52單片機控制可控硅驅動加過零檢測電路作為
- 功率控制電路來控制加熱過程,通過鍵盤掃描來設定水溫,
- DS18B20實時測量水的溫度,將實際水溫與設定水溫比較
- 通過PID控制算法調節,是實際水溫與設定水溫接近。從而
- 達到控制水溫的目的。
- 作 者:0903
- ***************************************************************/
- #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[]={"設定溫度:"};
- uchar code table1[]={"實測溫度:"};
- uchar code table2[]={"加熱"};
- uchar code table3[]={"保溫"};
- uchar code table4[]={"作者:0903鋒仔@"};
- uchar code table5[]={"系統初始化"};
- uchar code table6[]={"measured Temperature"};
- uchar code table7[]={"水溫控制系統設計"};
- uchar code table8[]={" "};
- void delay(uint z)//延時函數,延時5ms
- {
- uint x,y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
- }
- /***************************************
- 鍵盤掃描函數
- 通過S5,S4,S3,S2,S1鍵來分別實現溫度設定值的
- 粗加,粗減,精加,精減,和確定功能。
- ***************************************/
- void keyscan()
- {
- if(set_temp>=100)//將設定溫度限定在0-100度之間
- set_temp=100;
- if(set_temp<=0)
- set_temp=0;
- if(s5==0)//此鍵按下設定溫度加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)//此鍵按下設定溫度減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)//此鍵按下設定溫度加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)//此鍵按下設定溫度減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)//確定加熱狀態(加熱與不加熱)
- {
- delay(10);
- if(s1==0)
- {
- flag1=1;
- }
- while(s1==0);
- }
- }
- /******************************************
- DS18B20溫度采集模塊程序設計
- 通過DS18B20實時采集水溫,反映給單片機系統
- ******************************************/
- void dsreset()//DS18B20復位函數
- {
- uint i;
- ds=0;
- i=103;
- while(i>0)i--;
- ds=1;
- i=4;
- while(i>0)i--;
- }
- bit tempreadbit()//從DS18B20 RAM讀一位數據
- {
- 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讀一字節數據
- {
- 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寫以字節的數據
- {
- 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 readrom()
- {
- dsreset();
- delay(1);
- tempwritebyte(0x33);
- tempwritebyte(0xbe);
- readrom=tempread();
- }
- void matchrom()
- {
- dsreset();
- delay(1);
- tempwritebyte(0x55);
- }*/
- void tempchange()//啟動溫度轉換
- {
- dsreset();
- delay(1);
- tempwritebyte(0xcc);
- tempwritebyte(0x44);
- }
- float get_temp()//溫度值讀取與處理函數
- {
- 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);
- }
- /**********************************************
- 12864顯示模塊
- 顯示實際溫度制和設定溫度值
- **********************************************/
- 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寫數據
- {
- rs=1;
- wr=0;
- delay(1);
- P0=date;
- lcden=1;
- delay(1);
- lcden=0;
- delay(1);
- }
- void display(float m,uchar n)//顯示設定溫度、實測溫度、加熱狀態
- {
- 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%10;
- }
- else
- {
- a1=1;
- a2=0;
- a3=0;
- }
- p=m;
- j=(uint)(p*10);
- b1=(uchar)(j/1000);
- b2=(uchar)(j%1000/100);
- b3=(uchar)(j%100/10);
- b4=(uchar)(j%10);
- write_com(0x90+5);//顯示設定溫度
- 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)<n)
- {
- 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)&&((b+0.2)>=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++;
- }
- }
- }
- /*****************************************************
- PID控制算法程序設計
- 通過PID控制算法可以使實際水溫在設定水溫周圍呈很小范圍的
- 波動,從而使實際水溫值接近設定水溫值
- *****************************************************/
- void conversion()//定時器2初值處理函數
- {
- uint temp2;
- temp2=65536-PWMH*10;
- HighH=temp2/256;
- HighL=temp2%256;
- }
- 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()//初始化函數
- {
- uint i,j;
- TMOD=0x21;
- TH1=0xfd;
- TL1=0xfd;
- TH0=(65536-50000)/256;
- TL0=(65536-50000)%256;
- PWMH=0;
- conversion();
- TH2=(65536-50000)/256;
- TL2=(65536-50000)%256;
- rd=1;
- lcden=0;
- write_com(0x30);
- write_com(0x0c);
- write_com(0x01);
- write_com(0x90);
- while(table5[i]!='\0')//系統初始化
- {
- write_date(table5[i]);
- i++;
- delay(20);
- }
- for(j=0;j<=1;j++)//6個點的三次循環
- {
- 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);//顯示 水溫控制系統設計標題
- while(table7[i]!='\0')
- {
- write_date(table7[i]);
- i++;
- }
- i=0;
- write_com(0x90);//顯示 設定溫度
- 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);//設定DS18B20的分辨率為11位
- // tempwritebyte(0x5f);
- PWM=0;
- e1=0;
- e2=0;
- e3=0;
- duk=0;
- uk=0;
- KP=20;//PID控制算法參數
- KI=0.061;
- KD=30;
- REN=1;//串口通信設置
- 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();//調用鍵盤掃描函數
- tempchange();//啟動溫度轉換
- t=get_temp();//提取實測溫度
- display(t,set_temp);//顯示設定溫度和實測溫度
- senddate(t);//向上位機發送數據函數
- 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;
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
http://www.raoushi.com/bbs/dpj-124587-1.html
|