|
|
View previous topic :: View next topic |
Author |
Message |
jds-pic
Joined: 17 Sep 2003 Posts: 205
|
dallas onewire primitives library and ds1822 driver code |
Posted: Fri Jun 04, 2004 9:54 am |
|
|
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
|
|
Posted: Sat Jun 12, 2004 7:13 am |
|
|
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
|
|
Posted: Wed Jul 13, 2005 6:34 am |
|
|
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
|
Re: dallas onewire primitives library and ds1822 driver code |
Posted: Wed Jan 11, 2006 2:42 pm |
|
|
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
|
|
|
acidice333
Joined: 14 Oct 2006 Posts: 33
|
|
Posted: Sun Dec 24, 2006 4:25 am |
|
|
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
|
|
|
nuclear__
Joined: 24 Jan 2015 Posts: 63
|
can't make it work |
Posted: Fri Dec 16, 2016 4:07 am |
|
|
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: 63
|
fixed |
Posted: Fri Dec 23, 2016 3:11 pm |
|
|
I removed fixed_io line and now works. |
|
|
|
|
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
|