PIC16F877A drives DS18B20 temperature acquisition chip

Publisher:BlissfulBlissLatest update time:2016-07-07 Source: eefocusKeywords:PIC16F877A Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
Start driving the DS18B20 temperature acquisition chip today!

Information collected from the Internet

Internal structure of DS18B20

    The internal structure of DS18B20 mainly consists of four parts: 64-bit photolithography ROM, temperature sensor, non-volatile temperature alarm triggers TH and TL, and configuration register. The pin arrangement of DS18B20 is as follows:

    

    DQ is the digital signal input/output terminal; GND is the power ground; VDD is the external power supply input terminal (grounded when the parasitic power supply wiring method is used).

    The 64-bit serial number in the photolithography ROM is photolithography-prepared before leaving the factory, and it can be regarded as the address serial code of the DS18B20. The arrangement of the 64-bit photolithography ROM is: the first 8 bits (28H) are the product type label, the next 48 bits are the serial number of the DS18B20 itself, and the last 8 bits are the cyclic redundancy check code of the previous 56 bits (CRC=X8+X5+X4+1). The role of the photolithography ROM is to make each DS18B20 different, so that multiple DS18B20s can be connected to one bus.

    The temperature sensor in the DS18B20 can measure the temperature and provide it in the form of a 12-bit converted to a 16-bit sign-extended binary complement reading, expressed in the form of 0.0625℃/LSB, where S is the sign bit.

 

   This is the 12-bit data obtained after 12-bit conversion, which is stored in two 8-bit RAMs of 18B20. The first 5 bits in binary are sign bits. If the measured temperature is greater than 0, these 5 bits are 0. Just multiply the measured value by 0.0625 to get the actual temperature. If the temperature is less than 0, these 5 bits are 1. The measured value needs to be inverted, added by 1, and then multiplied by 0.0625 to get the actual temperature.

    For example, the digital output of +125℃ is 07D0H, the digital output of +25.0625℃ is 0191H, the digital output of -25.0625℃ is FF6FH, and the digital output of -55℃ is FC90H.

 

DS18B20 temperature sensor memory

     The internal memory of the DS18B20 temperature sensor includes a high-speed scratchpad RAM and a non-volatile electrically erasable E2RAM, which stores high and low temperature triggers TH, TL and configuration registers.

    The temporary memory contains 8 consecutive bytes. The first two bytes are the measured temperature information. The content of the first byte is the lower eight bits of the temperature, and the second byte is the upper eight bits of the temperature. The third and fourth bytes are volatile copies of TH and TL. The fifth byte is a volatile copy of the structure register. The contents of these three bytes are refreshed at each power-on reset. The sixth, seventh, and eighth bytes are used for internal calculations. The ninth byte is a redundant check byte.

 

The meaning of each bit of this byte is as follows: 

TM R1 R0 1 1 1 1 1 

The lower five bits are always 1. TM is the test mode bit, which is used to set whether the DS18B20 is in working mode or test mode. This bit is set to 0 when the DS18B20 leaves the factory. The user should not change it. R1 and R0 are used to set the resolution, as shown in the following table: (DS18B20 is set to 12 bits when it leaves the factory)

Resolution setting table:

 

R1 R0 Resolution Temperature maximum conversion time
0 0 9-digit 93.75ms
0 1 10-bit 187.5ms
1 0 11th place 375ms
1 1 12-bit 750ms

 

    According to the communication protocol of DS18B20, the host must go through three steps to control DS18B20 to complete temperature conversion: reset DS18B20 before each read and write, send a ROM instruction after the reset is successful, and finally send a RAM instruction, so that the DS18B20 can perform the predetermined operation. Reset requires the main CPU to pull down the data line for 500 microseconds and then release it. After receiving the signal, DS18B20 waits for about 16 to 60 microseconds, and then sends a low pulse of 60 to 240 microseconds. The main CPU receives this signal to indicate that the reset is successful.

 

