CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug Reports on this forum. Send them to support@ccsinfo.com

dallas onewire primitives library and ds1822 driver code

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
jds-pic



Joined: 17 Sep 2003
Posts: 205

View user's profile Send private message

dallas onewire primitives library and ds1822 driver code
PostPosted: Fri Jun 04, 2004 9:54 am     Reply with quote

http://losdos.dyndns.org:8080/public/onewire/lib-onewire.html

Code:

// onewire library, for dallas onewire devices
// currently includes:
//   - generic onewire functions (init, readbyte, sendbyte, crc, etc.)
//   - ds1822 dallas-semi econo-thermometer

// (C) copyright 2003 j.d.sandoz / jds-pic !at! losdos.dyndns.org

// released under the GNU GENERAL PUBLIC LICENSE (GPL)
// refer to http://www.gnu.org/licenses/gpl.txt

// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA


// ds1822 scratchpad registers
#define DS1822_SP_TLSB  0
#define DS1822_SP_TMSB  1
#define DS1822_SP_HLIM  2
#define DS1822_SP_LLIM  3
#define DS1822_SP_CFG   4
#define DS1822_SP_RES0  5
#define DS1822_SP_RES1  6
#define DS1822_SP_RES2  7
#define DS1822_SP_CRC   8

// ds1822 rom registers
#define DS1822_ROM_DEVTYPE  0
#define DS1822_ROM_SERIAL1  1
#define DS1822_ROM_SERIAL2  2
#define DS1822_ROM_SERIAL3  3
#define DS1822_ROM_SERIAL4  4
#define DS1822_ROM_SERIAL5  5
#define DS1822_ROM_SERIAL6  6
#define DS1822_ROM_CRC      7

// ds1822 command set
#define DS1822_CMD_READROM           0x33
#define DS1822_CMD_SKIPROM           0xCC
#define DS1822_CMD_CONVERTTEMP       0x44
#define DS1822_CMD_WRITESCRATCHPAD   0x4E
#define DS1822_CMD_READSCRATCHPAD    0xBE
#define DS1822_CMD_COPYSCRATCHPAD    0x48


// note that not all applications need to disable interrupts when
// performing onewire transactions.  but, if unmasked interrupts
// cause onewire timing violations, returned data will be suspect
// or there may be other, hard-to-reproduce problems.

void onewire_disable_interrupts(int disable) {
   if (disable)
     disable_interrupts(GLOBAL);
   else
     enable_interrupts(GLOBAL);
}


short int onewire_init_with_error_check() {
   onewire_disable_interrupts(TRUE);
   output_low(ONE_WIRE_PIN);
   delay_us( 500 ); // pull 1-wire low for reset pulse
   output_float(ONE_WIRE_PIN); // float 1-wire high
   delay_us( 5 );   // allow pin to stabilize
   if (!input(ONE_WIRE_PIN)) {
      onewire_disable_interrupts(FALSE);
      return ( FALSE ); // error (1-wire leads shorted)
      }
   delay_us( 80 ); // wait for presence pulse, allowing for device variation
   if (input(ONE_WIRE_PIN)) {
      onewire_disable_interrupts(FALSE);
      return ( FALSE ); // error (no 1-wire devices present)
      }
   delay_us( 420 ); // wait-out remaining initialisation window.
   output_float(ONE_WIRE_PIN);
   //printf(debug_putc,"<>ok >onewire_init\n\r");
   onewire_disable_interrupts(FALSE);
   return ( TRUE ); // device(s) present and initialised.
}


void onewire_init() { // OK if just using a single permanently connected device
   onewire_disable_interrupts(TRUE);
   output_low(ONE_WIRE_PIN);
   delay_us( 500 ); // pull 1-wire low for reset pulse
   output_float(ONE_WIRE_PIN); // float 1-wire high
   delay_us( 80 ); // wait for presence pulse, allowing for device variation
   delay_us( 420 ); // wait-out remaining initialisation window.
   output_float(ONE_WIRE_PIN);
   onewire_disable_interrupts(FALSE);
}


