單片機DS18B20溫度傳感器C語言程序含CRC校驗_第1頁
單片機DS18B20溫度傳感器C語言程序含CRC校驗_第2頁
單片機DS18B20溫度傳感器C語言程序含CRC校驗_第3頁
單片機DS18B20溫度傳感器C語言程序含CRC校驗_第4頁
單片機DS18B20溫度傳感器C語言程序含CRC校驗_第5頁
已閱讀5頁,還剩9頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、單片機中使用DS18B20溫度傳感器C語言程序(參考1)/*                               DS18B20 測溫程序    硬件:AT89S52     (1)單線ds18b20接 P2.2 

2、0;  (2)七段數(shù)碼管接P0口    (3)使用外部電源給ds18b20供電,沒有使用寄生電源     軟件:Kei uVision 3*/#include "reg52.h"#include "intrins.h"#define uchar unsigned char#define uint unsigned intsbit ds=P22;sbit dula=P26;sbit wela=P27;uchar flag ;uint temp;   

3、0;           /參數(shù)temp一定要聲明為 int 型 uchar code table=0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71;     /不帶小數(shù)點數(shù)字編碼uchar code table1=0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef;   

4、;     /帶小數(shù)點數(shù)字編碼/*延時函數(shù)*/void TempDelay (uchar us)   while(us-); void delay(uint count) /延時子函數(shù) uint i;while(count) i=200;while(i>0)i-;count-; /*串口初始化,波特率9600,方式1 */void init_com()   TMOD=0x20;      /設置定時器1為模式2   TH1=0xfd;

5、60;      /裝初值設定波特率   TL1=0xfd;   TR1=1;          /啟動定時器   SM0=0;          /串口通信模式設置   SM1=1;/ REN=1;       

6、60;  /串口允許接收數(shù)據(jù)   PCON=0;         /波特率不倍頻/ SMOD=0;       /波特率不倍頻/ EA=1;          /開總中斷/ES=1;          /開串行中斷/*數(shù)碼管的顯示 */void di

7、splay(uint temp)    uchar bai,shi,ge;    bai=temp/100;    shi=temp%100/10;    ge=temp%100%10;dula=0;    P0=tablebai; /顯示百位dula=1;         /從0到1,有個上升沿,解除鎖存,顯示相應段 dula=0;   

8、;      /從1到0再次鎖存    wela=0;    P0=0xfe;wela=1;wela=0;delay(1);    /延時約2msP0=table1shi; /顯示十位dula=1;    dula=0;P0=0xfd;wela=1;    wela=0;    delay(1);    P0=tablege; /顯示個位

9、dula=1;    dula=0;P0=0xfb;wela=1;    wela=0;    delay(1); /* 時序:初始化時序、讀時序、寫時序。所有時序都是將主機(單片機)作為主設備,單總線器件作為從設備。而每一次命令和數(shù)據(jù)的傳輸都是從主機主動啟動寫時序開始,如果要求單總線器件回送數(shù)據(jù),在進行寫命令后,主機需啟動讀時序完成數(shù)據(jù)接收。數(shù)據(jù)和命令的傳輸都是低位在先。 初始化時序:復位脈沖 存在脈沖        讀;1 或 0時

10、序        寫;1 或 0時序只有存在脈沖信號是從18b20(從機)發(fā)出的,其它信號都是由主機發(fā)出的。存在脈沖:讓主機(總線)知道從機(18b20)已經(jīng)做好了準備。*/*-初始化:檢測總線控制器發(fā)出的復位脈沖和ds18b20的任何通訊都要從初始化開始初始化序列包括一個由總線控制器發(fā)出的復位脈沖和跟在其后由從機發(fā)出的存在脈沖。初始化:復位脈沖+存在脈沖具體操作:總線控制器發(fā)出(TX)一個復位脈沖 (一個最少保持480s 的低電平信號),然后釋放總線,進入接收狀態(tài)(RX)。單線總線由5K 上拉電阻拉到高電平。探測到I/O

11、引腳上的上升沿后DS1820 等待1560s,然后發(fā)出存在脈沖(一個60240s 的低電平信號)。具體看18b20 單線復位脈沖時序和1-wire presence detect "的時序圖-*/void ds_reset(void)   ds=1;   _nop_();        /1us   ds=0;   TempDelay(80); /當總線停留在低電平超過480us,總線上所以器件都將被復位,這里延/時約530us總