Precautions for using DS1820

  Although DS1820 has the advantages of simple temperature measurement system, high temperature measurement accuracy, convenient connection, and less occupied lines, the following issues should also be noted in practical applications:

  (1) Small hardware costs require relatively complex software to compensate. Since serial data transmission is used between DS1820 and microprocessor, the read and write timing must be strictly guaranteed when programming DS1820, otherwise the temperature measurement results will not be read. When using high-level languages ​​such as PL/M and C for system programming, it is best to use assembly language to implement the DS1820 operation part.

  (2) The relevant information of DS1820 does not mention the number of DS1820s that can be connected to a single bus, which may lead people to mistakenly believe that any number of DS1820s can be connected. This is not the case in actual applications. When more than 8 DS1820s are connected to a single bus, the bus driver problem of the microprocessor needs to be solved. This should be paid attention to when designing a multi-point temperature measurement system.

  (3) The bus cable connecting DS1820 has a length limit. In the experiment, when the transmission length of ordinary signal cable exceeds 50m, the temperature measurement data read will be wrong. When the bus cable is changed to a twisted pair with shielded cable, the normal communication distance can reach 150m. When a twisted pair with shielded cable with more twists per meter is used, the normal communication distance is further extended. This situation is mainly caused by the distortion of the signal waveform caused by the bus distributed capacitance. Therefore, when designing a long-distance temperature measurement system using DS1820, the bus distributed capacitance and impedance matching issues must be fully considered.

  (4) In the design of DS1820 temperature measurement program, after sending the temperature conversion command to DS1820, the program always has to wait for the return signal of DS1820. Once a DS1820 has poor contact or is disconnected, when the program reads the DS1820, there will be no return signal and the program will enter an infinite loop. This point should also be paid attention to when making DS1820 hardware connection and software design.

 

After 1 and a half days of hard work, I finally completed the driver of DS18B20 networking! However, it is only a two-point network, but there should be no technical difficulties in multi-point networking!

Below is the driver

head File

#ifndef DS18B20_H
#define DS18B20_H
#include "main.h"
//define port and port direction registor
#define Dout RD0 
#define DoutDir TRISD0
//define command word
#define ROM_READ 0x33
#define ROM_MATCH 0x55
#define ROM_SKIP 0xCC
#define ROM_SERCH 0xF0 
#define ROM_ALARM 0xEC

#define MEM_WRITE 0x4E
#define MEM_READ 0xBE
#define MEM_COPY 0x48
#define MEM_CONVERT 0x44
#define MEM_RECALL 0xB8
#define POWER_READ 0xB4
//define function 
void configure_ds18b20(uchar flag) ;//configure the accuration of thermometer
uchar init_ds18b20() ;//初始化ds18b20
uchar read_ds18b20() ;//read  a byte  from ds18b20
void write_ds18b20(uchar data) ;//write a byte to ds18b20
void get_sequence(uchar *seq) ;//acquire the rom sequence of ds18b20
char get_configure() ;//acquire the configuration of accuration of thermometer
uint get_temp() ;//capture temperature from ds18b20
float process_temp(uint data) ;//process the  return value of the get_temp function

void start_convert() ;//start thermometer convert
uint read_temp() ;
void match_rom(uchar data[8]) ;
uint test(const uchar *data) ;//read temperature from ds18b20 specified by data
#endif 

Subroutines

#include "ds18b20.h"

const char crc_code[256]={
0,  94, 188,  226,  97,  63,  221,  131,  194,  156,  126,  32,  163,  253,  31,  65,
157,  195,  33,  127,  252,  162,  64,  30,  95,  1,  227,  189,  62,  96,  130,  220,
35,  125,  159,  193,  66,  28,  254,  160,  225,  191,  93,  3,  128,  222,  60,  98,
190,  224,  2,  92,  223,  129,  99,  61,  124,  34,  192,  158,  29,  67,  161,  255,
70,  24,  250,  164,  39,  121,  155,  197,  132,  218,  56,  102,  229,  187,  89,  7,
219,  133, 103,  57,  186,  228,  6,  88,  25,  71,  165,  251,  120,  38,  196,  154,
101,  59, 217,  135,  4,  90,  184,  230,  167,  249,  27,  69,  198,  152,  122,  36,
248,  166, 68,  26,  153,  199,  37,  123,  58,  100,  134,  216,  91,  5,  231,  185,
140,  210, 48,  110,  237,  179,  81,  15,  78,  16,  242,  172,  47,  113,  147,  205,
17,  79,  173,  243,  112,  46,  204,  146,  211,  141,  111,  49,  178,  236,  14,  80,
175,  241, 19,  77,  206,  144,  114,  44,  109,  51,  209,  143,  12,  82,  176,  238,
50,  108,  142,  208,  83,  13,  239,  177,  240,  174,  76,  18,  145,  207,  45,  115,
202,  148, 118,  40,  171,  245,  23,  73,  8,  86,  180,  234,  105,  55,  213, 139,
87,  9,  235,  181,  54,  104,  138,  212,  149,  203,  41,  119,  244,  170,  72,  22,
233,  183,  85,  11,  136,  214,  52,  106,  43,  117,  151,  201,  74,  20,  246,  168,
116,  42,  200,  150,  21,  75,  169,  247,  182,  232,  10,  84,  215,  137,  107,  53
};  
uchar init_ds18b20() 
{
 uchar temp=0 ;
 DoutDir=0 ;
 Dout=1 ;
 DelayUs(1) ;
 Dout=0 ;
 DelayUs(600) ;
 Dout=1 ;
 DoutDir=1 ;
 while(Dout) ;
 while(!Dout) ///这里使用了超时设置
 {
  DelayUs(24)
  if(temp==10)
  {
   if(Dout)
   {
    DoutDir=0 ;
    return 1 ;
   }
   else
   {
    return 0 ;
   }
  }
  temp++ ;
 }
 DoutDir=0 ;
 return 1 ;
}

