❶ 請教關於單片機溫控程序
我在10年做了一個差不多的,也是報警控制的,你借鑒一下吧:
軟體設計:
有兩個文件,DS18B20.c和DS18B20.h,將這兩個文件添加到工程里即可。
DS18B20.c:
/******************************************************************
程序名稱:DS18B20溫度測量、報警系統
簡要說明:DS18B20溫度計,溫度測量范圍0~99.9攝氏度
可設置上限報警溫度、下限報警溫度
即高於上限值或者低於下限值時蜂鳴器報警
默認上限報警溫度為32℃、默認下限報警溫度為10℃
報警值可設置范圍:最低上限報警值等於當前下限報警值
最高下限報警值等於當前上限報警值
將下限報警值調為0時為關閉下限報警功能
******************************************************************/
#include<AT89X52.h>
#include"DS18B20.h"
#defineuintunsignedint
#defineucharunsignedchar//宏定義
#defineSETP3_1//定義調整鍵
#defineDECP3_2//定義減少鍵
#defineADDP3_3//定義增加鍵
#defineBEEPP3_7//定義蜂鳴器
#defineJDQP3_5
bitshanshuo_st;//閃爍間隔標志
bitbeep_st;//蜂鳴器間隔標志
sbitDIAN=P2^7;//小數點
ucharx=0;//計數器
signedcharm;//溫度值全局變數
ucharn;//溫度值全局變數
ucharset_st=0;//狀態標志
signedcharshangxian=70;//上限報警溫度,默認值為70
signedcharxiaxian=0;//下限報警溫度,默認值為0
ucharcodeLEDData[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xff};
/*****延時子程序*****/
voidDelay(uintnum)
{
while(--num);
}
voidshortdelay()(void)//誤差0us
{
unsignedchara,b,c;
for(c=165;c>0;c--)
for(b=100;b>0;b--)
for(a=150;a>0;a--);
_nop_;//ifKeil,requireuseintrins.h
_nop_;//ifKeil,requireuseintrins.h
}
/*****初始化定時器0*****/
voidInitTimer(void)
{
TMOD=0x1;
TH0=0x3c;
TL0=0xb0;//50ms(晶振12M)
}
/*****定時器0中斷服務程序*****/
voidtimer0(void)interrupt1
{
TH0=0x3c;
TL0=0xb0;
x++;
}
/*****外部中斷0服務程序*****/
voidint0(void)interrupt0
{
EX0=0;//關外部中斷0
if(DEC==0&&set_st==1)
{
shangxian--;
if(shangxian<xiaxian)shangxian=xiaxian;
}
elseif(DEC==0&&set_st==2)
{
xiaxian--;
if(xiaxian<0)xiaxian=0;
}
}
/*****外部中斷1服務程序*****/
voidint1(void)interrupt2
{
EX1=0;//關外部中斷1
if(ADD==0&&set_st==1)
{
shangxian++;
if(shangxian>99)shangxian=99;
}
elseif(ADD==0&&set_st==2)
{
xiaxian++;
if(xiaxian>shangxian)xiaxian=shangxian;
}
}
/*****讀取溫度*****/
voidcheck_wen(void)
{
uinta,b,c;
c=ReadTemperature()-5;//獲取溫度值並減去DS18B20的溫漂誤差
a=c/100;//計算得到十位數字
b=c/10-a*10;//計算得到個位數字
m=c/10;//計算得到整數位
n=c-a*100-b*10;//計算得到小數位
if(m<0){m=0;n=0;}//設置溫度顯示上限
if(m>99){m=99;n=9;}//設置溫度顯示上限
}
/*****顯示開機初始化等待畫面*****/
Disp_init()
{
P2=0xbf;//顯示-
P1=0xf7;
Delay(200);
P1=0xfb;
Delay(200);
P1=0xfd;
Delay(200);
P1=0xfe;
Delay(200);
P1=0xff;//關閉顯示
}
/*****顯示溫度子程序*****/
Disp_Temperature()//顯示溫度
{
P2=0xc6;//顯示C
P1=0xf7;
Delay(300);
P2=LEDData[n];//顯示個位
P1=0xfb;
Delay(300);
P2=LEDData[m%10];//顯示十位
DIAN=0;//顯示小數點
P1=0xfd;
Delay(300);
P2=LEDData[m/10];//顯示百位
P1=0xfe;
Delay(300);
P1=0xff;//關閉顯示
}
/*****顯示報警溫度子程序*****/
Disp_alarm(ucharbaojing)
{
P2=0xc6;//顯示C
P1=0xf7;
Delay(200);
P2=LEDData[baojing%10];//顯示十位
P1=0xfb;
Delay(200);
P2=LEDData[baojing/10];//顯示百位
P1=0xfd;
Delay(200);
if(set_st==1)P2=0x89;
elseif(set_st==2)P2=0xc7;//上限H、下限L標示
P1=0xfe;
Delay(200);
P1=0xff;//關閉顯示
}
/*****報警子程序*****/
voidAlarm()
{
if(x>=10){beep_st=~beep_st;x=0;}
if((m>=shangxian&&beep_st==1)||(m<xiaxian&&beep_st==1))BEEP=0;
elseBEEP=1;
if((m>=shangxian)||(m<xiaxian))
{shortdelay()();
JDQ=0;}
elseJDQ=1;
}
/*****主函數*****/
voidmain(void)
{
uintz;
InitTimer();//初始化定時器
EA=1;//全局中斷開關
TR0=1;
ET0=1;//開啟定時器0
IT0=1;
IT1=1;
check_wen();
check_wen();
for(z=0;z<300;z++)
{
Disp_init();
}
while(1)
{
if(SET==0)
{
Delay(2000);
do{}while(SET==0);
set_st++;x=0;shanshuo_st=1;
if(set_st>2)set_st=0;
}
if(set_st==0)
{
EX0=0;//關閉外部中斷0
EX1=0;//關閉外部中斷1
check_wen();
Disp_Temperature();
Alarm();//報警檢測
}
elseif(set_st==1)
{
BEEP=1;//關閉蜂鳴器
EX0=1;//開啟外部中斷0
EX1=1;//開啟外部中斷1
if(x>=10){shanshuo_st=~shanshuo_st;x=0;}
if(shanshuo_st){Disp_alarm(shangxian);}
}
elseif(set_st==2)
{
BEEP=1;//關閉蜂鳴器
EX0=1;//開啟外部中斷0
EX1=1;//開啟外部中斷1
if(x>=10){shanshuo_st=~shanshuo_st;x=0;}
if(shanshuo_st){Disp_alarm(xiaxian);}
}
}
}
/*****END*****/
DS18B20.h:
#include<AT89X52.h>
#defineDQP3_6//定義DS18B20匯流排I/O
/*****延時子程序*****/
voidDelay_DS18B20(intnum)
{
while(num--);
}
/*****初始化DS18B20*****/
voidInit_DS18B20(void)
{
unsignedcharx=0;
DQ=1;//DQ復位
Delay_DS18B20(8);//稍做延時
DQ=0;//單片機將DQ拉低
Delay_DS18B20(80);//精確延時,大於480us
DQ=1;//拉高匯流排
Delay_DS18B20(14);
x=DQ;//稍做延時後,如果x=0則初始化成功,x=1則初始化失敗
Delay_DS18B20(20);
}
/*****讀一個位元組*****/
unsignedcharReadOneChar(void)
{
unsignedchari=0;
unsignedchardat=0;
for(i=8;i>0;i--)
{
DQ=0;//給脈沖信號
dat>>=1;
DQ=1;//給脈沖信號
if(DQ)
dat|=0x80;
Delay_DS18B20(4);
}
return(dat);
}
/*****寫一個位元組*****/
voidWriteOneChar(unsignedchardat)
{
unsignedchari=0;
for(i=8;i>0;i--)
{
DQ=0;
DQ=dat&0x01;
Delay_DS18B20(5);
DQ=1;
dat>>=1;
}
}
/*****讀取溫度*****/
unsignedintReadTemperature(void)
{
unsignedchara=0;
unsignedcharb=0;
unsignedintt=0;
floattt=0;
Init_DS18B20();
WriteOneChar(0xCC);//跳過讀序號列號的操作
WriteOneChar(0x44);//啟動溫度轉換
Init_DS18B20();
WriteOneChar(0xCC);//跳過讀序號列號的操作
WriteOneChar(0xBE);//讀取溫度寄存器
a=ReadOneChar();//讀低8位
b=ReadOneChar();//讀高8位
t=b;
t<<=8;
t=t|a;
tt=t*0.0625;
t=tt*10+0.5;//放大10倍輸出並四捨五入
return(t);
}
/*****END*****/
其中控制部分我用的是5V繼電器,可以直接控制你的電機了。
兩個電路圖都差不多的,只不過我的多了幾個調整按鍵,報警溫度可以調的。我的這個程序你完全可以用到你的電路里的
❷ 數顯溫控器溫度如何校正
溫度控制器一般有兩個差,一個是誤差(一般是正負多少K1),一個是回程公差(一般是多少K2)。
誤差就是測量的差,比如您設定的實際控制值是80度(您想達到的理想值),但是考慮誤差的存在,設定值:1)對於需要控制上限的,比如加熱器,應該是設定為:(80+K1);2)對於需要控制下限的,比如散熱風扇,應該設定為:(80-K1)。
回程公差是達到設定值後需要溫度改變到什麼程度控制器再動作,不是說超過您設定值(比如80+K1)一點點就立即動作,而是有個范圍,比如7、8K,對於上限控制的加熱器是(80-K2)後動作,對於下限控制的散熱風扇是(80+K2)後動作。
❸ 數顯溫控器中比例,微分、積分、是什麼作用參數設置多大比較好
數顯溫控器中比例,微分、積分的英文縮寫是PID。
比例調節(P)作用:是按比例反應系統的偏差,系統一旦出現了偏差,比例調節立即產生調節作用用以減少偏差。比例作用大,可以加快調節,減少誤差,但是過大的比例,使系統的穩定性下降,甚至造成系統的不穩定。
積分調節(I)作用:是使系統消除穩態誤差,提高無差度。因為有誤差,積分調節就進行,直至無差,積分 調節停止,積分調節輸出一常值。積分作用的強弱取決與積分時間常數Ti,Ti越小,積分作用就越強。反 之Ti大則積分作用弱,加入積分調節可使系統穩定性下降,動態響應變慢。積分作用常與另兩種調節規律 結合,組成PI調節器或PID調節器。
微分調節(D)作用:微分作用反映系統偏差信號的變化率,具有預見性,能預見偏差變化的趨勢,因此能產 生超前的控製作用,在偏差還沒有形成之前,已被微分調節作用消除。因此,可以改善系統的動態性能。在微分時間選擇合適情況下,可以減少超調,減少調節時間。微分作用對雜訊干擾有放大作用,因此過強 的加微分調節,對系統抗干擾不利。此外,微分反應的是變化率,而當輸入沒有變化時,微分作用輸出為 零。微分作用不能單獨使用,需要與另外兩種調節規律相結合,組成PD或PID控制器。
帶有PID調節功能的數顯溫度調節控制器都帶有PID自整定功能,設置完基本參數,讓數顯溫度調節控制器進入自整定,溫控器在升溫過程中會自動確定PID參數。比人工調整准確省時間。
❹ 基於單片機的自動溫控系統的設計.畢業論文開題報告
熱電致冷器件特別適合於小熱量和受空間限制的溫控領域。改變加在器件上的直流電的極性即可變致冷為加熱,而吸熱或放熱率則正比於所加直流電流的大小。Pe1tier 溫控器的設定溫度可以在一個較寬的范圍內任意選擇,可選擇低於或高於環境溫度。
在本系統中我們選用了天津藍天高科電源有限公司生產的半導體致冷器件 TES1-12739,其最大溫差電壓 14.7V,最大溫差電流3.9A最大致冷功率33.7W。
1.5 其它部分
系統採用Samsung(三星)公司生產的真空熒光數碼顯示屏 VFD用來實時顯示當前溫度,以觀察控制效果。鍵盤和串列通信介面用來設定控制溫度和調整PID參數。系統電路原理圖如圖3所示。
2 系統軟體設計
系統開始工作時,首先由單片機控制軟體發出溫度讀取指令,通過數字溫度感測器 DS18B20 采樣被控對象的當前溫度值T1並送顯示屏實時顯示。然後,將該溫度測量值與設定值T比較,其差值送 PID控制器。PID 控制器處理後輸出一定數值的控制量,經DA 轉換為模擬電壓量,該電壓信號再經大電流驅動電路,提高電流驅動能力後載入到半導體致冷器件上,對溫控對象進行加熱或製冷。加熱或製冷取決於致冷器上所加電壓的正負,若溫控對象當前溫度測量值與設定值差值為正,則輸出負電壓信號,致冷器上載入負電壓溫控對象溫度降低;反之,致冷器上載入正向電壓,溫控對象溫度升高。上述過程:溫度采樣-計算溫差-PID調節-信號放大輸出周而復始,最後將溫控對象的溫度控制在設定值附近上下波動,隨著循環次數的增加,波動幅度會逐漸減小到某一很小的量,直至達到控制要求。為了加快控制,在進入PID控制前加入了一段溫差判斷程序。當溫度差值大於設定閾值Δt時,系統進行全功率加熱或製冷,直到溫差小於Δt才進入PID控制環節。圖4為系統工作主程序的軟體流程圖.
3 結論
本文設計的基於單片機數字PID控制的精密溫度控制系統,在實際應用中取得了良好的控制效果,溫度控制精度達到±0.1℃。經48小時連續運行考驗,系統工作穩定,有效地降低了輻亮度標准探測器的溫度系數,使輻亮度標准探測器在溫度變化較大的環境中也能保持其高精度,為實現基於探測器的高精度輻射定標的廣泛應用奠定了基礎。
本文作者創新點:在原來基於PC的PID溫控系統的基礎上,設計了由單片機、數字式溫感測器DS18B20和半導體致冷器組成的精密溫度控制系統。該溫控系統的應用為高精度光輻射測量儀器-輻亮度標准探測器的小型化、智能化提供了有利條件。
❺ 求簡易溫度控制器設計的單片機匯編語言程序
這個程序你可以用來試試。我以前做的。
//溫控系統控製程序
//溫度感測器:DS18B20
//顯示方式:LED
#include<reg51.h>
#defineucharunsignedchar
sbitkeyup=P1^0;
sbitkeydn=P1^1;
sbitkeymd=P1^2;
sbitout=P3^7; //接控制繼電器
sbitDQ=P3^4; //接溫度感測器18B20
uchart[2],number=0,*pt; //溫度值
ucharTempBuffer1[4]={0,0,0,0};
ucharTmax=18,Tmin=8;
uchardistab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff,0xfe,0xf7};
uchardismod=0,xiaodou1=0,xiaodou2=0,currtemp;
bitflag;
voidt0isr()interrupt1
{
TH0=(65536-5000)/256;
TL0=(65536-5000)%256;
switch(number)
{
case0:
P2=0x08;
P0=distab[TempBuffer1[0]];
break;
case1:
P2=0x04;
P0=distab[TempBuffer1[1]];
break;
case2:
P2=0x02;
P0=distab[TempBuffer1[2]]&0x7f;
break;
case3:
P2=0x01;
P0=distab[TempBuffer1[3]];
break;
default:
break;
}
number++;
if(number>3)number=0;
}
voiddelay_18B20(unsignedinti)
{
while(i--);
}
/**********ds18b20初始化函數**********************/
voidInit_DS18B20(void)
{
bitx=0;
do{
DQ=1;
delay_18B20(8);
DQ=0;//單片機將DQ拉低
delay_18B20(90);//精確延時大於480us
DQ=1;//拉高匯流排
delay_18B20(14);
x=DQ;//稍做延時後如果x=0則初始化成功x=1則初始化失敗,繼續初始化
}while(x);
delay_18B20(20);
}
/***********ds18b20讀一個位元組**************/
unsignedcharReadOneChar(void)
{
unsignedchari=0;
unsignedchardat=0;
for(i=8;i>0;i--)
{
DQ=0;//給脈沖信號
dat>>=1;
DQ=1;//給脈沖信號
if(DQ)
dat|=0x80;
delay_18B20(4);
}
return(dat);
}
/*************ds18b20寫一個位元組****************/
voidWriteOneChar(unsignedchardat)
{
unsignedchari=0;
for(i=8;i>0;i--)
{
DQ=0;
DQ=dat&0x01;
delay_18B20(5);
DQ=1;
dat>>=1;
}
}
/**************讀取ds18b20當前溫度************/
unsignedchar*ReadTemperature(unsignedcharrs)
{
unsignedchartt[2];
delay_18B20(80);
Init_DS18B20();
WriteOneChar(0xCC);//跳過讀序號列號的操作
WriteOneChar(0x44); //啟動溫度轉換
delay_18B20(80);
Init_DS18B20();
WriteOneChar(0xCC); //跳過讀序號列號的操作
WriteOneChar(0xBE); //讀取溫度寄存器等(共可讀9個寄存器)前兩個就是溫度
tt[0]=ReadOneChar();//讀取溫度值低位
tt[1]=ReadOneChar();//讀取溫度值高位
return(tt);
}
voidcovert1(void) //將溫度轉換為LED顯示的數據
{
ucharx=0x00,y=0x00;
t[0]=*pt;
pt++;
t[1]=*pt;
if(t[1]&0x080)//判斷正負溫度
{
TempBuffer1[0]=0x0c; //c代表負
t[1]=~t[1]; /*下面幾句把負數的補碼*/
t[0]=~t[0]; /*換算成絕對值*********/
x=t[0]+1;
t[0]=x;
if(x==0x00)t[1]++;
}
elseTempBuffer1[0]=0x0a; //A代表正
t[1]<<=4; //將高位元組左移4位
t[1]=t[1]&0xf0;
x=t[0]; //將t[0]暫存到X,因為取小數部分還要用到它
x>>=4; //右移4位
x=x&0x0f; //和前面兩句就是取出t[0]的高四位
y=t[1]|x; //將高低位元組的有效值的整數部分拼成一個位元組
TempBuffer1[1]=(y%100)/10;
TempBuffer1[2]=(y%100)%10;
t[0]=t[0]&0x0f; //小數部分
TempBuffer1[3]=t[0]*10/16;
//以下程序段消去隨機誤檢查造成的誤判,只有連續12次檢測到溫度超出限制才切換加熱裝置
if(currtemp>Tmin)xiaodou1=0;
if(y<Tmin)
{
xiaodou1++;
currtemp=y;
xiaodou2=0;
}
if(xiaodou1>12)
{
out=0;
flag=1;
xiaodou1=0;
}
if(currtemp<Tmax)xiaodou2=0;
if(y>Tmax)
{
xiaodou2++;
currtemp=y;
xiaodou1=0;
}
if(xiaodou2>12)
{
out=1;
flag=0;
xiaodou2=0;
}
out=flag;
}
voidconvert(chartmp)
{
uchara;
if(tmp<0)
{
TempBuffer1[0]=0x0c;
a=~tmp+1;
}
else
{
TempBuffer1[0]=0x0a;
a=tmp;
}
TempBuffer1[1]=(a%100)/10;
TempBuffer1[2]=(a%100)%10;
}
voidkeyscan()
{
ucharkeyin;
keyin=P1&0x07;
if(keyin==0x07)return;
elseif(keymd==0)
{
dismod++;
dismod%=3;
while(keymd==0);
switch(dismod)
{
case1:
convert(Tmax);
TempBuffer1[3]=0x11;
break;
case2:
convert(Tmin);
TempBuffer1[3]=0x12;
break;
default:
break;
}
}
elseif((keyup==0)&&(dismod==1))
{
Tmax++;
convert(Tmax);
while(keyup==0);
}
elseif((keydn==0)&&(dismod==1))
{
Tmax--;
convert(Tmax);
while(keydn==0);
}
elseif((keyup==0)&&(dismod==2))
{
Tmin++;
convert(Tmin);
while(keyup==0);
}
elseif((keydn==0)&&(dismod==2))
{
Tmin--;
convert(Tmin);
while(keydn==0);
}
xiaodou1=0;
xiaodou2=0;
}
main()
{
TMOD=0x01;
TH0=(65536-5000)/256;
TL0=(65536-5000)%256;
TR0=1;
ET0=1;
EA=1;
out=1;
flag=0;
ReadTemperature(0x3f);
delay_18B20(50000); //延時等待18B20數據穩定
while(1)
{
pt=ReadTemperature(0x7f);//讀取溫度,溫度值存放在一個兩個位元組的數組中
if(dismod==0)covert1();
keyscan();
delay_18B20(30000);
}
}
❻ 溫控器採用什麼單片機最適用
樓上的說的不錯,用89C2051和DS18B20就可以了,不用A\D轉換,因為DS18B20自帶A\D轉換功能,單片機只需要處理DS18B20送過來的數字信號就可以了。
❼ 51單片機用DS18B20做溫控器,想用數碼管高位的後3位顯示溫度,十位,個位,小數
void dis_temp(uint t)//顯示溫度數值函數 t傳遞的是整形的溫度值
{
uint shi,ge,shifen;
shi=t/100;
ge=t%100/10;
shifen=t%100%10;
P1=table[shi];
led1=0; //位選,第一個數碼管亮
delay(5); //延時,亮一會
led1=1; //CLOSE
P1=table[ge];
led2=0; //位選,第二個數碼管亮
delay(5);
led2=1;
P1=table[shifen];
led3=0; //位選,第三個數碼管亮
delay(5);
led3=1;
led4=1;
}