您好,登錄后才能下訂單哦!
51單片機(jī)課程設(shè)計(jì):基于DS18B20的溫度報(bào)警器
本程序用于讀取DS18B20溫度,同時(shí)具備報(bào)警功能,工程分為3個(gè)文件,main.c、temp.c、temp.h,經(jīng)本人修改部分代碼,適用于吉林農(nóng)業(yè)大學(xué)51開(kāi)發(fā)板,其他朋友亦可移植到其他型號(hào)開(kāi)發(fā)板。工程文件及對(duì)應(yīng)開(kāi)發(fā)板的電路圖在文章最下方。
關(guān)于粘貼復(fù)制亂碼的問(wèn)題:如果程序復(fù)制到Keil編譯器上出現(xiàn)注釋亂碼,可以先建一個(gè).c文件,也就是說(shuō)不在keil里面編輯,然后用記事本打開(kāi).c文件,將源碼復(fù)制進(jìn)去,再在keil中添加文件即可,其他操作方法一樣。
1.main.c文件
/*********************************說(shuō)明****************************************** 本程序用于讀取溫度檢測(cè)模塊DS18B20數(shù)值,并顯示到數(shù)碼管上 本程序分為兩部分,一部分為主函數(shù)部分,文件名為main.c 另一部分為溫度讀取部分,文件名為temp.c 數(shù)碼管以及蜂鳴器連接方法參照以下定義,DS18B20連接見(jiàn)temp.h(引腳P3.7) 在程序剛開(kāi)始,會(huì)要求設(shè)置預(yù)警值,通過(guò)按鍵可以實(shí)現(xiàn)數(shù)值的加減,設(shè)置完成后按確認(rèn)鍵。 然后開(kāi)始監(jiān)測(cè)數(shù)值是否超過(guò)預(yù)警值,超過(guò)則報(bào)警。 (本程序經(jīng)修改適用于吉農(nóng)51單片機(jī)開(kāi)發(fā)板) 2016-12-29------------------------SWorld *******************************************************************************/ #include<reg51.h> #include"temp.h" //--定義使用的IO--// #define GPIO_DIG P0//位選以及段選數(shù)據(jù)輸出端口定義 #define GPIO_KEY P1 //按鍵引腳 p1.0:ADD數(shù)值增加 p1.1:SUB數(shù)值減少 p1.2:OK 確定 sbit DUC=P2^2; //DUC段選信號(hào) sbit WEC=P2^3; //WEC位選信號(hào) sbit BELL=P2^4;// 蜂鳴器連接 超出預(yù)警范圍蜂鳴器響 //sbit LIGHT=P1^4;//定義LED燈閃爍引腳 char HIGH=30,LOW=20;//定義預(yù)警范圍最大以及最低值 超出此數(shù)值將會(huì)報(bào)警 unsigned int ifset=0;//判斷是否設(shè)置好最高以及最低溫度 //--定義全局變量 unsigned char code DIG_CODE[19]={ 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x38,0x76}; //0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F、L、H的顯示碼 L代表最低溫度 H代表最高溫度 unsigned char DisplayData[8]; //用來(lái)存放要顯示的8位數(shù)的值 //--聲明全局函數(shù)--// void LcdDisplay(int temp); void DigDisplay(); void Delay10ms(unsigned int c); unsigned char Key_Scan(); /******************************************************************************* * 函 數(shù) 名 : main * 函數(shù)功能 : 主函數(shù) * 輸 入 : 無(wú) * 輸 出 : 無(wú) *******************************************************************************/ void main() { DUC=0;WEC=0;BELL=1; //初始化 while(1) { switch(ifset) { case 0://設(shè)置最高溫度 DisplayData[7] = DIG_CODE[17];//顯示H if(HIGH>0) {DisplayData[5]=0x00;} else {DisplayData[5]=0x40;} switch(Key_Scan())//掃描鍵值 { case 1://數(shù)值增加 if(HIGH>LOW) HIGH-=1; break; case 2://數(shù)值減少 HIGH+=1; break; case 4://確定 ifset=1; break; } //顯示最大溫度 DisplayData[4] = DIG_CODE[HIGH / 100]; DisplayData[3] = DIG_CODE[HIGH % 100 / 10]; DisplayData[2] = DIG_CODE[HIGH % 10]; break; case 1://設(shè)置最低溫度 DisplayData[7] = DIG_CODE[16]; if(LOW>0) {DisplayData[5]=0x00;} else {DisplayData[5]=0x40;} switch(Key_Scan()) { case 1: LOW-=1; break; case 2: if(LOW<HIGH) LOW+=1; break; case 4: ifset=2; break; } //顯示最低溫度 DisplayData[4] = DIG_CODE[LOW / 100]; DisplayData[3] = DIG_CODE[LOW % 100 / 10]; DisplayData[2] = DIG_CODE[LOW % 10]; break; case 2://設(shè)置完成 開(kāi)始監(jiān)控 DisplayData[7]=0x00; LcdDisplay(Ds18b20ReadTemp()); break; } if(ifset!=2) DigDisplay(); } } /******************************************************************************* * 函 數(shù) 名 : LcdDisplay() * 函數(shù)功能 : LCD顯示讀取到的溫度 * 輸 入 : v * 輸 出 : 無(wú) *******************************************************************************/ void LcdDisplay(int temp) //lcd顯示 { float tp; if(temp< 0)//當(dāng)溫度值為負(fù)數(shù) { DisplayData[6] = 0x40; //因?yàn)樽x取的溫度是實(shí)際溫度的補(bǔ)碼,所以減1,再取反求出原碼 temp=temp-1; temp=~temp; tp=temp; temp=tp*0.0625*100+0.5; //留兩個(gè)小數(shù)點(diǎn)就*100,+0.5是四舍五入,因?yàn)镃語(yǔ)言浮點(diǎn)數(shù)轉(zhuǎn)換為整型的時(shí)候把小數(shù)點(diǎn) //后面的數(shù)自動(dòng)去掉,不管是否大于0.5,而+0.5之后大于0.5的就是進(jìn)1了,小于0.5的就 //算由?.5,還是在小數(shù)點(diǎn)后面。 } else { DisplayData[6] = 0x00; tp=temp;//因?yàn)閿?shù)據(jù)處理有小數(shù)點(diǎn)所以將溫度賦給一個(gè)浮點(diǎn)型變量 //如果溫度是正的那么,那么正數(shù)的原碼就是補(bǔ)碼它本身 temp=tp*0.0625*100+0.5; //留兩個(gè)小數(shù)點(diǎn)就*100,+0.5是四舍五入,因?yàn)镃語(yǔ)言浮點(diǎn)數(shù)轉(zhuǎn)換為整型的時(shí)候把小數(shù)點(diǎn) //后面的數(shù)自動(dòng)去掉,不管是否大于0.5,而+0.5之后大于0.5的就是進(jìn)1了,小于0.5的就 //算加上0.5,還是在小數(shù)點(diǎn)后面。 if(temp*100<LOW||temp>HIGH*100)//以下是判斷是否超出預(yù)警范圍 { BELL=0; } else { BELL=1; } } DisplayData[5] = DIG_CODE[temp / 10000]; DisplayData[4] = DIG_CODE[temp % 10000 / 1000]; DisplayData[3] = DIG_CODE[temp % 1000 / 100] | 0x80; DisplayData[2] = DIG_CODE[temp % 100 / 10]; DisplayData[1] = DIG_CODE[temp % 10]; DigDisplay(); //掃描顯示 } /******************************************************************************* * 函 數(shù) 名 : DigDisplay * 函數(shù)功能 : 使用數(shù)碼管顯示 * 輸 入 : 無(wú) * 輸 出 : 無(wú) *******************************************************************************/ void DigDisplay() { unsigned char i; unsigned int j; for(i=0;i<8;i++) { WEC=1;DUC=0; switch(i) //位選,選擇點(diǎn)亮的數(shù)碼管, { case(0): GPIO_DIG=0x7F; break;//顯示第0位 case(1): GPIO_DIG=0xBF; break;//顯示第1位 case(2): GPIO_DIG=0xDF; break;//顯示第2位 case(3): GPIO_DIG=0xEF; break;//顯示第3位 case(4): GPIO_DIG=0xF7; break;//顯示第4位 case(5): GPIO_DIG=0xFB; break;//顯示第5位 case(6): GPIO_DIG=0xFD; break;//顯示第6位 case(7): GPIO_DIG=0xFE; break;//顯示第7位 } WEC=0;DUC=1; GPIO_DIG=DisplayData[i];//發(fā)送段碼 j=50; //掃描間隔時(shí)間設(shè)定 while(j--); GPIO_DIG=0x00;//消隱 } } /******************************************************************************* * 函 數(shù) 名 : Key_Scan() * 函數(shù)功能 : 掃描鍵盤(pán) * 輸 入 : 無(wú) * 輸 出 : 讀取到的鍵值 *******************************************************************************/ unsigned char Key_Scan() { unsigned char keyValue = 0 , i; //保存鍵值 //--檢測(cè)按鍵1--// if (GPIO_KEY != 0xFF)//檢測(cè)按鍵K1是否按下 { Delay10ms(1);//消除抖動(dòng) if (GPIO_KEY != 0xFF)//再次檢測(cè)按鍵是否按下 { keyValue = ~GPIO_KEY; i = 0; while ((i<50) && (GPIO_KEY != 0xFF)) //檢測(cè)按鍵是否松開(kāi) { Delay10ms(1); i++; } } } return keyValue; //將讀取到鍵值的值返回 } /******************************************************************************* * 函 數(shù) 名 : Delay10ms * 函數(shù)功能 : 延時(shí)函數(shù),延時(shí)10ms * 輸 入 : 無(wú) * 輸 出 : 無(wú) *******************************************************************************/ void Delay10ms(unsigned int c) //誤差 0us { unsigned char a, b; //--c已經(jīng)在傳遞過(guò)來(lái)的時(shí)候已經(jīng)賦值了,所以在for語(yǔ)句第一句就不用賦值了--// for (;c>0;c--) { for (b=38;b>0;b--) { for (a=130;a>0;a--); } } }
2.temp.c文件
/*-----------------------------------------------------------------------------*/ /*----------------------------DS18B20操作函數(shù)----------------------------------*/ /*-----------------------------------------------------------------------------*/ #include"temp.h" /******************************************************************************* * 函 數(shù) 名 : Delay1ms * 函數(shù)功能 : 延時(shí)函數(shù) * 輸 入 : 無(wú) * 輸 出 : 無(wú) *******************************************************************************/ void Delay1ms(uint y) { uint x; for( ; y>0; y--) { for(x=110; x>0; x--); } } /******************************************************************************* * 函 數(shù) 名 : Ds18b20Init * 函數(shù)功能 : 初始化 * 輸 入 : 無(wú) * 輸 出 : 初始化成功返回1,失敗返回0 *******************************************************************************/ uchar Ds18b20Init() { uchar i; DSPORT = 0; //將總線拉低480us~960us i = 70; while(i--);//延時(shí)642us DSPORT = 1;//然后拉高總線,如果DS18B20做出反應(yīng)會(huì)將在15us~60us后總線拉低 i = 0; while(DSPORT)//等待DS18B20拉低總線 { Delay1ms(1); i++; if(i>5)//等待>5MS { return 0;//初始化失敗 } } return 1;//初始化成功 } /******************************************************************************* * 函 數(shù) 名 : Ds18b20WriteByte * 函數(shù)功能 : 向18B20寫(xiě)入一個(gè)字節(jié) * 輸 入 : com * 輸 出 : 無(wú) *******************************************************************************/ void Ds18b20WriteByte(uchar dat) { uint i, j; for(j=0; j<8; j++) { DSPORT = 0; //每寫(xiě)入一位數(shù)據(jù)之前先把總線拉低1us i++; DSPORT = dat & 0x01; //然后寫(xiě)入一個(gè)數(shù)據(jù),從最低位開(kāi)始 i=6; while(i--); //延時(shí)68us,持續(xù)時(shí)間最少60us DSPORT = 1;//然后釋放總線,至少1us給總線恢復(fù)時(shí)間才能接著寫(xiě)入第二個(gè)數(shù)值 dat >>= 1; } } /******************************************************************************* * 函 數(shù) 名 : Ds18b20ReadByte * 函數(shù)功能 : 讀取一個(gè)字節(jié) * 輸 入 : com * 輸 出 : 無(wú) *******************************************************************************/ uchar Ds18b20ReadByte() { uchar byte, bi; uint i, j; for(j=8; j>0; j--) { DSPORT = 0;//先將總線拉低1us i++; DSPORT = 1;//然后釋放總線 i++; i++;//延時(shí)6us等待數(shù)據(jù)穩(wěn)定 bi = DSPORT; //讀取數(shù)據(jù),從最低位開(kāi)始讀取 /*將byte左移一位,然后與上右移7位后的bi,注意移動(dòng)之后移掉那位補(bǔ)0。*/ byte = (byte >> 1) | (bi << 7); i = 4;//讀取完之后等待48us再接著讀取下一個(gè)數(shù) while(i--); } return byte; } /******************************************************************************* * 函 數(shù) 名 : Ds18b20ChangTemp * 函數(shù)功能 : 讓18b20開(kāi)始轉(zhuǎn)換溫度 * 輸 入 : com * 輸 出 : 無(wú) *******************************************************************************/ void Ds18b20ChangTemp() { Ds18b20Init(); Delay1ms(1); Ds18b20WriteByte(0xcc);//跳過(guò)ROM操作命令 Ds18b20WriteByte(0x44); //溫度轉(zhuǎn)換命令 //Delay1ms(100);//等待轉(zhuǎn)換成功,而如果你是一直刷著的話,就不用這個(gè)延時(shí)了 } /******************************************************************************* * 函 數(shù) 名 : Ds18b20ReadTempCom * 函數(shù)功能 : 發(fā)送讀取溫度命令 * 輸 入 : com * 輸 出 : 無(wú) *******************************************************************************/ void Ds18b20ReadTempCom() { Ds18b20Init(); Delay1ms(1); Ds18b20WriteByte(0xcc); //跳過(guò)ROM操作命令 Ds18b20WriteByte(0xbe); //發(fā)送讀取溫度命令 } /******************************************************************************* * 函 數(shù) 名 : Ds18b20ReadTemp * 函數(shù)功能 : 讀取溫度 * 輸 入 : com * 輸 出 : 無(wú) *******************************************************************************/ int Ds18b20ReadTemp() { int temp = 0; uchar tmh, tml; Ds18b20ChangTemp(); //先寫(xiě)入轉(zhuǎn)換命令 Ds18b20ReadTempCom();//然后等待轉(zhuǎn)換完后發(fā)送讀取溫度命令 tml = Ds18b20ReadByte();//讀取溫度值共16位,先讀低字節(jié) tmh = Ds18b20ReadByte();//再讀高字節(jié) temp = tmh; temp <<= 8; temp |= tml; return temp; }
3.temp.h文件
#ifndef __TEMP_H_ #define __TEMP_H_ #include<reg51.h> //---重定義關(guān)鍵詞---// #ifndef uchar #define uchar unsigned char #endif #ifndef uint #define uint unsigned int #endif //--定義使用的IO口--// sbit DSPORT=P3^7; //--聲明全局函數(shù)--// void Delay1ms(uint ); uchar Ds18b20Init(); void Ds18b20WriteByte(uchar com); uchar Ds18b20ReadByte(); void Ds18b20ChangTemp(); void Ds18b20ReadTempCom(); int Ds18b20ReadTemp(); #endif
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。