- #include<reg51.h> //51單片機的頭文件
- #define uchar unsigned char //宏定義,用uchar來代替unsigned char(無符號字符型變量,也即是無符號的8位變量),
- //宏定義的原因就是書寫方便,宏定義后,uchar可直接用來定義變量
- #define uint unsigned int //原因同上,不過要注意,unsigned int為無符號的整型變量
- uint present; // 實際溫度(擴大了10倍)
- uint setting=30; //設定值
- sbit led=P3^5; //sbit是用來管腳的。此處定義LED燈由P3.5口控制
- sbit buzzer=P3^6; //蜂鳴器由P3.6口控制
- sbit DS=P3^7; //讀取溫度引腳
- sbit NixieTube0_DIG1=P1^2; // 實際溫度顯示十位數(shù)字的數(shù)碼管位選端
- sbit NixieTube0_DIG2=P1^3; //// 實際溫度顯示個位數(shù)字的數(shù)碼管位選端
- sbit NixieTube1_DIG1=P1^4; //// 設定溫度顯示十位數(shù)字的數(shù)碼管位選端
- sbit NixieTube1_DIG2=P1^5; //// 設定溫度顯示個位數(shù)字的數(shù)碼管位選端
-
- sbit add=P1^0; //按鍵加
- sbit sub=P1^1; //按鍵減
- unsigned char code table[]={0x82,0xF3,0x4A,0x62,0x33,0x26,0x06,0xE3,0x02,0x22}; //數(shù)碼管端碼表,相當于顯示緩沖區(qū),依次是0——9.
- void delay(uint count) //延時函數(shù),用來進行延時,應該是毫秒級延時
- {
- uint i;
- while(count) // count為函數(shù)的形參,當count為0時,跳出此處while循環(huán)
- {
- i=200;
- while(i>0) //
- i--; //此i--和while(i>0)可以看成是一個整體,當i=0時,就會跳出,執(zhí)行count--。
- count--; //count自減一次,i就會由200減到0
- }
- }
- /***********************************************************
- void initialize(void)//初始化函數(shù)
- 溫度傳感器采用的是DS18b20,此傳感器采用的
- 是“單總線”來傳輸數(shù)據(jù)。
- 在使用DS18b20時,要對其進行初始化操作,其初始化的要求是(根據(jù)DS18b20的時序圖得):
- (1)先將數(shù)據(jù)線置1,但是置1的時間要盡可能短(可以直接忽略此操作,因為51單片機引腳上電默認就是高電平。)。
- (2)將數(shù)據(jù)線(DS)拉低
- (3)延時750us左右
- (4)再將數(shù)據(jù)線(DS)拉高
- (5)進行短暫延時
- *****************************************************************/
- void initialize(void) //初始化
- {
-
- uint i;
- DS=0; //將DS(P3.7)引腳拉低。請注意,這里的DS不是變量,而是單片機的引腳�。�!
- i=103;
- while(i>0)i--; //延時
- DS=1; //將DS拉高
- i=4;
- while(i>0)i--; //短暫延時
- }
- /*************************************************************************************
- 說明:DS18b20采用的是單總線,一次只能讀取溫度的1個Bit。
- 函數(shù)作用:bit tmpreadbit(void) //溫度讀取函數(shù),此處讀取的是溫度的1個bit,帶返回值
- 函數(shù)使用舉例:A=tmpreadbit(); // 變量A保存的只是溫度的一個bit
- DS18B20溫度讀取時序用單片機來實現(xiàn)的步驟如下:
- (1) 數(shù)據(jù)線DS拉低
- (2) 延時6us左右
- (3)將數(shù)據(jù)線DS拉高
- (4)延時4us左右
- (5) 此時DS便會得到一個狀態(tài)位,即1個Bit的數(shù)據(jù)
- (6)延時30us左右
- **************************************************************************************/
- bit tmpreadbit(void) //溫度讀取函數(shù),此處讀取的是溫度的1個bit.帶返回值
- {
- uint i;
- bit dat;
- DS=0;i++; //將數(shù)據(jù)線拉低并延時
- DS=1;i++;i++; //將數(shù)據(jù)線拉高并延時
- dat=DS; //讀取1個bit數(shù)據(jù),此處注意,DS變成了輸入引腳,DS18b20的數(shù)據(jù)會保存到局部變量dat中
- i=8;while(i>0)i--; //延時
- return (dat); //將讀取的數(shù)據(jù)返回
- }
- /***********************************************************************************************
- 說明:DS18b20采用的是單總線,一次只能讀取溫度的1個Bit。溫度一共8個bit,此函數(shù)共讀了8次
- 函數(shù)作用:uchar tmpread(void) //溫度讀取函數(shù),此處讀取的是溫度數(shù)據(jù)的原始數(shù)據(jù),帶返回值
- 函數(shù)使用舉例:A=tmpread(); // 變量A保存的是溫度的原始數(shù)據(jù)
- *************************************************************************************************/
- uchar tmpread(void)
- {
- uchar i,j,dat;
- dat=0;
- for(i=1;i<=8;i++) //采用for 循環(huán),讀取原始溫度數(shù)據(jù)
- {
- j=tmpreadbit(); //讀取一個位
- dat=(j<<7)|(dat>>1);//讀取的溫度最低位在前,這樣剛好一個字節(jié)的溫度在dat中
- }
- return(dat); //將溫度數(shù)據(jù)返回
- }
-
- void tmpwritebyte(uchar dat) // 寫指令函數(shù), dat為形參。
- {
- uint i;
- uchar j;
- bit testb;
- for(j=1;j<=8;j++) //for循環(huán),8次,剛好寫一個字節(jié)
- {
- testb=dat&0x01; //將形參的最低位與1相與,1&1=1,0&1=0;
- dat=dat>>1; //執(zhí)行完testb=dat&0x01;把傳入的形參右移一位,方便判斷下一位數(shù)據(jù)是0還是1,共移位8次,保證寫入一個字節(jié)
- if(testb) //write 1
- {
- DS=0;
- i++;i++;
- DS=1; //DS=1的延時比較長,寫入的就是1
- i=8;while(i>0)i--;
- }
- else
- {
- DS=0; //write 0
- i=8;while(i>0)i--; //DS=0的延時比較長,寫入的就是0
- DS=1;
- i++;i++;
- }
- }
- }
- void tmpchange(void) //溫度轉(zhuǎn)換函數(shù),
- {
- initialize(); //初始
- delay(1);
- tmpwritebyte(0xcc); //跳過讀ROM指令
- tmpwritebyte(0x44); //告訴DS18b20轉(zhuǎn)換溫度
- }
- uint tmp() //轉(zhuǎn)換函數(shù),將原始數(shù)據(jù)轉(zhuǎn)化成實際的溫度數(shù)據(jù)
- {
- float tt;
- uchar a,b;
- initialize(); //初始化
- delay(1); //延時
- tmpwritebyte(0xcc);//跳過讀ROM指令
- tmpwritebyte(0xbe); //讀溫度指令
- a=tmpread(); // 低8位數(shù)據(jù),即溫度的小數(shù)部分
- b=tmpread(); //高8位,即溫度的整數(shù)部分
- present=b;
- present<<=8; //將整數(shù)部分右移8位
- present=present|a; //將兩個字節(jié)組合成一個字
- tt=present*0.0625; //分辨率是0.0625,即原始數(shù)據(jù)*分辨率=實際溫度
- present=tt*10+0.5; //乘10表示小數(shù)點后面只取一位,+0.5是表示四舍五入
- return present; //返回實際溫度
- }
- //用的是共陽極數(shù)碼管,顯示原理采用的是動態(tài)顯示
- void display0(uint temp) //溫度顯示函數(shù) ,temp 為形參
- {
- uchar A1,A2,A2t;
- ////此處注意!因溫度讀取函數(shù)中 present=tt*10+0.5;即將溫度擴大了10倍,所以原始溫度的十位變成了百位,
- //各位變成了十位,十分位變成了個位,因此我們只需取百位上的數(shù)字和十位上的數(shù)字即可。注意,是數(shù)字,不是數(shù)!
- A1=temp/100; //取模,將百位數(shù)字取下,存到變量A1中,
- A2t=temp%100; //取余,比如傳進來的temp=325,則325%100=25;
- A2=A2t/10; //將余數(shù)對10取模,比如 25/10=2;
-
- NixieTube0_DIG1=1; //打開數(shù)碼管位選端
- if(A1<=9|A1>=0) //判斷A1是否位一位數(shù)字,實際溫度的十位上的數(shù)字
- P2=table[A1]; //送入顯示
- delay(1); //延時,待顯示穩(wěn)定
- NixieTube0_DIG1=0; // 關(guān)斷數(shù)碼管
- NixieTube0_DIG2=1; //打開數(shù)碼管位選端
- if(A2<=9|A2>=0) //判斷A2是否位一位數(shù)字,實際溫度的個位上的數(shù)字
- P2=table[A2]; //送入顯示
- delay(1); //延時,待顯示穩(wěn)定
- NixieTube0_DIG2=0; // 關(guān)斷數(shù)碼管
-
- }
- void display1(uint spare) //設定溫度顯示
- {
- uchar B1,B2;
- B1=spare/10; //將設定溫度對10取模,獲取十位上的數(shù)字
- B2=spare%10; //將設定溫度對10取余,獲取個位上的數(shù)字
- NixieTube1_DIG1=1; ////打開數(shù)碼管位選端
- P2=table[B1]; //送入十位上的數(shù)字
- delay(1); ////延時,待顯示穩(wěn)定
- NixieTube1_DIG1=0; //關(guān)斷顯示
-
- NixieTube1_DIG2=1; //打開顯示
- P2=table[B2]; //送入個位上的數(shù)字
- delay(1); //延時,待顯示穩(wěn)定
- NixieTube1_DIG2=0; //關(guān)斷顯示
- }
- void main() //主函數(shù)
- {
-
- uchar a;
- uchar b;
- uchar c;
- P2=0xf7; //對P2口初始化,開機先不讓數(shù)碼管顯示
- NixieTube0_DIG1=1; //初始化,數(shù)碼管位選端拉高
- NixieTube0_DIG2=1; //同上
- NixieTube1_DIG1=1; //同上
- NixieTube1_DIG2=1; //同上
- buzzer=0; //蜂鳴器引腳拉低,上電,蜂鳴器響一秒
- delay(1000); //延時1S左右
- while(1)
- {
- tmpchange();//向溫度傳感器寫入溫度轉(zhuǎn)換指令
- if(add==1) //如果 按鍵加 沒有按下
- b=1; //b=1;b的作用相當于松手檢測
- if(add==0&b==1) //如果按鍵按下
- {
- if(setting==99)
- {}
- else
- {
- setting++;//設定值自加一次
- b=0; //只有按下松手后,再按 按鍵加 才能再次使設定值自加一次
- }
- };
- if(sub==1) //按鍵減未被按下
- c=1; //作用與b相同
- if(sub==0&c==1) //如果按鍵減 被按下
- {
- if(setting==0)
- {}
- else
- {
- setting--;//設定值自減一次
- c=0; //作用同上面的b
- }
- };
- if(present<=setting*10) //如果實際溫度小于設定溫度
- {
- buzzer=0; //蜂鳴器不響
- led=0; //燈亮
- }
- else
- {
- buzzer=0; //否則 蜂鳴器響
- led=1; //燈不亮
- }
- for(a=10;a>0;a--)
- {
- display0(tmp()); //顯示實際溫度
- display1(setting); //顯示設定溫度
- }
- }
- }
復制代碼
|