12、60;線停留在低電平超過480s,總線上的所有器件都將被復位。   _nop_();    ds=1;           /產(chǎn)生復位脈沖后,微處理器釋放總線,讓總線處于空閑狀態(tài),原因查18b20中文資料TempDelay(5); /釋放總線后,以便從機18b20通過拉低總線來指示其是否在線,              

13、;    /存在檢測高電平時間:1560us, 所以延時44us,進行1-wire presence detect(單線存在檢測)   _nop_();   _nop_();   _nop_();   if(ds=0)        flag=1;       /detect 18b20 success   else  

14、;      flag=0;       /detect 18b20 failTempDelay(20);    /存在檢測低電平時間:60240us,所以延時約140us   _nop_();   _nop_();   ds=1;          /再次拉高總線,讓總線處于空閑狀態(tài)/*/原理解釋:控制器對

15、 18B20 操作流程:1 , 復位 : 首先我們必須對 DS18B20 芯片進行復位 , 復位就是由控制器 ( 單片機 )給 DS18B20 單總線至少 480uS 的低電平信號 。 當 18B20 接到此復位信號后則會 在1560uS 后回發(fā)一個芯片的存在脈沖。2 , 存在脈沖 : 在復位電平結(jié)束之后 , 控制器應該將數(shù)據(jù)單總線拉高 , 以便于 在1560uS 后接收存在脈沖,存在脈沖為一個 60240uS 的低電平信號。至此,通信雙方已經(jīng)達成了基本的協(xié)議,接下來將會是控制器與 18B20 間的數(shù)據(jù)通信 。 /*-讀/寫時間隙:DS1820 的數(shù)據(jù)讀寫是通過時間隙處理位和命令字來確認信息交

16、換。-*/bit ds_read_bit(void)    /讀一位   bit dat;   ds=0;         /單片機(微處理器)將總線拉低_nop_();       /讀時隙起始于微處理器將總線拉低至少1us   ds=1;        /拉低總線后接著釋放總線,讓從機18b20

17、能夠接管總線,輸出有效數(shù)據(jù)   _nop_();   _nop_();          /小延時一下,讀取18b20上的數(shù)據(jù) ,因為從ds18b20上輸出的數(shù)據(jù)/在讀"時間隙"下降沿出現(xiàn)15us內(nèi)有效   dat=ds;           /主機讀從機18b20輸出的數(shù)據(jù),這些數(shù)據(jù)在讀時隙的下降沿出現(xiàn)/15us內(nèi)有效 

18、60;  TempDelay(10);    /所有讀"時間隙"必須60120us,這里77us   return(dat);       /返回有效數(shù)據(jù)原理:圖 8讀時間隙時控制時的采樣時間應該更加的精確才行 , 讀時間隙時也是必須先由主機產(chǎn)生至少 1uS 的低電平,表示讀時間的起始。隨后在總線被釋放后的 15uS 中DS18B20 會發(fā)送內(nèi)部數(shù)據(jù)位,這時控制如果發(fā)現(xiàn)總線為高電平表示讀出 “ 1 ” ,如果總線為低電平則表示讀出數(shù)據(jù) “ 0 ” 。每一位

19、的讀取之前都由控制器加一個起始信號。注意:如圖 8 所示,必須在讀間隙開始的 15uS 內(nèi)讀取數(shù)據(jù)位才可以保證通信的正確。在通信時是以 8 位 “ 0 ” 或 “ 1 ” 為一個字節(jié) , 字節(jié)的讀或?qū)懯菑母呶婚_始的 , 即A7 到 A0. 字節(jié)的讀寫順序也是如圖 2 自上而下的。uchar ds_read_byte(void ) /讀一字節(jié)uchar value,i,j;value=0;           /一定別忘了給初值for(i=0;i<8;i+)   

20、; j=ds_read_bit();     value=(j<<7)|(value>>1);   /這一步的說明在一個word文檔里面 ? return(value);        /返回一個字節(jié)的數(shù)據(jù)void ds_write_byte(uchar dat) /寫一個字節(jié)uchar i;bit onebit;        /一定不要忘了,onebit是一位for(i

21、=1;i<=8;i+)     onebit=dat&0x01;    dat=dat>>1; /由低到高傳送數(shù)據(jù)if(onebit)      /寫 1ds=0;_nop_();          _nop_();      /看時序圖,至少延時1us,才產(chǎn)生寫"時間隙" ds=1;  &#