void onewire_sendbyte(int data) {
   int count;
   //static int debugS;
   //printf(debug_putc,"0x%x >onewire_sendbyte(%u)\n\r",data,debugS++);
   onewire_disable_interrupts(TRUE);
   for (count=0; count<8; ++count) {
      output_low(ONE_WIRE_PIN);
      delay_us( 2 ); // pull 1-wire low to initiate write time-slot.
      output_bit(ONE_WIRE_PIN, shift_right(&data,1,0)); // set output bit on 1-wire
      delay_us( 60 ); // wait until end of write slot.
      output_float(ONE_WIRE_PIN); // set 1-wire high again,
      delay_us( 2 ); // for more than 1us minimum.
      }
   onewire_disable_interrupts(FALSE);
}


int onewire_readbyte() {
   int count, data;
   //static int debugR;
   onewire_disable_interrupts(TRUE);
   for (count=0; count<8; ++count) {
      output_low(ONE_WIRE_PIN);
      delay_us( 2 ); // pull 1-wire low to initiate read time-slot.
      output_float(ONE_WIRE_PIN); // now let 1-wire float high,
      delay_us( 8 ); // let device state stabilise,
      shift_right(&data,1,input(ONE_WIRE_PIN)); // and load result.
      delay_us( 120 ); // wait until end of read slot.
      }
   //printf(debug_putc,"0x%x >onewire_readbyte(%u)\n\r",data,debugR++);
   onewire_disable_interrupts(FALSE);
   return( data );
}


int onewire_ds1822_read_scratchpad(int field) { /* returns config bitfield */
   int data[9];

   onewire_init();
   onewire_sendbyte(DS1822_CMD_SKIPROM);
   onewire_sendbyte(DS1822_CMD_READSCRATCHPAD);

   data[DS1822_SP_TLSB]=onewire_readbyte();    // 0 Tlsb
   data[DS1822_SP_TMSB]=onewire_readbyte();    // 1 Tmsb
   data[DS1822_SP_HLIM]=onewire_readbyte();    // 2 Thlim
   data[DS1822_SP_LLIM]=onewire_readbyte();    // 3 Tllim
   data[DS1822_SP_CFG]=onewire_readbyte();     // 4 Config
   data[DS1822_SP_RES0]=onewire_readbyte();    // 5 RES0
   data[DS1822_SP_RES1]=onewire_readbyte();    // 6 RES1
   data[DS1822_SP_RES2]=onewire_readbyte();    // 7 RES2
   data[DS1822_SP_CRC]=onewire_readbyte();     // 8 CRC

   if (field > 8) {
      //printf(debug_putc,"ERR! >scratchpad field 0x%x out of range (ds1822)\n\r",field);
      return(0);
      }
   else {
      //printf(debug_putc,"0x%x >scratchpad field 0x%x (ds1822)\n\r",data[field],field);
      return(data[field]);
      }
}


int onewire_ds1822_read_rom(int field) { /* rtns ROM info, one byte at a time */
   int data[8];

   if (!onewire_init_with_error_check())
     return (0);
   onewire_sendbyte(DS1822_CMD_READROM);

   data[DS1822_ROM_DEVTYPE]=onewire_readbyte();   // 0 family code
   data[DS1822_ROM_SERIAL1]=onewire_readbyte();   // 1 serial number LSB
   data[DS1822_ROM_SERIAL2]=onewire_readbyte();   // 2 serial number
   data[DS1822_ROM_SERIAL3]=onewire_readbyte();   // 3 serial number
   data[DS1822_ROM_SERIAL4]=onewire_readbyte();   // 4 serial number
   data[DS1822_ROM_SERIAL5]=onewire_readbyte();   // 5 serial number
   data[DS1822_ROM_SERIAL6]=onewire_readbyte();   // 6 serial number MSB
   data[DS1822_ROM_CRC]=onewire_readbyte();       // 7 CRC

   if (field > 7) {
      //printf(debug_putc,"ERR! >rom field 0x%x out of range (ds1822)\n\r",field);
      return(0);
      }
   else {
      //printf(debug_putc,"0x%x >rom field 0x%x (ds1822)\n\r",data[field],field);
      return(data[field]);
      }
}


