fundamental.cz

Elektronika

Digitální teplotní senzor DS18B20 a PIC16F1829

pic_ds18b20_s.jpg, 54kB

Obrázek vytvořen s využitím Fritzing (www.fritzing.org).

DS18B20 je digitální teplotní senzor měřící teplotu v rozsahu -55 °C až +125 °C s přesností ±0.5 °C v intervalu teplot -10 °C až +85 °C. Senzor nabízí kromě prostého odečtení měřené teploty několik dalších možností - obsahuje 64bitový identifikační kód (ve skutečnosti je jedinečných jen 48 bitů, protože 8 bitů připadá na CRC a 8 bitů je "family code" rovný 28H), který umožňuje použití více senzorů na jedné sběrnici. Nabízí volbu rozlišení výstupu v rozmezí 9 až 12 bitů, s čímž souvisí rychlost konverze - 12ti bitový výstup zpracuje za maximálně 750 ms. A nakonec obsahuje funkci alarmu - uživatel zadá 2 krajní hodnoty teploty, v jejichž rozmezí se v daném zařízení vyvolá stav alarmu. Tyto hodnoty můžou být v trvale uloženy v EEPROM, a stejně tak si po odpojení napájení senzor "pamatuje" i nastavení rozlišení.

Zapojení na nepájivém poli:

DS18B20_foto.jpg, 261kB

Odkazy:

Zdrojový kód

Níže uvedený kód slouží k otestování funkčnosti senzoru a je napsaný ve vývojovém prostředí MPLAB X v jazyce C (překladač XC8). Program pracuje s výchozím nastavením rozlišení senzoru - 12 bitů - a s předpokladem, že na sběrnici je pouze jeden senzor DS18B20. Dále - pro zjednodušení - získaný výsledek interpretuje jako kladnou hodnotu teploty. Naměřená teplota ve stupních Celsia se každé 2 sekundy odesílá po seriové lince (9600 Baud, 8 bitů, 1 stop bit).Programování na zakázku C/C++.

#include ‹xc.h›
#define _XTAL_FREQ 16000000

// CONFIG1
#pragma config FOSC = INTOSC
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config MCLRE = OFF
#pragma config CP = OFF
#pragma config CPD = OFF
#pragma config BOREN = ON
#pragma config CLKOUTEN = OFF
#pragma config IESO = OFF
#pragma config FCMEN = OFF

// CONFIG2
#pragma config WRT = OFF
#pragma config PLLEN = OFF
#pragma config STVREN = OFF
//#pragma config BORV = LO
#pragma config LVP = OFF

#include ‹stdio.h›
#include ‹stdlib.h›
#include ‹string.h›

//send string over the serial line
void sendSerialString(char *s)
{
  unsigned char l=strlen(s);
  for (unsigned char i=0;i‹l;i++)
  {
    TXREG=s[i];
    while (!TRMT)
      ;
  }
}

//don't care about negative value
void outputData(unsigned char *data)
{
  //data[0] and data[1] contain the temperatue value
  //data[0] LSB
  //data[1] MSB
  double temp=0.0;
  if (data[0] & 0b00000001)
    temp+=0.0625;
  if (data[0] & 0b00000010)
    temp+=0.125;
  if (data[0] & 0b00000100)
    temp+=0.25;
  if (data[0] & 0b00001000)
    temp+=0.5;
  if (data[0] & 0b00010000)
    temp+=1.0;
  if (data[0] & 0b00100000)
    temp+=2.0;
  if (data[0] & 0b01000000)
    temp+=4.0;
  if (data[0] & 0b10000000)
    temp+=8.0;
  
  if (data[1] & 0b00000001)
    temp+=16.0;
  if (data[1] & 0b00000010)
    temp+=32.0;
  if (data[1] & 0b00000100)
    temp+=64.0;
  
  unsigned char s[20];
  sprintf(s,"\n\nTEMP = %.2f °C",temp);
  sendSerialString(s);
}
  