22、160;    /寫時間隙開始后的15s內(nèi)允許數(shù)據(jù)線拉到高電平     TempDelay(5); /所有寫時間隙必須最少持續(xù)60uselse         /寫 0ds=0;     TempDelay(8);    /主機要生成一個寫0 時間隙,必須把數(shù)據(jù)線拉到低電平并保持至少60s,這里64usds=1;_nop_();    

23、_nop_(); 主機(單片機)控制18B20完成溫度轉(zhuǎn)換要經(jīng)過三個步驟:每一次讀寫之前都要18B20進行復位操作,復位成功后發(fā)送一條ROM指令,最后發(fā)送RAM指令,這樣才能對DS18b20進行預定的操作。復位要求主CPU將數(shù)據(jù)線下拉500us,然后釋放,當ds18B20受到信號后等待1660us,后發(fā)出60240us的存在低脈沖,主CPU收到此信號表示復位成功*/*-進行溫度轉(zhuǎn)換:先初始化然后跳過ROM:跳過64位ROM地址,直接向ds18B20發(fā)溫度轉(zhuǎn)換命令,適合單片工作發(fā)送溫度轉(zhuǎn)換命令-*/void tem_change()ds_reset(); delay(1);  

24、;            /約2msds_write_byte(0xcc);/單線情況下,跳躍ROM指令ds_write_byte(0x44);/溫度轉(zhuǎn)換指令/*-獲得溫度:-*/uint get_temperature()float wendu;uchar a,b;ds_reset();delay(1);              /約2msds_writ

25、e_byte(0xcc);ds_write_byte(0xbe);/發(fā)送讀溫度命令a=ds_read_byte();/讀出溫度低8位b=ds_read_byte();/讀書溫度高8位temp=b;temp<<=8;temp=temp|a;wendu=temp*0.0625;     /得到真實十進制溫度值,因為DS18B20                  

26、60;                 /可以精確到0.0625度,所以讀回數(shù)據(jù)的最低位代表的是 /0.0625度temp=wendu*10+0.5;       /放大十倍,這樣做的目的將小數(shù)點后第一位                &#

27、160;                      /也轉(zhuǎn)換為可顯示數(shù)字,同時進行一個四舍五入操作。return temp;/*-讀ROM   -*/*void ds_read_rom()               &

28、#160;  /這里沒有用到   uchar a,b;   ds_reset();   delay(30);   ds_write_byte(0x33);   a=ds_read_byte();   b=ds_read_byte();*/void main()   uint a;   init_com();   while(1)   tem_change();  &#

