|
基于DS18B20的溫度傳感器設計,有程序詳細解釋,適合初學者。
效果圖
- /*******************************************************************
- 基于DS18B20的溫度傳感器設計
- 版本號: V1.0;2016.9.19
- 溫度傳感器:DS18B20
- 顯示方式: LCD1602
- ********************************************************************/
- #include<reg52.h>
- #include <intrins.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit DQ=P1^6;//ds18b20與單片機連接口
- sbit RS=P1^0;
- sbit RW=P1^1;
- sbit EN=P1^2;
- sbit BEEP = P1^7;
- uchar code str1[]={" Temperature is "};
- uchar code str2[]={" designer: "};
- uchar code str3[]={" xzf586" };
- uchar data disdata[5];
- uchar p=0;
- uint tvalue;//溫度值
- uchar tflag;//溫度正負標志
- /*******************************************************************
- lcd1602程序
- 1:延時
- 2:讀數據(因為沒有忙檢測,本程序沒有)
- 3:忙檢測(本程序沒有)
- 4: 寫指令
- 5:寫數據
- 6: 初始化
- ********************************************************************/
- void delay1ms(uint ms)//延時1毫秒
- {
- uint i,j;
- for(i=0;i<ms;i++)
- for(j=0;j<114;j++);
- }
- void wr_com(uchar com)//寫指令//
- {
- delay1ms(1);
- RS=0;
- RW=0;
- EN=0;
- P0=com;
- delay1ms(1);
- EN=1;
- delay1ms(1);
- EN=0;
- }
- void wr_dat(uchar dat)//寫數據//
- {
- delay1ms(1);
- RS=1;
- RW=0;
- EN=0;
- P0=dat;
- delay1ms(1);
- EN=1;
- delay1ms(1);
- EN=0;
- }
- void lcd_init()//初始化設置//
- {
- wr_com(0x38);delay1ms(5);
- wr_com(0x08);delay1ms(5);
- wr_com(0x01);delay1ms(5);
- wr_com(0x06);delay1ms(5);
- wr_com(0x0c);delay1ms(5);
- }
- /***************************************************
- 報警程序
- ****************************************************/
- void baojing(void)
- {
- unsigned int j;
- BEEP=0;
- for (j = 49; j > 0; j--)//響30ms
- {
- BEEP = ~BEEP; //輸出頻率800Hz
- delay1ms(10); //延時310us
- }
- BEEP=0;
- }
- void display(uchar *p)//顯示//
- {
- while(*p!='\0')
- {
- wr_dat(*p);
- p++;
- delay1ms(1);
- }
- }
- void init_play()//初始化顯示
- {
- lcd_init();
- wr_com(0x80);
- display(str2);
- wr_com(0xc0);
- display(str3);
- delay1ms(3000);
- lcd_init();
- wr_com(0x80);
- display(str1);
- }
- /*******************************************************************
- ds18b20程序
- 1:延時
- 2:復位
- 3:讀數據
- 4: 寫數據
- 5:讀取溫度值并轉換(正負)
- ********************************************************************/
- void delay_18B20(uint i)//延時1微秒
- {
- while(i--);
- }
- void ds1820rst()/*ds1820復位*/
- {
- DQ = 1; //DQ復位
- delay_18B20(4); //延時
- DQ = 0; //DQ拉低
- delay_18B20(100); //精確延時大于480us
- DQ = 1; //拉高
- delay_18B20(40);
- }
- uchar ds1820rd()/*讀數據*/
- {
- uchar i=0;
- uchar dat = 0;
- for (i=8;i>0;i--)
- {
- DQ = 0; //給脈沖信號
- dat>>=1; //相當于0輸入最高位
- DQ = 1; //給脈沖信號
- if(DQ)
- dat|=0x80; // 等價于dat=dat|0x80,dat和0x80做“或”的運算,意思是最高位置1,其它位保持不變,即1輸入最高位
- delay_18B20(10);
- }
- return(dat);
- }
- void ds1820wr(uchar wdata)/*寫數據*/
- {
- uchar i=0;
- for (i=8; i>0; i--)
- {
- DQ = 0;
- DQ = wdata&0x01; //前7位置0,最后一位保持不變,輸出
- delay_18B20(10);
- DQ = 1;
- wdata>>=1; //倒數第二位到最后一位,繼續上面過程,輸出
- }
- }
- /*******************************************************************
- ds18b20溫度值規則
- 1:b=0000 0111 1101 0000=64+32+16+8+4+1=125度 最大
- 2:b=0000 0001 1101 0001=16+8+4+1+2^(-4)=29.0625度
- 3:b=0000 0000 0000 0000=0度
- 4: b=1111 1111 1111 1000轉換 前五位=1,說明負值,其絕對值為取反加1,即0000 0000 0111+1=0000 0000 1000=2^(-1)=0.5
- 5:b=1111 1100 1001 0000轉換 絕對值為取反加1,即0011 0110 1111+1=0011 0111 0000=-55 最小
- 6:15~11是符號位,都為1就是零下;都0就是零上,后10~0 這11位,是溫度的實際數據,這個數據乘0.0625就得到溫度了(正溫度算法)
- ********************************************************************/
- read_temp()/*讀取溫度值并轉換*/
- {
- uint a,b;
- ds1820rst(); //復位
- ds1820wr(0xcc);//*跳過讀序列號*/
- ds1820wr(0x44);//*啟動溫度轉換*/
- ds1820rst();
- ds1820wr(0xcc);//*跳過讀序列號*/
- ds1820wr(0xbe);//*讀取溫度*/
- a=ds1820rd(); //第一次讀的低八位,例如125度,則 a=0000 0000 1101 0000
- b=ds1820rd(); //第二次讀的高八位,例如125度,則 b=0000 0000 0000 0111
- tvalue=b; //下面三句是將這兩次讀的合起來
- tvalue<<=8; //若是125,則tvalue<<=8,即tvalue=0000 0111 0000 0000
- tvalue=tvalue|a; //tvalue|a=0000 0111 0000 0000 | 0000 0000 1101 0000=0000 0111 1101 0000
- if(tvalue<0x08ff) //若tvalue是正的,則tvalue<0000 0111 1111 1111,前五位符號都是0
- tflag=0;
- else
- {
- tvalue=~tvalue+1; //負值,取反加1
- tflag=1;
- }
- tvalue=tvalue*(0.0625)*10;//溫度值擴大10倍,精確到1位小數,注意到負溫度已經轉換了,因此可以這樣算
- return(tvalue);
- }
- /*******************************************************************/
- void ds1820disp()//溫度值顯示
- {
- uchar flagdat;
- disdata[0]=tvalue/1000+0x30;//百位數,0的ASCII碼是0x30,以此類推
- disdata[1]=tvalue%1000/100+0x30;//十位數
- disdata[2]=tvalue%100/10+0x30;//個位數
- disdata[3]=tvalue%10+0x30;//小數位
- if(tflag==0)
- //flagdat=0x20;//正溫度不顯示符號,空格的ASCII碼是0x20
- flagdat=0x2b;//正溫度顯示正號,正號的ASCII碼是0x2b
- else
- flagdat=0x2d;//負溫度顯示負號:-
- if(disdata[0]==0x30) //注意0的ASCII碼是0x30,空格的ASCII碼是0x20
- {
- disdata[0]=0x20;//如果百位為0,不顯示
- if(disdata[1]==0x30)
- {
- disdata[1]=0x20;//如果百位為0,十位為0也不顯示
- }
- }
- wr_com(0xc0+4); //LCD第二行,空4格
- wr_dat(flagdat);//顯示符號位
- wr_com(0xc1+4);
- wr_dat(disdata[0]);//顯示百位
- wr_com(0xc2+4);
- wr_dat(disdata[1]);//顯示十位
- wr_com(0xc3+4);
- wr_dat(disdata[2]);//顯示個位
- wr_com(0xc4+4);
- wr_dat(0x2e);//顯示小數點
- wr_com(0xc5+4);
- wr_dat(disdata[3]);//顯示小數位
- wr_com(0xc6+4);
- wr_dat(0x43); //C的ASCII碼是0x43
- }
- //********************主程序***********************************//
- void main()
- {
- BEEP=0;
- init_play();//初始化顯示
- while(1)
- {
- read_temp();//讀取溫度
- ds1820disp();//顯示
- if(read_temp()>950||read_temp()<860) //報警溫度 86~95之間,因為前面乘以10
- {
- baojing() ;
- }
- delay1ms(1) ;
- }
- }
復制代碼
|
評分
-
查看全部評分
|