#define SEARCH_ROM        0xF0
#define READ_ROM          0x33
#define MATCH_ROM         0x55
#define SKIP_ROM          0xCC
#define ALARM_SEARCH      0xEC

#define CONVERT           0x44
#define WRITE_SCRATCHPAD  0x4E
#define READ_SCRATCHPAD   0xBE
#define COPY_SCRATCHPAD   0x48
#define RECALL_EEPROM     0xB8
#define READ_POWER_SUPPLY 0xB4

void initializeDS18B20(void)
{
  TRISCbits.TRISC0=0;
  LATCbits.LATC0=0;
  __delay_us(550);
  TRISCbits.TRISC0=1;
  while (PORTCbits.RC0==1)
  {
    ;
  }
  while (PORTCbits.RC0==0)
  {
    ;
  }
}

void writeBitZero(void)
{
  __delay_us(2);
  TRISCbits.TRISC0=0;
  LATCbits.LATC0=0;
  __delay_us(65);
  TRISCbits.TRISC0=1;
}

void writeBitOne(void)
{
  __delay_us(2);
  TRISCbits.TRISC0=0;
  LATCbits.LATC0=0;
  __delay_us(5);
  TRISCbits.TRISC0=1;
  __delay_us(65);
}

unsigned char readBit(void)
{
  __delay_us(2);
  TRISCbits.TRISC0=0;
  LATCbits.LATC0=0;
  __delay_us(2);
  TRISCbits.TRISC0=1;
  __delay_us(14);
  if (PORTCbits.RC0==0)
  {
    __delay_us(60);
    return 0;
  }
  else
  {
    __delay_us(60);
    return 1;
  }
}

void sendRomCommand(unsigned char command)
{
  for (unsigned char i=0;i‹8;i++)
  {
    if ((command ›› i) & 1)
      writeBitOne();
    else
      writeBitZero();
  }
}

void sendFunctionCommand(unsigned char command)
{
  for (unsigned char i=0;i‹8;i++)
  {
    if ((command ›› i) & 1)
      writeBitOne();
    else
      writeBitZero();
  }
  
  if (command==READ_SCRATCHPAD)
  {
    unsigned char data[9];
    memset(data,0,9);
    
    //there are 9 bytes in the scratchpad
    //read them all though byte 0 & 1 is all we need (skip CRC processing for now)
    for (unsigned char i=0;i‹9;i++)
    {
      for (unsigned char j=0;j‹8;j++)
      {
        if (readBit()==1)
        {
          data[i]|=(1 ‹‹ j);
        }
//        else
//        {
//          data[i]&=(~(1 ‹‹ j));
//        }
      }
    }
    outputData(data);
  }
}

void main(void)
{
  OSCCON = 0b01111000;  //16 MHz clock speed, 250 ns / 1 instruction
  
  //setup USART
  TRISBbits.TRISB5=1;//RX
  ANSELBbits.ANSB5=0;
  TRISBbits.TRISB7=0;//TX
  SPBRG=103;
  TXSTAbits.BRGH=1;
  TXSTAbits.SYNC=0;
  RCSTAbits.SPEN=1;
  TXSTAbits.TXEN=1;
  
  __delay_ms(2000);
  sendSerialString("\nready\n\n");
  __delay_ms(200);
  
  //DS18B20 operation..................................
  //...................................................
  TRISC=0;
  ANSELCbits.ANSC0=0;
  LATC=1;
  __delay_ms(500);
  
  while (1)
  {
    initializeDS18B20();
    sendRomCommand(SKIP_ROM);
    sendFunctionCommand(CONVERT);
    while (readBit()==0)
      ;

    initializeDS18B20();
    sendRomCommand(SKIP_ROM);
    sendFunctionCommand(READ_SCRATCHPAD);
    
    __delay_ms(2000);
  }
  //...................................................
  //DS18B20 operation..................................
}