put read_ds18b20()
{
 put temp,i ;
 temp= 0 ;
 DoutDir = 0 ;
 for ( i = 0 ; i < 8 ; i ++ )
 {
  Doubt = 1 ;
  DelayUs ( 1 ) ;
  temp=temp>>1 ;
  Doubt=0 ;
  DelayUs ( 1 ) ;
  Doubt=1 ;
  DoutDir = 1 ;
  DelayUs ( 8 ) ;
  if ( Doubt )
   temp = temp | 0x80 ;
  DelayUs ( 60 ) ;
  DoutDir = 0 ;
 }
 Doubt = 1 ;
 return temp ;
} }

void write_ds18b20(uchar data)
{
 uchar temp ,i ;
 DoutDir=0 ;
 for(i=0;i<8;i++) 
 {
  temp=data&0x01 ;
  if(temp)
  {
   Dout=0 ;
   DelayUs(2) ;
   Dout=1 ;
   DelayUs(57) ;
  }
  else
  {
   Dout=0 ;
   DelayUs(57) ;
   Dout=1 ;
   DelayUs(2) ;
  }
  data=data>>1 ;
 }
 Dout=1 ;
}

uint get_temp() 
{
 uchar th,tl ;
 uint temp ;
 th=0 ;
 tl=0 ;
 init_ds18b20() ;
 write_ds18b20(ROM_SKIP) ;
 write_ds18b20(MEM_CONVERT) ;
 init_ds18b20() ;
 write_ds18b20(ROM_SKIP) ;
 write_ds18b20(MEM_READ) ;
 tl=read_ds18b20() ;
 th=read_ds18b20() ;
 if(!(th&0xf0))
 {
  th=th&07 ;
  temp=th*256+tl ;
  return temp ;
 } 
 else
 { th=th&0x07 ;
  temp=th*256 +tl ;
  return temp  ;
 }
}

void get_sequence(uchar *seq) 
{
 uchar i ;
 uchar *temp ;
 temp=seq ;
 init_ds18b20() ;
 write_ds18b20(ROM_READ) ;
 for(i=0;i<8;i++) 
 {
  *temp++=read_ds18b20() ;
 }
 return ;
}

char get_configure()
{
 char temp,i ;
 i=0 ;
 init_ds18b20() ;
 write_ds18b20(ROM_SKIP) ;
 write_ds18b20(MEM_READ) ;
 temp=0 ;
 while(++i) 
 {
  temp=read_ds18b20() ;
  if(i==5) 
   return temp ;
 }
}

float process_temp(uint data)
{
 return data*0.0625 ;
}

void configure_ds18b20(uchar flag)
{
 uchar tmp1,tmp2 ;
 init_ds18b20() ;
 write_ds18b20(ROM_SKIP) ;
 write_ds18b20(MEM_READ) ;
 tmp1=read_ds18b20() ;
 tmp2=read_ds18b20() ;
 tmp1=read_ds18b20() ;//get TH
 tmp2=read_ds18b20() ;//get Tl 
 init_ds18b20() ;// reset bus 
 write_ds18b20(ROM_SKIP) ;//skip rom
 write_ds18b20(MEM_WRITE) ;//write command
 write_ds18b20(tmp1) ;//
 write_ds18b20(tmp2) ;//
 switch(flag)
 { 
  case 0 :
   write_ds18b20(0x1F) ;
   break ;
  case 1 :
   write_ds18b20(0x3F) ;
   break ;
  case 2 :
   write_ds18b20(0x5F) ;
   break ; 
  case 3 :
   write_ds18b20(0x7F) ;
   break ;
  default :
   write_ds18b20(0x1F) ;
   break ;
 }
 init_ds18b20() ;//reset bus
 write_ds18b20(ROM_SKIP) ;//skip rom
 write_ds18b20(MEM_COPY) ;//copy ram to eeprom
 write_ds18b20(MEM_RECALL) ;//recopy eeprom to ram
}

