|
#include <AT89X52.h> //調(diào)用51單片機(jī)的頭文件 #include <Intrins.h> //--------------------------------------- //1602液晶相關(guān)I/O設(shè)置 sbit E=P2^3; //1602液晶的E腳接在P2.3口上 sbit RW=P2^4; //1602液晶的RW腳接在P2.4口上 sbit RS=P2^5; //1602液晶的RS腳接在P2.5口上 //--------------------------------------- sbit ds18b20=P3^7; sbit led=P2^7; sbit beep=P1^1; sbit key1=P1^2; sbit key2=P1^3; sbit key_set=P1^4; //--------------------------------------- //1602液晶寄存器設(shè)置 unsigned char DISbuf; //設(shè)置8位的unsigend char型寄存器用來暫存1602要顯示的內(nèi)容 //--------------------------------------- unsigned char temp1; unsigned char temp2; bit n=0; unsigned int i; unsigned char temperature=28; unsigned char code table[16]={0,0,1,2,2,3,4,4,5,6,6,7,8,8,9,9}; unsigned char code beep1[10]={0,1,0,1,0,1,0,1,0,1}; //名稱:延時函數(shù) void Delay(unsigned int nTimeDelay) { unsigned int i; while (nTimeDelay--) for (i=0;i<125;i++); } //--------------------------------------- //名稱:復(fù)位DS18B20函數(shù) //--------------------------------------- bit Reset(void) { unsigned int i; bit k; ds18b20=0; //拉低DQ總線開始復(fù)位 i=100; //保持DQ低大約870uS,符合不低于48US的要求 while(i>0) //保持DQ低大約870uS,符合不低于48US的要求 i--; //保持DQ低大約870uS,符合不低于48US的要求 ds18b20=1; //拉高準(zhǔn)備接收數(shù)據(jù) i=10; //大約80uS后 while(i>0) //大約80uS后 i--; //大約80uS后 k=ds18b20; //讀出數(shù)據(jù)并保存 i=45; //維持約400US,符合總讀時隙不低于480US的要求 while(i>0) //維持約400US,符合總讀時隙不低于480US的要求 i--; //維持約400US,符合總讀時隙不低于480US的要求 return k; //k=0為復(fù)位成功,k=1為復(fù)位失敗 } //--------------------------------------- //名稱:讀一字節(jié)函數(shù) //--------------------------------------- unsigned char ReadByte(void) { unsigned int i; unsigned char j,buf=0; for(j=0;j<8;j++) //接收8次還原一個字節(jié)數(shù)據(jù) { buf=buf>>1; //接收前,想將接收緩沖區(qū)右移 ds18b20=0; //拉低 _nop_(); _nop_(); ds18b20=1; //拉高,為讀數(shù)據(jù)做準(zhǔn)備 _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); if(ds18b20==1) buf|=0x80; //讀出1位數(shù)據(jù)保存于buf中 i=10; while(i>0) i--; } return buf; //退出的同時將接收緩沖區(qū)參數(shù)返回 } //--------------------------------------- //名稱:寫一字節(jié)函數(shù) //--------------------------------------- void WriteByte(unsigned char dat) { unsigned int i; unsigned char j; for(j=0;j<8;j++) { if(dat&0x01) //如果寫1 { ds18b20=0; //拉低 _nop_(); _nop_(); ds18b20=1; //拉高 i=14; while(i>0) i--; } else //如果寫0 { ds18b20=0; //拉低 i=14; while(i>0) i--; ds18b20=1; //拉高 _nop_(); _nop_(); } dat=dat>>1; //寫入字節(jié)右移1位 } } //--------------------------------------- //名稱:DS18B20溫度轉(zhuǎn)換函數(shù) //--------------------------------------- bit Convert(void) { if(Reset()==0) //復(fù)位DS18B20 { WriteByte(0xcc); //寫入跳過序列號命令字 Skip Rom WriteByte(0x44); //寫入溫度轉(zhuǎn)換命令字 Convert T return 1; //啟動溫度轉(zhuǎn)換成功 } else { return 0; //啟動溫度轉(zhuǎn)換失敗 } } //--------------------------------------- //名稱:轉(zhuǎn)換結(jié)束處理函數(shù) //--------------------------------------- void ReadFlash(void) { unsigned char Lsb,Msb; if(Reset()==0) //復(fù)位DS18B20 { WriteByte(0xcc); //寫入跳過序列號命令字 Skip Rom WriteByte(0xbe); //寫入讀取數(shù)據(jù)令字 Read Scratchpad Lsb=ReadByte(); //讀出第一個字節(jié)暫存于LSB Msb=ReadByte(); //讀出第二個字節(jié)暫存于MSB temp1=Lsb&0x0f; //temp1內(nèi)裝溫度參數(shù)的小數(shù)部分 temp2=(Lsb>>4)|(Msb<<4);//temp2內(nèi)裝溫度參數(shù)的整數(shù)部分 } else { temp1=0; //如果復(fù)位失敗,溫度參數(shù)清零 temp2=0; //如果復(fù)位失敗,溫度參數(shù)清零 } } //--------------------------------------- //名稱:1602液晶忙檢測函數(shù) //--------------------------------------- void LCD1602_busy(void) { P0_7=1; //將P0.7置1,為讀狀態(tài)做準(zhǔn)備 RS=0; //RS=0、RW=1、E=1時,忙信號輸出到DB7,由P0.7讀入 RW=1; //RS=0、RW=1、E=1時,忙信號輸出到DB7,由P0.7讀入 E=1; //RS=0、RW=1、E=1時,忙信號輸出到DB7,由P0.7讀入 while(P0_7==1); //由P0.7讀入1,表示1602液晶忙,需要等待 E=0; //讀完以后,恢復(fù)E的電平 } //--------------------------------------- //名稱:1600寫命令函數(shù) //--------------------------------------- void LCD1602_Write_com(unsigned char combuf) { RS=0; //選擇指令寄存器 RW=0; //選擇寫狀態(tài) P0=combuf; //將命令字通過P0口送至DB E=1; //E高電平將命令字寫入1602液晶 E=0; //寫完以后,恢復(fù)E的電平 } //--------------------------------------- //名稱:1602寫命令函數(shù)(帶忙檢測) //--------------------------------------- void LCD1602_Write_com_busy(unsigned char combuf) { LCD1602_busy(); //調(diào)用忙檢測函數(shù) LCD1602_Write_com(combuf); //調(diào)用忙檢測函數(shù) } //--------------------------------------- //名稱:1602寫數(shù)據(jù)函數(shù)(帶忙檢測) //--------------------------------------- void LCD1602_Write_data_busy(unsigned char databuf) { LCD1602_busy(); //調(diào)用忙檢測函數(shù) RS=1; //選擇數(shù)據(jù)寄存器 RW=0; //選擇寫狀態(tài) P0=databuf; //將命令字通過P0口送至DB E=1; //E高電平將命令字寫入1602液晶 E=0; //寫完以后,恢復(fù)E的電平 } //--------------------------------------- //名稱:1602液晶顯示地址寫函數(shù) //--------------------------------------- void LCD1602_Write_address(unsigned char x,unsigned char y) { x&=0x0f; //列地址限制在0-15間 y&=0x01; //行地址限制在0-1間 if(y==0) //如果是第一行 LCD1602_Write_com_busy(x|0x80); //將列地址寫入 else //如果是第二行 LCD1602_Write_com_busy((x+0x40)|0x80); //將列地址寫入 } //--------------------------------------- //名稱:1602液晶初始化函數(shù) //--------------------------------------- void LCD1602_init(void) { Delay(50); //調(diào)用延時函數(shù) LCD1602_Write_com(0x38); //8位數(shù)據(jù)總線,兩行顯示模式,5*7點陣顯示 Delay(20); //調(diào)用延時函數(shù) LCD1602_Write_com(0x38); //8位數(shù)據(jù)總線,兩行顯示模式,5*7點陣顯示 Delay(20); //調(diào)用延時函數(shù) LCD1602_Write_com(0x38); //8位數(shù)據(jù)總線,兩行顯示模式,5*7點陣顯示 LCD1602_Write_com_busy(0x38); //8位數(shù)據(jù)總線,兩行顯示模式,5*7點陣顯示 LCD1602_Write_com_busy(0x08); //顯示功能關(guān),無光標(biāo) LCD1602_Write_com_busy(0x01); //清屏 LCD1602_Write_com_busy(0x06); //寫入新的數(shù)據(jù)后,光標(biāo)右移,顯示屏不移動 LCD1602_Write_com_busy(0x0C); //顯示功能開,無光標(biāo) } //--------------------------------------- //名稱:1602液晶指定地址顯示函數(shù) //--------------------------------------- void LCD1602_Disp(unsigned char x,unsigned char y,unsigned char buf) { LCD1602_Write_address(x,y); //先將地址信息寫入 LCD1602_Write_data_busy(buf); //再寫入要顯示的數(shù)據(jù) } void disp() { if(temp2>99) temp2=99; if(temp1>15) temp1=0; LCD1602_Disp(0,0,'T'); //溫度整數(shù)部分個位 LCD1602_Disp(1,0,'e'); LCD1602_Disp(2,0,'m'); //溫度整數(shù)部分個位 LCD1602_Disp(3,0,'p'); LCD1602_Disp(4,0,':'); LCD1602_Disp(5,0,temp2/10+'0'); //溫度整數(shù)部分十位 LCD1602_Disp(6,0,temp2%10+'0'); //溫度整數(shù)部分個位 LCD1602_Disp(7,0,'.'); //. LCD1602_Disp(8,0,table[temp1]+'0'); //溫度小數(shù)部分 Set up LCD1602_Disp(9,0,0xdf); //. LCD1602_Disp(10,0,0x43); //C } void set_temp() { LCD1602_Disp(0,1,'S'); LCD1602_Disp(1,1,'e'); LCD1602_Disp(2,1,'t'); LCD1602_Disp(3,1,' '); LCD1602_Disp(4,1,':'); if(n==0) { LCD1602_Disp(5,1,temperature/10+'0'); LCD1602_Disp(6,1,temperature%10+'0'); } } unsigned char key_sm(void) { if(key_set==0) { Delay(1); if(key_set==0) while (!key_set) n=~n; led=0; beep=1; } if(key1==0&n==1) { Delay(1); if(key1==0&n==1) { LCD1602_Disp(5,1,temperature/10+'0'); LCD1602_Disp(6,1,temperature%10+'0'); while(!key1); temperature++; if(temperature>99) temperature=28; if(i>5) i=0; } } if(key2==0&n==1) { Delay(1); if(key2==0&n==1) { LCD1602_Disp(5,1,temperature/10+'0'); LCD1602_Disp(6,1,temperature%10+'0'); while(!key2); temperature--; if(temperature==0) temperature=1; if(i>5) i=0; } } return temperature; } void main(void) { LCD1602_init(); //調(diào)用1602液晶初始化函數(shù) led=0; beep=1; while(1) { if(Convert()==1) //啟動轉(zhuǎn)換 { key_sm(); ReadFlash(); //讀取溫度 disp(); set_temp(); //顯示 if(n==1) { key_sm(); LCD1602_Disp(5,1,temperature/10+'0'); LCD1602_Disp(6,1,temperature%10+'0'); Delay(200); LCD1602_Disp(5,1,' '); LCD1602_Disp(6,1,' '); Delay(200); } if(temp2>=temperature&temp2<85&n==0) { i++; led=~led; if(temp2>=temperature&i<10&n==0) { beep=~beep; } Delay(100); } if(beep==0&i>=10)beep=1; if(led==1&temp2<temperature)led=0; } } }
|