使用DS18B20溫度傳感器采集溫度,并將溫度的值顯示在LCD1602上,可以通過按鍵調整溫度的閾值,當溫度傳感器的值在閾值之外,報警電路發出警報,在按鍵的時候可以將溫度傳感器的值數據保存在AT24C02中。可以通過串口將溫度傳感器的值上傳到電腦的串口調試助手。
原理圖如下:
原理圖.PNG (145.72 KB, 下載次數: 82)
下載附件
2022-4-14 10:05 上傳
單片機源程序如下:
- #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;//數據單總線
- sbit LED=P3^6;//LED報警燈
-
- void Delay10us(void);//10us延時函數
- void Delay600us(void);//600us延時子函數
- void Delay(uint n);//LCD1602中延時子函數
- void Delay1ms(uint t);//t毫秒延時子函數
-
- void Init_Ds(void);//DS18B20初始化
- void Write_Ds(uchar com);//向DS18B20寫入一字節
- uchar Read_Ds(void);//從DS18B20讀出一字節
- uint Get_Tem(void);//獲取溫度值
-
- void Change(uint x);//把整型數值x轉換為字符串
- void Write_com(uchar com);//寫命令子函數
- void Write_dat(uchar dat);//寫數據子函數
- void Init_1602(void);//LCD1602初始化子函數
- void Show(uchar x,uchar y,uchar *str);//LCD1602顯示子函數
-
-
- uchar str[4];//儲存轉換值對應的字符串
- 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); //讀取溫度閾值數據
- // TLow=AT24C02_ReadByte(1);
- if(THigh>125 || TLow<-55 || THigh<=TLow)
- {
- THigh=25; //如果閾值非法,則設為默認值
- 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); //串口發送溫度值
- 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); //顯示閾值數據
- 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);
- }
-
- }
- }
-
- /***************************************延時函數體**************************/
- void Delay10us(void)//10us延時函數
- {
- unsigned char a,b;
- for(b=1;b>0;b--)
- for(a=1;a>0;a--);
- }
- void Delay600us(void)//600us延時函數
- {
- unsigned char a,b;
- for(b=119;b>0;b--)
- for(a=1;a>0;a--);
- }
- void Delay1ms(uint t)//t毫秒延時函數
- {
- 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初始化函數*************************/
- void Init_Ds(void)//DS18B20初始化
- {
- Bus=0;//主動拉低480-960us(此處選擇600us)
- Delay600us();
- Bus=1;//釋放總線,傳感器15-60us后拉低總線
- while(Bus);//等待傳感器拉低;
- while(!Bus);//度過傳感器被拉低的時間(60-240us)后主動拉高
- Bus=1;//主動拉高
- }
- /********************************向DS18B20寫入一字節***********************/
- void Write_Ds(uchar com)//從低位開始寫入
- {
- uchar mask;
- for(mask=0x01;mask!=0;mask<<=1)
- {
- //該位為0,先拉低,15us后在拉高,并通過延時使整個周期為60us
- //該位為1,先拉低并在15us內(此處選擇5us)拉高,并通過延時使整個周期為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();;//延時60us
- _nop_();_nop_();_nop_();_nop_();_nop_();
- Bus=1;//拉高
- _nop_();_nop_();//寫兩個位之間至少有1us的間隔(此處選擇2us)
- }
- }
- /********************************從DS18B20讀出一字節***********************/
- uchar Read_Ds(void)//先讀的是低位,整個讀周期至少為60us,但控制器采樣要在15us內完成,相鄰“位”之間至少間隔1us
- {
- uchar value=0,mask;
- for(mask=0x01;mask!=0;mask<<=1)
- {
- Bus=0;//先把總線拉低超過1us(此處選擇2us)后釋放
- _nop_();_nop_();
- Bus=1;
- _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();//再延時6us后讀總線數據
- if(Bus==0)//如果該位是0
- {
- value&=(~mask);
- }
- else
- {
- value|=mask;
- }
- Delay10us();Delay10us();Delay10us();Delay10us();Delay10us();//再延時52us,湊夠至少60us的采樣周期
- _nop_();_nop_();
- Bus=1;
- _nop_();_nop_();//寫兩個位之間至少有1us的間隔(此處選擇2us)
- }
- return value;
- }
- /**********************************獲取溫度值函數***************************/
- uint Get_Tem(void)
- {
- uint temp=0;
- float tp;
- uchar LSB=0,MSB=0;
- Delay1ms(10);//延時10ms度過不穩定期
-
- Init_Ds();//Ds18b20初始化
- Delay1ms(1);
- Write_Ds(0xcc);//跳過ROM尋址
- Write_Ds(0x44);//啟動一次溫度轉換
- Delay1ms(1000);//延時1s等待轉化
-
- Init_Ds();//Ds18b20初始化
- Delay1ms(1);
- Write_Ds(0xcc);//跳過ROM尋址
- Write_Ds(0xbe);//發送讀值命令·
- 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;
- }
- /******************************把整型數據轉換為字符串**********************/
- void Change(uint x)
- {
- str[0]=x/100+48;
- str[1]=(x/10)%10+48;
- str[2]=x%10+48;
- str[3]='\0';
- }
復制代碼
僅供參考,如存在錯誤和不足之處,請大家回帖多多指教,切勿照搬,Keil代碼下載:
代碼.7z
(32.55 KB, 下載次數: 28)
2022-4-14 17:55 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|