uchar crc_check(uchar *data)
{
 uchar temp ,i;
 uchar *p=data ;
//complement ;
 temp=0 ;
 for(i=0;i<7;i++) 
 {
  temp=crc_code[temp^*p] ;
  p++ ;
 }
 if(temp==data[7])
  return 1 ;
 else
  return 0 ;
}

void start_convert() 
{
 init_ds18b20() ;
 write_ds18b20(ROM_SKIP) ;
 write_ds18b20(MEM_CONVERT) ;
}
uint read_temp()
{
 uchar tl,th ;
 uint temp ;
 tl=0 ;
 th=0 ;
// init_ds18b20() ;
// write_ds18b20(0xcc) ;//note that don't skip rom command here ;
 write_ds18b20(MEM_READ) ;
 tl=read_ds18b20() ;
 th=read_ds18b20() ;
 if(!(th&0xf0))
 {
  th=th&07 ;
  temp=th*256+tl ;
  return temp ;
 } 
 else
 { th=th&0x07 ;
  temp=th*256 +tl ;
  return temp  ;
 }
}

void match_rom(uchar data[8])
{
 //uchar *temp=data ;
 uchar i ;
 init_ds18b20() ;
 write_ds18b20(ROM_MATCH) ;
 for(i=0;i<8;i++) 
  write_ds18b20(data[i]) ;
}

uint test(const uchar *data)//Note that the const keyword must be used here
{
 uint temp ;
 uchar t,tl,th;
 tl=0 ;
 th=0 ;
// start_convert() ;
 init_ds18b20() ;
 write_ds18b20(ROM_MATCH) ;
 for(t=0;t<8;t++) 
 {
  write_ds18b20(*data++) ;
 }
 write_ds18b20(MEM_READ) ;
 tl=read_ds18b20() ;
 th=read_ds18b20() ;

 if(!(th&0xf0))
 {
  th=th&07 ;
  temp=th*256+tl ;
  return temp ;
 } 
 else
 { th=th&0x07 ;
  temp=th*256 +tl ;
  return temp  ;
 } 
}

Main Program

#include
#include


#include "main.h"
#include "t232.h"

#include "ds18b20.h"
const uchar rom1[8]={0x28,0x94,0xB8,0x1A,0x02,0x00,0x00,0x6E} ;
const uchar rom2[8]={0x28,0x4B,0xE6,0x1A,0x02,0x00,0x00,0xB9} ;
void init_all() 
{
 asm("clrwdt");   
 init_232() ;
}

void main() 
{
 const char str[]="hello world!" ;
 uchar dat[16],td;
 uint data[2] ;
 init_all() ;
//get ID of DS18b20
// init_ds18b20() ;
// write_ds18b20(0x33) ;
//for(t=0;t<8;t++)
//{
// td=read_ds18b20() ;
// put_char(td) ;
//}

//configure_ds18b20(3) ;//configure the accuration of thermometer
//td=get_configure() ;
//put_char(td) ;

 while(1) 
 {
  start_convert() ;
  data[0]=test(rom1) ;
  data[1]=test(rom2) ;
  DelayMs(70) ;
  sprintf(dat,"temp1 %d temp2 %d",data[0],data[1]) ;
  send_str(dat) ;
 } 
}
Problems that may occur when using DS18B20:

     1. If the temperature value read does not change, it may be a hardware problem. This problem is easy to occur when using parasitic power supply! It is recommended to use an independent power supply, and don't forget to connect a 4.7K pull-up resistor;

     2. The read and write timing of DS18B20 is very important. In fact, to drive DS18B20, you only need to write three functions, an initialization function, a byte read function, and a byte write function. If these two functions are verified, you are halfway to success. The other functions of DS18B20 are all realized by encapsulating these three functions! Just follow the instructions for using the functions!

Keywords:PIC16F877A Reference address:PIC16F877A drives DS18B20 temperature acquisition chip

Previous article:Infrared remote control and decoding of PIC microcontroller
Next article:PIC16F877A AD Learning

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号