int onewire_crc(int oldcrc, int newbyte) {
   // see http://pdfserv.maxim-ic.com/arpdf/AppNotes/app27.pdf
   int shift_reg, data_bit, sr_lsb, fb_bit, j;

   shift_reg=oldcrc;
   for(j=0; j<8; j++) {   // for each bit
      data_bit = (newbyte >> j) & 0x01;
      sr_lsb = shift_reg & 0x01;
      fb_bit = (data_bit ^ sr_lsb) & 0x01;
      shift_reg = shift_reg >> 1;
      if (fb_bit)
         shift_reg = shift_reg ^ 0x8c;
      }
   return(shift_reg);
}


int onewire_ds1822_set_temperature_resolution(int resolution) { /* set up for nbit resolution */
   int resolution_cfgfield;

   if ((resolution < 9) || (resolution > 12))
      resolution=9;

   resolution_cfgfield=((resolution-9)<<5);  // see DS1822 datasheet page 7

   if (!onewire_init_with_error_check())
     return (0);
   onewire_sendbyte(DS1822_CMD_SKIPROM);
   onewire_sendbyte(DS1822_CMD_WRITESCRATCHPAD);

   onewire_sendbyte(0b01111101);   // set max TH threshold (125'C)
   onewire_sendbyte(0b11001001);   // set min TL threshold (-55'C)
   onewire_sendbyte(resolution_cfgfield);    // Temp resolution, set to nbit

   onewire_init(); // reset
   onewire_sendbyte(DS1822_CMD_SKIPROM);
   onewire_sendbyte(DS1822_CMD_COPYSCRATCHPAD);
   delay_ms(15); // allow time for flash memory write.

   return( (onewire_ds1822_read_scratchpad(DS1822_SP_CFG) & 0b01100000)>>5 );
}


int onewire_ds1822_read_temp_c_lite() { /* 0 to 125'C byte rtnd, nonparasitic mode */
   int temperatureLSB, temperatureMSB, config, delaymult;

   config=((onewire_ds1822_read_scratchpad(DS1822_SP_CFG) & 0b01100000)>>5);
      // each addn'l resolution bit needs twice the base conversion time!
   if (!onewire_init_with_error_check())
     return (0);
   onewire_sendbyte(DS1822_CMD_SKIPROM);
   onewire_sendbyte(DS1822_CMD_CONVERTTEMP);

   delaymult=(1<<config);
      //printf(debug_putc,"0x%x >delay_mult (ds1822)\n\r",delaymult);

   while (delaymult--)
      delay_ms(100); // allow worst case time for temp. conversion.

   temperatureLSB = onewire_ds1822_read_scratchpad(DS1822_SP_TLSB);
   temperatureMSB = onewire_ds1822_read_scratchpad(DS1822_SP_TMSB);

   if (temperatureMSB & 0b11111000) // if temp is negative rtn 0
      return(0);
   else {                           // else rtn the positive temp
      temperatureLSB=((temperatureLSB & 0b11110000)>>4);
      temperatureMSB=((temperatureMSB & 0b00000111)<<4);
      }
   return(temperatureMSB | temperatureLSB);  // OR msb&lsb
}


Last edited by jds-pic on Sun Jan 23, 2011 5:47 pm; edited 1 time in total
jds-pic



Joined: 17 Sep 2003
Posts: 205

View user's profile Send private message

PostPosted: Sat Jun 12, 2004 7:13 am     Reply with quote

someone asked me for example code...

for temperature measurements WITH A SINGLE PERMANENTLY ATTACHED DS1822 onewire device...
in your main() or other calling function:
Code:

int temperature;

if (int onewire_init_with_error_check()) {
  // set the number of bits of resolution on the ds1822.
  // note that this affects the conversion time,
  // RTFM and see the called function.
  onewire_ds1822_set_temperature_resolution(9);

  // read the temperature from the ds1822.
  // note that the returned value is in deg C,
  // and the "lite" function returns only positive temps.
  temperature = onewire_ds1822_read_temp_c_lite();
  }
else
  printf("onewire device not found");



here's a little snippet that shows how to get the 48bit unique serial number from the DS1822...
Code:

