功能要求: 1) 采用液晶顯示器顯示溫度測量值。 2) 檢測的溫度范圍為0~128℃。 3) 溫度超過警戒值時能報警提示。 4) 能通過鍵盤輸入設定溫度并顯示。 5) 用PID控制溫度,控溫精度≦±2℃。 DS18B20溫度顯示仿真如圖,DS18B20的值可以任意調整,模擬溫度的采集,LCD的顯示值隨DS18B20的溫度值變化而變化。當溫度超過界限,LED亮,同時SOUNDER響,模擬警報系統。當按下k1,顯示溫度的最高位光標開始閃爍,進入設定溫度調整,按下k2,光標右移,按下k3數值加1,按下k4數值減1。
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載):
2.png (25.88 KB, 下載次數: 284)
下載附件
PID控制仿真圖
2017-6-4 15:01 上傳
1.png (35.76 KB, 下載次數: 246)
下載附件
DS18B20仿真圖
2017-6-4 15:01 上傳
PID控制仿真如圖,電加熱爐OVEN輸出的模擬量經ADC0804轉化成數字量,再送到LCD顯示。OVEN的溫度與設定溫度在單片機內進行PID運算,PID輸出量控制晶閘管的導通,從而控制OVEN的加熱。
0.png (70.96 KB, 下載次數: 235)
下載附件
2017-6-4 16:12 上傳
下面是51單片機的源碼:
- #include<reg52.h>
- #include<math.h>
- float R;
- float Kp;
- float T;
- float Ti;
- float Td;
- float e2;
- float e1,e;
- float a0,a1,a2;
- #define ui unsigned int
- #define uc unsigned char
- sbit bj=P2^4; //低電平報警模塊工作
- sbit lcden=P2^7; //LCD E
- sbit lcdrs=P2^6; //LCD RS
- sbit lcdrw=P2^5; // //LCD RW
- sbit control=P2^3; //加熱模塊相關。低電平啟動
- char lshi,lge,hshi,hge;
- uc num,flag;
- ui temp;
- sbit dsio=P3^7; //DS18B20輸入口
- //延時
- void delay(ui z)
- {
- uc x,y;
- for(x=z;x>0;x--)
- for(y=110;y>0;y--);
- }
- //DS18B20控制
- void dsinit()
- {
- uc i;
- dsio=0;
- i=70;
- while(i--);
- dsio=1;
- i=4;
- while(i--);
- }
- void dswritebyte(uc dat)
- {
- uc i,j;
- for(j=0;j<8;j++)
- {
- dsio=0;
- i++;
- dsio=dat&0x01;
- i=6;
- while(i--);
- dsio=1;
- dat>>=1;
- }
- }
- uc dsreadbyte()
- {
- uc i,j,byte,b;
- for(j=0;j<8;j++)
- {
- dsio=0;
- i++;
- dsio=1;
- i++;i++;
- b=dsio;
- byte=(byte>>1)|(b<<7);
- i=4;
- while(i--);
- }
- return byte;
- }
- void dschangetemp()
- {
- dsinit();
- delay(1);
- dswritebyte(0xcc);
- dswritebyte(0x44);
- }
- void dsreadtemp()
- {
- dsinit();
- delay(1);
- dswritebyte(0xcc);
- dswritebyte(0xbe);
- }
- ui gettemp()
- {
- int temp;
- uc h,l;
- dschangetemp();
- dsreadtemp();
- l=dsreadbyte();
- h=dsreadbyte();
- temp=h;
- temp<<=8;
- temp|=l;
- temp=temp*0.0625*100+0.5;
- return temp;
- }
- //LCD控制程序
- void lcdwritecom(uc com)
- {
- lcdrs=0;
- P0=com;
- delay(10);
- lcden=1;
- delay(10);
- lcden=0;
- }
- void lcdwritedata(uc date)
- {
- lcdrs=1;
- P0=date;
- delay(10);
- lcden=1;
- delay(10);
- lcden=0;
- }
- void lcdinit()
- {
- lcdrw=0;
- lcden=0;
- lcdwritecom(0x38);
- lcdwritecom(0x0c);
- lcdwritecom(0x06);
- lcdwritecom(0x01);
- }
- //LCD顯示
- void lcddisplay(int temp)
- {
- ui tab[]={0,0,0,-2,0,0};
- lcdwritecom(0x80);
- lcdwritedata('+');
- tab[0]=temp/10000;
- tab[1]=temp%10000/1000;
- tab[2]=temp%1000/100;
- tab[4]=temp%100/10;
- tab[5]=temp%10;
- lcdwritecom(0x81);
- for(num=0;num<6;num++)
- {
- lcdwritedata('0'+tab[num]);
- }
- }
- void adjust()
- {
- delay(100);
- flag++;
- if(flag==5)flag=1;
- if(flag==1)
- {
- lcdwritecom(0x80+0x44);
- lcdwritecom(0x0f);
- }
- if(flag==2)
- {
- lcdwritecom(0x80+0x45);
- lcdwritecom(0x0f);
- }
- if(flag==3)
- {
- lcdwritecom(0x80+0x47);
- lcdwritecom(0x0f);
- }
- if(flag==4)
- {
- lcdwritecom(0x80+0x48);
- lcdwritecom(0x0f);
- }
- }
- void inc()
- {
- delay(100);
- switch(flag)
- {
- case 1:lshi++; if(lshi==10)lshi=0;
- lcdwritedata('0'+lshi);
- lcdwritecom(0x10);
- break;
- case 2:lge++; if(lge==10)lge=0;
- lcdwritedata('0'+lge);
- lcdwritecom(0x10);
- break;
- case 3:hshi++; if(hshi==10)hshi=0;
- lcdwritedata('0'+hshi);
- lcdwritecom(0x10);
- break;
- case 4:hge++; if(hge==10)hge=0;
- lcdwritedata('0'+hge);
- lcdwritecom(0x10);
- break;
- }
- }
- void dec()
- {
- delay(100);
- switch(flag)
- {
- case 1:lshi--; if(lshi<0)lshi=9;
- lcdwritedata('0'+lshi);
- lcdwritecom(0x10);
- break;
- case 2:lge--; if(lge<0)lge=9;
- lcdwritedata('0'+lge);
- lcdwritecom(0x10);
- break;
- case 3:hshi--; if(hshi<0)hshi=9;
- lcdwritedata('0'+hshi);
- lcdwritecom(0x10);
- break;
- case 4:hge--; if(hge<0)hge=9;
- lcdwritedata('0'+hge);
- lcdwritecom(0x10);
- break;
- }
- }
- //鍵盤掃描
- void keyscan()
- {
- uc test,num;
- num=0;
- test=P1;
- if(test!=0xff)
- delay(5);
- test=P1;
- if(test==0xf7)
-
- {
- while(P1!=0xff);
- num++;
- while(1)
- {
- test=P1;
- if(test!=0xff)
- delay(5);
- test=P1;
- if(test!=0xff)
- {
- if(test==0xf7)
- num++;
- if(num==2)
- { lcdwritecom(0x0c);
- break;}
- switch(test)
- {
- case 0xfe:adjust();
- break;
- case 0xfd:inc();
- break;
- case 0xfb:dec();
- break;
- }
- }
- while(P1!=0xff);
-
- }
- }
- }
- //PID
- void PIDinit()
- {
-
- Kp=2;Ti=4;Td=1;T=1;R=25;
- a0=Kp*(1+T/Ti+Td/T);
- a1=-Kp*(1+(2*Td)/T);
- a2=Kp*(Td/T);
- e2=e1=0;
- }
- void PIDdeal()
- {
- float y ,u ;
- y=gettemp();
- e=y/100-R;
- u=a0*e+a1*e1+a2*e2;
- e2=e1;e1=e;
- if(u>0.5||u<-0.5)
- control=0;
- else control=1;
- }
- void main()
- {
- uc code tab2[]="SET:20~80C";
- uc i;
- TMOD=0x01;
- TH0=(65535-10900)/256;
- TL0=(65535-10900)%256;
- ET0=1;
- TR0=1;
- lcdinit();
- lcdwritecom(0x87);
- lcdwritedata('C');
- lcdwritecom(0x80+0x40);
- for(i=0;i<10;i++)
- lcdwritedata(tab2[i]) ;
- lshi=2;lge=0;hshi=5;hge=0;
- while(1)
- {
- lcddisplay(gettemp());
- keyscan() ;
- EA=1; while(1);
- }
- }
- void t0() interrupt 1
- {
- uc i;
- TH0=(65535-10900)/256;
- TL0=(65535-10900)%256;
- i++;
- if(i==100)
- {
- void PIDinit();
- void PIDdeal();
- }
- }
復制代碼
上文是網上轉載的給大家學習參考的,附件里面是我自己弄的,目前不成功,調試了好幾天了,搞不定,求大神指導如何修改?
仿真失敗的程序,求大神幫忙指導修改.7z
(236.78 KB, 下載次數: 1201)
2021-4-14 00:00 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|