Interfacing with a Dallas DS1820 1-W Thermometer



/* DS1820_1.C
**
** Illustrates interfacing of the Flashlite V25 with up to eight DS1820's
** on Port P2.
**
** This routine does not use the search ROM feature.  Rather, the Skip
** ROM.  Thus, only a single DS1820 may be configured on each bit of
** Port P2.
**
** This routine performs measurements on P2.0, P2.1, P2.2 and P2.3 and
** displays the nine bytes fetched from each of the DS1820s.  The
** temperature is also displayed.  Note that the extended resolution
** feature of the DS1820 is not used.  Thus, the temperature resolution is
** 0.5 degrees C.
**
** Flashlite               DS1820
**
** P2.X -------------------- DQ
**
** Note that 4.7K pullups to +5 VDC are required on each DQ lead.
**
** copyright, Peter H. Anderson, Baltimore, MD, Sept, '00
*/

#include <stdio.h>
#include <dos.h>

#define SEG 0xf000
#define P2_OFFSET 0xff10
#define PM2_OFFSET 0xff11
#define PMC2_OFFSET 0xff12

typedef unsigned char byte;

void _1w_init(byte sensor);
byte _1w_in_byte(byte sensor);
void _1w_out_byte(byte sensor, byte d);
void _1w_pin_hi(byte sensor);
void _1w_pin_low(byte sensor);
void _1w_strong_pull_up(byte sensor);

byte far *p2, *pm2, *pmc2;    /* note global */

#define MAX_SENSORS 4

void main(void)
{
   byte sensor, n, buff[9];
   float T_C;

   p2 = MK_FP(SEG, P2_OFFSET);
   pm2 = MK_FP(SEG, PM2_OFFSET);
   pmc2 = MK_FP(SEG, PMC2_OFFSET);

   pm2 = 0xff;     /* all of port 2 are inputs */

   while(1)
   {
      for (sensor = 0; sensor < MAX_SENSORS; sensor++)
      {
         _1w_init(sensor);
         _1w_out_byte(sensor, 0xcc);  /* skip ROM */

         _1w_out_byte(sensor, 0x44);  /* perform temperature conversion  */
         _1w_strong_pull_up(sensor);

         _1w_init(sensor);
         _1w_out_byte(sensor, 0xcc);  /* skip ROM */

         _1w_out_byte(sensor, 0xbe);

         for (n=0; n<9; n++)  /* fetch the 9 bytes */
         {
            buff[n]=_1w_in_byte(sensor);
         }

         /* display the result */
         printf("%d\n", sensor);

         for (n=0; n<4; n++)
         {
            printf("%2x  ", buff[n]);
         }

         printf("\n");

         for (n=4; n<9; n++)
         {
           printf("%2x  ", buff[n]);
         }

         printf("\n");

         if (buff[n] & 0x80)  /* its negative */
         {
            buff[n] = ~buff[0] + 1;
            T_C = - ((float) buff[0]) / 2.0;
         }
         else
         {
            T_C = ((float) buff[0]) / 2.0;
         }
         printf("T_C = %.1f\n", T_C);

         delay(500);
      }
   }
}

void _1w_init(byte sensor)
{
   byte n;
   _1w_pin_hi(sensor);  /* be sure DQ is high */
   _1w_pin_low(sensor);

   for (n=166; n>0; n--)   /* 500 us delay */   ;

   _1w_pin_hi(sensor);
   for (n=166; n>0; n--)   /* 500 us delay */   ;
}

byte _1w_in_byte(byte sensor)
{
   byte m, n, i_byte, temp, mask_0, mask_1;
   mask_1 = 0x01<<sensor;
   mask_0 = ~mask_1;
   for (n=0; n<8; n++)
   {
      *p2 = 0x00;
      *pm2 = mask_0;
      *pm2 = 0xff;

      temp = *p2;

      if (temp & mask_1)
      {
         i_byte=(i_byte>>1) | 0x80;  /* least sig bit first  */
      }
      else
      {
        i_byte=i_byte >> 1;
      }
      for(m=19; m>0; m--)  /* 60 us */  ;
   }
   return(i_byte);
}

void _1w_out_byte(byte sensor, byte d)
{
   byte m, n, mask_0, mask_1;
   mask_1 = 0x01<<sensor;
   mask_0 = ~mask_1;
   for(n=0; n<8; n++)
   {
      if (d&0x01)
      {
         *p2 = 0x00;
         *pm2 = mask_0;
         *pm2 = 0xff;
         for(m=19; m>0; m--)  /* 60 us */  ;
      }

      else
      {
         *p2 = 0x00;
         *pm2 = mask_0;
         for(m=19; m>0; m--)  /* 60 us */  ;
         *pm2 = 0xff;
      }
      d=d>>1;
   }
}

void _1w_pin_hi(byte sensor)
{
   *pm2 = 0xff;
}

void _1w_pin_low(byte sensor)
{
   byte mask_0, mask_1;
   mask_1 = 0x01 << sensor;
   mask_0 = ~mask_1;
   *p2 = mask_0;
   *pm2 = mask_0;
}

void _1w_strong_pull_up(byte sensor)
{
   byte mask_0, mask_1;
   mask_1 = 0x01 << sensor;
   mask_0 = ~mask_1;
   *p2 = mask_1;     /* bring bit to a hard logic one */
   *pm2 = mask_0;    /* dirs configured as output */
   delay(500);
   *pm2 = 0xff;
}