printf(lcd_putc,"Widget / Ver%04Lx", (int16)FW_VERSION);
printf(lcd_putc,"Ser ");
if (onewire_init_with_error_check()) {
  for (loop=6; loop>=1; loop--)
  printf(lcd_putc,"%x",onewire_ds1822_read_rom(loop));
}


and then another snippet that shows how to retrieve the burned in CRC and compute same from the ROM data...
Code:

crc=0;
if (onewire_init_with_error_check()) {
  for (loop=0;loop<7;loop++)  // crc check to see if we are reading onewire net correctly
    crc=onewire_crc(crc,onewire_ds1822_read_rom(loop));
  printf(serial_putc,"\r\nchk: 0x%x/",onewire_ds1822_read_rom(DS1822_ROM_DEVTYPE));  // 1st ROM byte = device type
  printf(serial_putc,"0x%x/0x%x\r\n",onewire_ds1822_read_rom(DS1822_ROM_CRC),crc);
}
glavic



Joined: 13 Jul 2005
Posts: 7

View user's profile Send private message Send e-mail

PostPosted: Wed Jul 13, 2005 6:34 am     Reply with quote

function onewire_readbyte()
Code:
int onewire_readbyte() {
   int count, data;
   //static int debugR;
   onewire_disable_interrupts(TRUE);
   for (count=0; count<8; ++count) {
      output_low(ONE_WIRE_PIN);
      delay_us( 2 ); // pull 1-wire low to initiate read time-slot.
      output_float(ONE_WIRE_PIN); // now let 1-wire float high,
      delay_us( 8 ); // let device state stabilise,
      shift_right(&data,1,input(ONE_WIRE_PIN)); // and load result.
      delay_us( 120 ); // wait until end of read slot.
      }
   //printf(debug_putc,"0x%x >onewire_readbyte(%u)\n\r",data,debugR++);
   onewire_disable_interrupts(FALSE);
   return( data );
}
Why is there 120us delay in readybyte function ?
The read-time slots is minimum 60us + minimum 1us recovery time between slots, so 80us is enough. I am using 66us read-time slots. You should take samples between 15us and 30us. I am getting sample in 18us.

edited >
Code:
int onewire_read_byte ()
{
   int count, data;

   onewire_disable_interrupts(TRUE);

   for (count=0; count < 8; ++count)
   {
      output_low(ONE_WIRE_PIN);
      delay_us(2);
      output_float(ONE_WIRE_PIN);
      delay_us(18);
      shift_right(&data, 1, input(ONE_WIRE_PIN));
      delay_us(44);
   }

   onewire_disable_interrupts(FALSE);
   return(data);
}





function onewire_ds1822_read_temp_c_lite()
Code:
.
.
.
   temperatureLSB = onewire_ds1822_read_scratchpad(DS1822_SP_TLSB);
   temperatureMSB = onewire_ds1822_read_scratchpad(DS1822_SP_TMSB);
.
.
Here you read the scratchpad twice. Why?

edited >
Code:
void onewire_ds1822_read_scratchpad(int *data)
{
   onewire_init();
   onewire_sendbyte(DS1822_CMD_SKIPROM);
   onewire_sendbyte(DS1822_CMD_READSCRATCHPAD);

   data[DS1822_SP_TLSB]=onewire_readbyte();    // 0 Tlsb
   data[DS1822_SP_TMSB]=onewire_readbyte();    // 1 Tmsb
   data[DS1822_SP_HLIM]=onewire_readbyte();    // 2 Thlim
   data[DS1822_SP_LLIM]=onewire_readbyte();    // 3 Tllim
   data[DS1822_SP_CFG]=onewire_readbyte();     // 4 Config
   data[DS1822_SP_RES0]=onewire_readbyte();    // 5 RES0
   data[DS1822_SP_RES1]=onewire_readbyte();    // 6 RES1
   data[DS1822_SP_RES2]=onewire_readbyte();    // 7 RES2
   data[DS1822_SP_CRC]=onewire_readbyte();     // 8 CRC
}


