|
使用DS18B20溫度傳感器采集溫度,并將溫度的值顯示在LCD1602上,可以通過(guò)按鍵調(diào)整溫度的閾值,當(dāng)溫度傳感器的值在閾值之外,報(bào)警電路發(fā)出警報(bào),在按鍵的時(shí)候可以將溫度傳感器的值數(shù)據(jù)保存在AT24C02中。可以通過(guò)串口將溫度傳感器的值上傳到電腦的串口調(diào)試助手。
原理圖如下:
單片機(jī)源程序如下:
- #include<reg52.h>
- #include<intrins.h>
- #include"lcd1602.h"
- #include"key.h"
- #include"timer0.h"
- #include"at24c02.h"
- #include"uart.h"
- #include"nixie.h"
-
- typedef unsigned char uchar;
- typedef unsigned int uint;
-
- sbit Bus=P3^7;//數(shù)據(jù)單總線
- sbit LED=P3^6;//LED報(bào)警燈
-
- void Delay10us(void);//10us延時(shí)函數(shù)
- void Delay600us(void);//600us延時(shí)子函數(shù)
- void Delay(uint n);//LCD1602中延時(shí)子函數(shù)
- void Delay1ms(uint t);//t毫秒延時(shí)子函數(shù)
-
- void Init_Ds(void);//DS18B20初始化
- void Write_Ds(uchar com);//向DS18B20寫入一字節(jié)
- uchar Read_Ds(void);//從DS18B20讀出一字節(jié)
- uint Get_Tem(void);//獲取溫度值
-
- void Change(uint x);//把整型數(shù)值x轉(zhuǎn)換為字符串
- void Write_com(uchar com);//寫命令子函數(shù)
- void Write_dat(uchar dat);//寫數(shù)據(jù)子函數(shù)
- void Init_1602(void);//LCD1602初始化子函數(shù)
- void Show(uchar x,uchar y,uchar *str);//LCD1602顯示子函數(shù)
-
-
- uchar str[4];//儲(chǔ)存轉(zhuǎn)換值對(duì)應(yīng)的字符串
- unsigned char KeyNum;
- char TLow,THigh;
- unsigned char t;
- unsigned char second=1;
- unsigned char minute;
- unsigned char hour;
- void main()
- {
- unsigned int temp;
- UART_Init(); //串口初始化
- LED=0;
- LCD_Init();
- // THigh=AT24C02_ReadByte(0); //讀取溫度閾值數(shù)據(jù)
- // TLow=AT24C02_ReadByte(1);
- if(THigh>125 || TLow<-55 || THigh<=TLow)
- {
- THigh=25; //如果閾值非法,則設(shè)為默認(rèn)值
- TLow=20;
- }
- LCD_ShowString(2,1,"TH:");
- LCD_ShowString(2,9,"TL:");
- LCD_ShowSignedNum(2,4,THigh,3);
- LCD_ShowSignedNum(2,12,TLow,3);
- while(1)
- {
- KeyNum=Key();
- temp=Get_Tem();
- UART_SendByte(temp); //串口發(fā)送溫度值
- if(temp>THigh) //越界判斷
- {
- LED=1;
- }
- else if(temp<TLow)
- {
- LED=1;
- }
- else
- {
- LED=0;
- }
- Change(temp);
- LCD_ShowString(1,1,"Temperature:");
- LCD_ShowString(1,13,str);
-
- /*閾值判斷及顯示*/
- if(KeyNum)
- {
- if(KeyNum==1) //K1按鍵,THigh自增
- {
- THigh++;
- if(THigh>125){THigh=125;}
- }
- if(KeyNum==2) //K2按鍵,THigh自減
- {
- THigh--;
- if(THigh<=TLow){THigh++;}
- }
- if(KeyNum==3) //K3按鍵,TLow自增
- {
- TLow++;
- if(TLow>=THigh){TLow--;}
- }
- if(KeyNum==4) //K4按鍵,TLow自減
- {
- TLow--;
- if(TLow<-55){TLow=-55;}
- }
- LCD_ShowSignedNum(2,4,THigh,3); //顯示閾值數(shù)據(jù)
- LCD_ShowSignedNum(2,12,TLow,3);
- AT24C02_WriteByte(0,temp); //寫入到At24C02中保存
- Delay(20);
- AT24C02_WriteByte(1,THigh);
- Delay(20);
- AT24C02_WriteByte(1,TLow);
- Delay(20);
- }
-
- }
- }
-
- /***************************************延時(shí)函數(shù)體**************************/
- void Delay10us(void)//10us延時(shí)函數(shù)
- {
- unsigned char a,b;
- for(b=1;b>0;b--)
- for(a=1;a>0;a--);
- }
- void Delay600us(void)//600us延時(shí)函數(shù)
- {
- unsigned char a,b;
- for(b=119;b>0;b--)
- for(a=1;a>0;a--);
- }
- void Delay1ms(uint t)//t毫秒延時(shí)函數(shù)
- {
- unsigned char a,b;
- uint i;
- for(i=0;i<t;i++)
- for(b=199;b>0;b--)
- for(a=1;a>0;a--);
- }
-
- /********************************DS18B20初始化函數(shù)*************************/
- void Init_Ds(void)//DS18B20初始化
- {
- Bus=0;//主動(dòng)拉低480-960us(此處選擇600us)
- Delay600us();
- Bus=1;//釋放總線,傳感器15-60us后拉低總線
- while(Bus);//等待傳感器拉低;
- while(!Bus);//度過(guò)傳感器被拉低的時(shí)間(60-240us)后主動(dòng)拉高
- Bus=1;//主動(dòng)拉高
- }
- /********************************向DS18B20寫入一字節(jié)***********************/
- void Write_Ds(uchar com)//從低位開始寫入
- {
- uchar mask;
- for(mask=0x01;mask!=0;mask<<=1)
- {
- //該位為0,先拉低,15us后在拉高,并通過(guò)延時(shí)使整個(gè)周期為60us
- //該位為1,先拉低并在15us內(nèi)(此處選擇5us)拉高,并通過(guò)延時(shí)使整個(gè)周期為60us
- Bus=0;
- _nop_();_nop_();_nop_();_nop_();_nop_();//先拉低5us
- if((com&mask)==0)//該位是0
- {
- Bus=0;
- }
- else//該位是1
- {
- Bus=1;
- }
- Delay10us();Delay10us();Delay10us();Delay10us();Delay10us();;//延時(shí)60us
- _nop_();_nop_();_nop_();_nop_();_nop_();
- Bus=1;//拉高
- _nop_();_nop_();//寫兩個(gè)位之間至少有1us的間隔(此處選擇2us)
- }
- }
- /********************************從DS18B20讀出一字節(jié)***********************/
- uchar Read_Ds(void)//先讀的是低位,整個(gè)讀周期至少為60us,但控制器采樣要在15us內(nèi)完成,相鄰“位”之間至少間隔1us
- {
- uchar value=0,mask;
- for(mask=0x01;mask!=0;mask<<=1)
- {
- Bus=0;//先把總線拉低超過(guò)1us(此處選擇2us)后釋放
- _nop_();_nop_();
- Bus=1;
- _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();//再延時(shí)6us后讀總線數(shù)據(jù)
- if(Bus==0)//如果該位是0
- {
- value&=(~mask);
- }
- else
- {
- value|=mask;
- }
- Delay10us();Delay10us();Delay10us();Delay10us();Delay10us();//再延時(shí)52us,湊夠至少60us的采樣周期
- _nop_();_nop_();
- Bus=1;
- _nop_();_nop_();//寫兩個(gè)位之間至少有1us的間隔(此處選擇2us)
- }
- return value;
- }
- /**********************************獲取溫度值函數(shù)***************************/
- uint Get_Tem(void)
- {
- uint temp=0;
- float tp;
- uchar LSB=0,MSB=0;
- Delay1ms(10);//延時(shí)10ms度過(guò)不穩(wěn)定期
-
- Init_Ds();//Ds18b20初始化
- Delay1ms(1);
- Write_Ds(0xcc);//跳過(guò)ROM尋址
- Write_Ds(0x44);//啟動(dòng)一次溫度轉(zhuǎn)換
- Delay1ms(1000);//延時(shí)1s等待轉(zhuǎn)化
-
- Init_Ds();//Ds18b20初始化
- Delay1ms(1);
- Write_Ds(0xcc);//跳過(guò)ROM尋址
- Write_Ds(0xbe);//發(fā)送讀值命令·
- LSB=Read_Ds();
- MSB=Read_Ds();
- temp=MSB;
- temp<<=8;
- temp|=LSB;
- tp=temp*0.0625;
- temp=tp;
- if(tp-temp>=0.5)
- {
- temp+=1;
- }
- return temp;
- }
- /******************************把整型數(shù)據(jù)轉(zhuǎn)換為字符串**********************/
- void Change(uint x)
- {
- str[0]=x/100+48;
- str[1]=(x/10)%10+48;
- str[2]=x%10+48;
- str[3]='\0';
- }
復(fù)制代碼
僅供參考,如存在錯(cuò)誤和不足之處,請(qǐng)大家回帖多多指教,切勿照搬,Keil代碼下載:
代碼.7z
(32.55 KB, 下載次數(shù): 28)
2022-4-14 17:55 上傳
點(diǎn)擊文件名下載附件
|
評(píng)分
-
查看全部評(píng)分
|