29、160;       /12位轉(zhuǎn)換時間最大為750msfor(a=10;a>0;a-)display( get_temperature();    單片機中使用DS18B20溫度傳感器C語言程序含CRC校驗(參考2)CRC是序列號的校驗碼 用來驗證序列號對不對的。序列號一般是沒標的要自己讀。給你個讀序列號的程序改下端口就能用:#include <reg51.h> #include <intrins.h> #define uchar unsigned char #define uint

30、unsigned int sbit DQ = P20; /定義DS18B20端口DQ sbit BEEP=P37 ; /蜂鳴器驅(qū)動線 bit presence ; sbit LCD_RS = P26; sbit LCD_RW = P25; sbit LCD_EN = P24; uchar code cdis1 = " DS18B20 OK " uchar code cdis2 = " " uchar code cdis3 = " DS18B20 ERR0R " uchar code cdis4 = " PLEASE CHEC

31、K " unsigned char data display2 = 0x00,0x00; unsigned char data RomCode8 = 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00; unsigned char Temp; unsigned char crc; void beep(); #define delayNOP(); _nop_();_nop_();_nop_();_nop_(); /*/ void delay1(int ms) unsigned char y; while(ms-) for(y = 0; y<250; y

32、+) _nop_(); _nop_(); _nop_(); _nop_(); /*/ /*檢查LCD忙狀態(tài) */ /*lcd_busy為1時,忙,等待。lcd-busy為0時,閑,可寫指令與數(shù)據(jù)。 */ /*/ bit lcd_busy() bit result; LCD_RS = 0; LCD_RW = 1; LCD_EN = 1; delayNOP(); result = (bit)(P0&0x80); LCD_EN = 0; return(result); /*/ /*寫指令數(shù)據(jù)到LCD */ /*RS=L,RW=L,E=高脈沖,D0-D7=指令碼。 */ /*/ void lc

33、d_wcmd(uchar cmd) while(lcd_busy(); LCD_RS = 0; LCD_RW = 0; LCD_EN = 0; _nop_(); _nop_(); P0 = cmd; delayNOP(); LCD_EN = 1; delayNOP(); LCD_EN = 0; /*/ /*寫顯示數(shù)據(jù)到LCD */ /*RS=H,RW=L,E=高脈沖,D0-D7=數(shù)據(jù)。 */ /*/ void lcd_wdat(uchar dat) while(lcd_busy(); LCD_RS = 1; LCD_RW = 0; LCD_EN = 0; P0 = dat; delayNOP(

34、); LCD_EN = 1; delayNOP(); LCD_EN = 0; /*/ /* LCD初始化設定 */ /*/ void lcd_init() delay1(15); lcd_wcmd(0x01); /清除LCD的顯示內(nèi)容 lcd_wcmd(0x38); /16*2顯示,5*7點陣,8位數(shù)據(jù) delay1(5); lcd_wcmd(0x38); delay1(5); lcd_wcmd(0x38); delay1(5); lcd_wcmd(0x0c); /顯示開,關(guān)光標 delay1(5); lcd_wcmd(0x06); /移動光標 delay1(5); lcd_wcmd(0x01

35、); /清除LCD的顯示內(nèi)容 delay1(5); /*/ /* 設定顯示位置 */ /*/ void lcd_pos(uchar pos) lcd_wcmd(pos | 0x80); /數(shù)據(jù)指針=80+地址變量 /*/ /*us級延時函數(shù) */ /*/ void Delay(unsigned int num) while( -num ); /*/ /*初始化ds1820 */ /*/ Init_DS18B20(void) DQ = 1; /DQ復位 Delay(8); /稍做延時 DQ = 0; /將DQ拉低 Delay(90); /精確延時 大于 480us DQ = 1; /拉高總線 D

36、elay(8); presence = DQ; /讀取存在信號 Delay(100); DQ = 1; return(presence); /返回信號,0=presence,1= no presence /*/ /* 讀一位(bit) */ /*/ uchar read_bit(void) unsigned char i; DQ = 0; /將DQ 拉低開始讀時間隙 DQ = 1; / then return high for (i=0; i<3; i+); / 延時15s return(DQ); / 返回 DQ 線上的電平值 /*/ /* 讀一個字節(jié) */ /*/ ReadOneCha

37、r(void) unsigned char i = 0; unsigned char dat = 0; /for (i = 8; i > 0; i-) / / read_bit(); / DQ = 0; / 給脈沖信號 / dat >>= 1; / DQ = 1; / 給脈沖信號 for (i=0;i<8;i+) / 讀取字節(jié),每次讀取一個字節(jié) if(read_bit() dat|=0x01<<i; / 然后將其左移 / if(DQ) / dat |= 0x80; Delay(4); return (dat); /*/ /* 寫一位 */ /*/ void

38、write_bit(char bitval) DQ = 0; / 將DQ 拉低開始寫時間隙 if(bitval=1) DQ =1; / 如果寫1,DQ 返回高電平 Delay(5); / 在時間隙內(nèi)保持電平值, DQ = 1; / Delay函數(shù)每次循環(huán)延時16s,因此delay(5) = 104s /*/ /* 寫一個字節(jié) */ /*/ WriteOneChar(unsigned char dat) unsigned char i = 0; unsigned char temp; / for (i = 8; i > 0; i-) / for (i=0; i<8; i+) / 寫入

39、字節(jié), 每次寫入一位 / DQ = 0; / DQ = dat&0x01; / Delay(5); / DQ = 1; temp = dat>>i; temp &= 0x01; write_bit(temp); / dat>>=1; Delay(5); /*/ /* 讀取64位序列碼 */ /*/ Read_RomCord(void) unsigned char j; Init_DS18B20(); WriteOneChar(0x33); / 讀序列碼的操作 for (j = 0; j < 8; j+) RomCodej = ReadOneChar

40、() ; /*/ /*DS18B20的CRC8校驗程序 */ /*/ uchar CRC8() uchar i,x; uchar crcbuff; crc=0; for(x = 0; x <8; x+) crcbuff=RomCodex; for(i = 0; i < 8; i+) if(crc crcbuff)&0x01)=0) crc >>= 1; else crc = 0x18; /CRC=X8+X5+X4+1 crc >>= 1; crc |= 0x80; crcbuff >>= 1; return crc; /*/ /* 數(shù)據(jù)轉(zhuǎn)

41、換與顯示 */ /*/ Disp_RomCode() uchar j; uchar H_num=0x40; /LCD第二行初始位置 for(j=0;j<8;j+) Temp = RomCodej; display0=(Temp&0xf0)>>4); if(display0>9) display0=display0+0x37; elsedisplay0=display0+0x30; lcd_pos(H_num); lcd_wdat(display0); /高位數(shù)顯示 H_num+; display1=(Temp&0x0f); if(display1>

42、9) display1=display1+0x37; else display1=display1+0x30; lcd_pos(H_num); lcd_wdat(display1); /低位數(shù)顯示 H_num+; /*/ /* 蜂鳴器響一聲 */ /*/ void beep() unsigned char y; for (y=0;y<100;y+) Delay(60); BEEP=!BEEP; /BEEP取反 BEEP=1; /關(guān)閉蜂鳴器 Delay(40000); /*/ /* DS18B20 OK 顯示菜單 */ /*/ void Ok_Menu () uchar m; lcd_in

43、it(); /初始化LCD lcd_pos(0); /設置顯示位置為第一行的第1個字符 m = 0; while(cdis1m != '0') lcd_wdat(cdis1m); /顯示字符 m+; lcd_pos(0x40); /設置顯示位置為第二行第1個字符 m = 0; while(cdis2m != '0') lcd_wdat(cdis2m); /顯示字符 m+; /*/ /* DS18B20 ERROR 顯示菜單 */ /*/ void Error_Menu () uchar m; lcd_init(); /初始化LCD lcd_pos(0); /設置

44、顯示位置為第一行的第1個字符 m = 0; while(cdis3m != '0') lcd_wdat(cdis3m); /顯示字符 m+; lcd_pos(0x40); /設置顯示位置為第二行第1個字符 m = 0; while(cdis4m != '0') lcd_wdat(cdis4m); /顯示字符 m+; /*/ /* 主函數(shù) */ /*/ void main() P0 = 0xff; P2 = 0xff; while(1) Ok_Menu (); Read_RomCord(); /讀取64位序列碼 CRC8(); /CRC效驗 if(crc=0) /

45、CRC效驗正確 Disp_RomCode(); /顯示64位序列碼 beep(); while(!presence) Init_DS18B20(); delay1(1000); Error_Menu (); do Init_DS18B20(); beep(); while(presence); /*/曾經(jīng)編寫的DS18B20程序原來一切正常,但是最近拿來用時發(fā)現(xiàn)偶爾會出現(xiàn)數(shù)據(jù)錯誤,例如正常室溫20度,但是偶爾會出現(xiàn)負值或很高的溫度,懷疑新購的DS18B20時序參數(shù)同上批有點差別,有遇到過這種情況的嗎?大家在使用DS18B20時是讀出全部9個自己并用CRC進行校驗嗎?請大家指教。晶振頻率11.0

46、592MHz,AT89C52,我的代碼如下:unsigned char DS18B20_ReadByte() unsigned char i, dat=0; for(i=0; i<8; i+) dat >>= 1; /開始另一個讀周期前必須有1us以上的高電平恢復期 DQ = 1; Delay2us(); /產(chǎn)生讀起始信號,數(shù)據(jù)線保持在低電平至少1s,DS18B20在總線下降沿后輸出15us的有效數(shù)據(jù) DQ = 0; Delay2us(); DQ = 1; Delay8us(); if(DQ) dat |= 0x80; /延時60us以上來滿足DS18B20的時序 Delay65us(); return dat; /* 對總線上唯一的DS18B20進行溫度轉(zhuǎn)換及讀取,返回帶符號整形值。計算溫度時需要乘以0.0625,如果出錯返回值為200,超過其測溫范圍*/int DS18B20_GetTemperature(void) unsigned

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論