so now you can call this function once and you will get all the scratchpad registers in array >>
Code:
int onewire_ds1822_read_temp_c_lite() { /* 0 to 125'C byte rtnd, nonparasitic mode */
   int temperatureLSB, temperatureMSB, config, delaymult, scratchpad[9];
.
.
.
   onewire_ds1822_read_scratchpad(scratchpad);

   temperatureLSB = scratchpad[0];
   temperatureMSB = scratchpad[1];
.
.
.
}
jds-pic



Joined: 17 Sep 2003
Posts: 205

View user's profile Send private message

Re: dallas onewire primitives library and ds1822 driver code
PostPosted: Wed Jan 11, 2006 2:42 pm     Reply with quote

Code:

int onewire_ds1822_read_temp_c_lite() { /* 0 to 125'C byte rtnd, nonparasitic mode */
   int temperatureLSB, temperatureMSB, config, delaymult;
<...snip...>
   if (temperatureMSB & 0b11111000) // if temp is negative rtn 0
      return(0);
   else {                           // else rtn the positive temp
      temperatureLSB=((temperatureLSB & 0b11110000)>>4);
      temperatureMSB=((temperatureMSB & 0b00000111)<<4);
      }
   return(temperatureMSB | temperatureLSB);  // OR msb&lsb
}


for dealing with negative temperatures, see this thread:
http://www.ccsinfo.com/forum/viewtopic.php?t=25630

jds-pic
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Mar 08, 2006 8:12 am     Reply with quote

A more efficient implementation of the CRC calculation can be found in http://www.ccsinfo.com/forum/viewtopic.php?p=60194
acidice333



Joined: 14 Oct 2006
Posts: 33

View user's profile Send private message

PostPosted: Sun Dec 24, 2006 4:25 am     Reply with quote

Now I know this is for just a single, but does anybody have a modified code for multiple?
jds-pic



Joined: 17 Sep 2003
Posts: 205

View user's profile Send private message

PostPosted: Sun Dec 24, 2006 9:11 am     Reply with quote

acidice333 wrote:
Now I know this is for just a single, but does anybody have a modified code for multiple?


you need to use the "Search ROM" technique to find all of the devices on the onewire net; see for example,
http://www.ccsinfo.com/forum/viewtopic.php?t=21848
http://www.ccsinfo.com/forum/viewtopic.php?t=19255
etc

jds-pic
nuclear__



Joined: 24 Jan 2015
Posts: 33

View user's profile Send private message

can't make it work
PostPosted: Fri Dec 16, 2016 4:07 am     Reply with quote

Hi there. Using 16f684 and pin_c2 with internal 8MHz osc, i try to make it work. I don't have lcd on it, it's a very simple circuit. Generally working. I have 3 leds for debugging.
Anyway i can't get temperature reading. I can see that i get no pulses to pin_c2 (with oscilloscope). When i use #use FIXED_IO( C_outputs=PIN_C2) then i do see pulses coming periodically, however it's still not reading anything but 0.
Running this at main once, i can see ledr going low:
Code:

if (onewire_init_with_error_check()) {
  onewire_ds1822_set_temperature_resolution(9);
  }
  else {
   output_low(ledr);
   delay_ms(2000);
  }

Probably something is wrong with my configuration.
Nothing changes if i remove ds1822.
Any tip?
Code:

#include <16F684.h>
#device ADC=8

#FUSES WDT                      //Watch Dog Timer
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOMCLR                   //Master Clear pin used for I/O
#FUSES PROTECT                  //Code protected from reads
#FUSES NOCPD                    //No EE protection
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES FCMEN                    //Fail-safe clock monitor enabled

#use delay(internal=8000000,restart_wdt)
#use FIXED_IO( C_outputs=PIN_C5,PIN_C4,PIN_C3,PIN_C0 )

#include <ds1822.c>
 
#define pot   PIN_A2
#define s_season   PIN_A4
#define s_mode     PIN_A5
#define Relay   PIN_C0
#define ledR   PIN_C3
#define ledG   PIN_C4
#define ledB   PIN_C5
nuclear__



Joined: 24 Jan 2015
Posts: 33

View user's profile Send private message

fixed
PostPosted: Fri Dec 23, 2016 3:11 pm     Reply with quote

I removed fixed_io line and now works.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group