一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

您好,歡迎來(lái)電子發(fā)燒友網(wǎng)! ,新用戶?[免費(fèi)注冊(cè)]

您的位置:電子發(fā)燒友網(wǎng)>電子元器件>傳感器>

DS18b20如何讀取它的負(fù)溫度值呢? - 全文

2017年11月23日 15:24 網(wǎng)絡(luò)整理 作者: 用戶評(píng)論(0
關(guān)鍵字:DS18B20(80969)

  單片機(jī) 測(cè)溫芯片 18B20 是一款常用的IC,優(yōu)勢(shì)特點(diǎn)不多說(shuō),這里主要討論溫度值的處理,尤其是負(fù)溫度。

  18B20片內(nèi)有一個(gè)9Byte的 SRAM 和一個(gè)3Byte的 EEPROM。如下圖:

 DS18b20如何讀取它的負(fù)溫度值呢?

  其中我們需要使用的就是SRAM中的前兩個(gè)字節(jié),這里儲(chǔ)存的就是我們要的溫度值。這兩個(gè)字節(jié)的結(jié)構(gòu)如下:

 DS18b20如何讀取它的負(fù)溫度值呢?

  我們可以看到,LS(低字節(jié))的高四位 和 MS(高字節(jié))的低四位共8個(gè)字節(jié)構(gòu)成了實(shí)際的一個(gè)帶符號(hào)位的字節(jié)數(shù)據(jù)可以表示(-128~127)足夠表示18B20的溫度范圍。MS的高四位為符號(hào)為的擴(kuò)展,當(dāng)溫度值為正時(shí)MS高5位(圖中S的五位)全為0,溫度值為負(fù)時(shí)全為1。LS的低四位為小數(shù)部分,不是要求太高的話可以忽略。我們這里暫不套路小數(shù)部分的處理方法。

  下面我們就來(lái)討論整數(shù)部分的數(shù)據(jù)處理方法。

  整數(shù)部分我們實(shí)際只要高字節(jié)的第四位和低字節(jié)的高四位。首先通過(guò)移位求或后生成一個(gè)無(wú)符號(hào)位的字節(jié)。然后判斷這個(gè)無(wú)符號(hào)的值是否大于127,如果大于128說(shuō)明是個(gè)負(fù)溫度需要處理,否則就可以直接返回。

  18B20的負(fù)溫度使用補(bǔ)碼形式輸出,我們只需要對(duì)這個(gè)字節(jié)進(jìn)行取反加1后就是這個(gè)負(fù)溫度的絕對(duì)值,這時(shí)候我們需要一個(gè)符號(hào)標(biāo)記告訴輸出函數(shù)這是個(gè)負(fù)溫度需要顯示負(fù)號(hào)即可。

  下面貼出數(shù)據(jù)處理部分的代碼:

  uchar readtemp() //讀取溫度

  {

  uchar temp = 0;

  uchar tmp[2]

  reset();

  writebyte(0xCC); // 跳過(guò)序列號(hào)

  writebyte(0x44); // 啟動(dòng)溫度轉(zhuǎn)換

  delayms(1000);

  reset();

  writebyte(0xCC);

  writebyte(0xBE); //讀9個(gè)寄存器,前兩個(gè)為溫度

  tmp[0]=readbyte(); //低位

  tmp[1]=readbyte(); //高位

  temp = ((tmp[1]《《4)&0xF0)|((tmp[0]》》4)&0x0F);

  if(temp》127)

  {

  temp = ~temp + 1;

  }

  return (temp);

  }

  如何用51單片機(jī)讀取ds18b20的取負(fù)溫度?

  18b20的ram中,前兩個(gè)字節(jié)放的是溫度信息。其中第二個(gè)字節(jié)的高五位是符號(hào)位,當(dāng)溫度為正的時(shí)候,高五位的字節(jié)是0,當(dāng)溫度為負(fù)的時(shí)候,高五位字節(jié)為一。當(dāng)溫度為正的時(shí)候,只需要將兩個(gè)字節(jié)的數(shù)合到一個(gè)字節(jié),然后乘以0.0625就是實(shí)際的溫度。

  那么,當(dāng)溫度為負(fù)的時(shí)候,該怎么讀取溫度呢?是將兩個(gè)字節(jié)合為一個(gè)字節(jié),然后先取反,再加一,最后再和0.0625相乘嗎?這樣得出的結(jié)果就是實(shí)際的負(fù)溫度值嗎?

  判斷是否是負(fù),就是取高幾位的讀取值采用與的方式判斷,比如(000) 11111 00001000,那么高5位可以這樣弄,tempH&0x1f,如果這個(gè)值=1;說(shuō)明是負(fù)的,否則就是正的啊,不過(guò)有一點(diǎn),取反是對(duì)的,還要加1啊,記得哦。

  至于在LCD中顯示的,確實(shí)是按你說(shuō)的那樣,直接寫上一個(gè)符號(hào)即可。

  DS18b20 輸出的負(fù)溫度數(shù)據(jù)是定點(diǎn)補(bǔ)碼(小數(shù)點(diǎn)后固定二進(jìn)制四位),符號(hào)可由最高位判定(0為正,1為負(fù))。若是負(fù)數(shù),則求其補(bǔ)碼即可,具體為“取反加一”或 0x10000 - T (T為度出來(lái)的補(bǔ)碼)。

  把讀出來(lái)的數(shù)temperaturebuffer定義成16位的帶符號(hào)整形,進(jìn)行帶符號(hào)的移位,直接轉(zhuǎn)成浮點(diǎn)數(shù),正負(fù)號(hào)就在里面了,用下面的表達(dá)式,你不用判斷正負(fù)。

 ?。ǎ╢loat)(temperaturebuffer》》4))+((temperaturebuffer&0x0F)/16.0)

  其內(nèi)有兩個(gè)溫度上下限寄存器TH和TL,所采溫度若超過(guò)此溫度范圍后會(huì)置相應(yīng)的報(bào)警標(biāo)志位。至于那個(gè)校驗(yàn),是CRC-8,這并不太復(fù)雜,可以找些相關(guān)資料了解一下便知。

  DS18B20測(cè)負(fù)溫度程序

  //main.c

  #include

  #include

  #include “18B20.h”

  #include“disp.h”

  #define uint unsigned int

  #define uchar unsigned char

  const uchar shu[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,

  0x82,0xF8,0x80,0x90};

  const uchar bshu[3]={0xff,0xf9,0xbf};

  //延時(shí)函數(shù)在4M時(shí)延時(shí)1ms

  void s_1ms(unsigned int ms)

  {

  unsigned int aa;

  for(;ms》=1;ms--)

  {

  for(aa=0;aa《=800;aa++)

  {;}

  }

  }

  void main()

  {

  uint wendu,xiao,ge,shi,bai;

  uchar fh;

  DDRA = 0xff;

  PORTA = 0xff;

  s_1ms(200); //延時(shí)200ms

  ds1820_reset(); //DS18B20復(fù)位

  while (1)

  {

  ds1820_start();

  wendu = ds1820_read_temp(); //讀取溫度數(shù)值

  fh=ds1820_fh();

  if(fh)

  {

  wendu=~(wendu)+1;

  wendu = (wendu * 10)/ 16; //數(shù)值處理

  wendu = wendu % 1000;

  shi= wendu / 100; //顯示第2位

  wendu = wendu % 100;

  ge= wendu / 10; //顯示ge位

  xiao=wendu % 10; // 顯示小數(shù)位

  display(0,shu[xiao]); //小數(shù)位

  display(1,shu[ge]&0x7f); //個(gè)位

  display(2,shu[shi]); //shi

  display(3,bshu[2]); //bai位,0不顯示

  }

  else

  {

  wendu = (wendu * 10) / 16; //數(shù)值處理

  bai = wendu / 1000; //bai位

  wendu = wendu % 1000;

  shi= wendu / 100; //顯示第2位

  wendu = wendu % 100;

  ge= wendu / 10; //顯示ge位

  xiao=wendu % 10; // 顯示小數(shù)位

  display(0,shu[xiao]); //小數(shù)位

  display(1,shu[ge]&0x7f); //個(gè)位

  display(2,shu[shi]); //shi

  display(3,bshu[bai]); //bai位,0不顯示

  }

  }

  }

  //18B20.h

  #define uchar unsigned char

  #define uint unsigned int

  //設(shè)置成輸入

  #define DQ_INPUT DDRC &= ~BIT(7)

  //設(shè)置成輸出

  #define DQ_OUT DDRC |= BIT(7)

  //設(shè)置成低電平

  #define DQ_LO PORTC &= ~BIT(7)

  //設(shè)置成高電平

  #define DQ_HI PORTC |= BIT(7)

  //讀出

  #define DQ_R PINC & BIT(7)

  //中斷標(biāo)志

  uchar init_f;

  //延時(shí)函數(shù)

  void delay_us(uint ms)

  {

  uchar tm;

  while(ms--)

  {

  for(tm=0;tm《2;tm++);

  }

  }

  //DS18B20復(fù)位

  void ds1820_reset(void)

  {

  uchar i;

  //中斷保護(hù)

  init_f = SREG;

  //關(guān)中斷

  CLI();

  DQ_OUT;

  DQ_LO;

  delay_us(80); //延時(shí)500us

  DQ_HI;

  DQ_INPUT;

  delay_us(10); //延時(shí)80us

  i = DQ_R;

  delay_us(80); //延時(shí)500us

  if (init_f & 0x80) //恢復(fù)中斷狀態(tài)

  {

  SEI();

  }

  }

  //DS18B20字節(jié)讀取

  uchar ds1820_read_byte(void)

  {

  uchar i;

  uchar value = 0;

  //中斷保護(hù)

  init_f = SREG;

  //關(guān)中斷

  CLI();

  for (i = 8; i != 0; i--) {

  value 》》= 1;

  DQ_OUT;

  DQ_LO;

  delay_us(2);

  DQ_HI;

  DQ_INPUT;

  if (DQ_R)

  {

  value|=0x80;

  }

  delay_us(10); //延時(shí)60us

  }

  if (init_f&&0x80) //恢復(fù)中斷狀態(tài)

  {

  SEI();

  }

  return(value);

  }

  //DS18B20字節(jié)寫入

  void ds1820_write_byte(unsigned char value)

  {

  uchar i;

  init_f = SREG;

  CLI();

  for (i = 8; i 》 0; i--)

  {

  DQ_OUT;

  DQ_LO;

  if (value & 0x01)

  {

  DQ_HI;

  }

  delay_us(10); //延時(shí)80us

  DQ_HI;

  value 》》= 1;

  }

  if (init_f & 0x80)//恢復(fù)中斷狀態(tài)

  {

  SEI();

  }

  }

  //啟動(dòng)ds1820轉(zhuǎn)換

  void ds1820_start(void)

  {

  ds1820_reset();

  ds1820_write_byte(0xCC); //勿略ROM

  ds1820_write_byte(0x44); //啟動(dòng)轉(zhuǎn)換

  }

  //讀溫度

  uint ds1820_read_temp(void)

  {

  uint i,wendu;

  uchar buf[2];

  ds1820_reset();

  ds1820_write_byte(0xCC); //勿略ROM

  ds1820_write_byte(0xBE); //讀溫度

  for (i = 0; i 《 2; i++)

  {

  buf[i] = ds1820_read_byte();

  }

  wendu = (buf[1]《《8)|buf[0];

  return wendu;

  }

  uint ds1820_fh(void) //讀正負(fù)溫度符號(hào)

  {

  uint i,bb;

  uchar buf[2];

  ds1820_reset();

  ds1820_write_byte(0xCC); //勿略ROM

  ds1820_write_byte(0xBE); //讀溫度

  for (i = 0; i 《 2; i++)

  {

  buf[i] = ds1820_read_byte();

  }

  bb=buf[1]&0xf0;

  return bb;

  }

  //disp.h

  #define uchar unsigned char

  #define uint unsigned int

  #define SHCP_0 PORTA&=~BIT(1)

  #define SHCP_1 PORTA|=BIT(1)

  #define DS_0 PORTA&=~BIT(3)

  #define DS_1 PORTA|=BIT(3)

  #define STCP_0 PORTA&=~BIT(2)

  #define STCP_1 PORTA|=BIT(2)

  void CKin()

  {

  SHCP_0;

  NOP();

  SHCP_1;

  }

  void Dataout() //并行輸出

  {

  STCP_0;

  NOP();

  STCP_1;

  }

  void Datein( uchar date ) //數(shù)據(jù)串行輸入

  {

  uchar i,mod;

  DDRA=0xff;

  for(i=0;i《8;i++)

  {

  mod=date&0x80;

  if(mod==0x80)

  {DS_1;}

  else

  {DS_0;}

  CKin();

  date《《=1;

  }

  Dataout(); //并行輸出

  }

  void weihao(uchar add)

  {

  DDRA=0xff;

  switch(add)

  {

  case 0:PORTA=0x1f;break;

  case 1:PORTA=0x1f|0x80;break;

  case 2:PORTA=0x1f|0x40;break;

  case 3:PORTA=0x1f|0xc0;break;

  case 4:PORTA=0x1f|0x20;break;

  case 5:PORTA=0x1f|0xA0;break;

  case 6:PORTA=0x1f|0x60;break;

  case 7:PORTA=0x1f|0xE0;break;

  default:break;

  }

  }

  void DELAY(uint tt)

  {

  uint mm;

  while(tt--)

  {

  for(mm=30;mm》0;mm--);

  }

  }

  void display(uchar wei,uchar data)

  {

  weihao(wei);

  Datein(data);

  DELAY(20);

  weihao(wei);

  Datein(0xff);

  }

非常好我支持^.^

(16) 94.1%

不好我反對(duì)

(1) 5.9%

( 發(fā)表人:李倩 )

      發(fā)表評(píng)論

      用戶評(píng)論
      評(píng)價(jià):好評(píng)中評(píng)差評(píng)

      發(fā)表評(píng)論,獲取積分! 請(qǐng)遵守相關(guān)規(guī)定!

      ?