comparison ds18x20.c @ 9:7da9a3f23592

Import ds18x20 code
author Matt Johnston <matt@ucc.asn.au>
date Fri, 18 May 2012 23:57:08 +0800
parents
children
comparison
equal deleted inserted replaced
8:c55321727d02 9:7da9a3f23592
1 /*********************************************************************************
2 Title: DS18X20-Functions via One-Wire-Bus
3 Author: Martin Thomas <[email protected]>
4 http://www.siwawi.arubi.uni-kl.de/avr-projects
5 Software: avr-gcc 4.3.3 / avr-libc 1.6.7 (WinAVR 3/2010)
6 Hardware: any AVR - tested with ATmega16/ATmega32/ATmega324P and 3 DS18B20
7
8 Partly based on code from Peter Dannegger and others.
9
10 changelog:
11 20041124 - Extended measurements for DS18(S)20 contributed by Carsten Foss (CFO)
12 200502xx - function DS18X20_read_meas_single
13 20050310 - DS18x20 EEPROM functions (can be disabled to save flash-memory)
14 (DS18X20_EEPROMSUPPORT in ds18x20.h)
15 20100625 - removed inner returns, added static function for read scratchpad
16 . replaced full-celcius and fractbit method with decicelsius
17 and maxres (degreeCelsius*10e-4) functions, renamed eeprom-functions,
18 delay in recall_e2 replaced by timeout-handling
19 20100714 - ow_command_skip_last_recovery used for parasite-powerd devices so the
20 strong pull-up can be enabled in time even with longer OW recovery times
21 20110209 - fix in DS18X20_format_from_maxres() by Marian Kulesza
22 **********************************************************************************/
23
24 #include <stdlib.h>
25 #include <stdint.h>
26
27 #include <avr/io.h>
28 #include <avr/pgmspace.h>
29
30 #include "ds18x20.h"
31 #include "onewire.h"
32 #include "crc8.h"
33
34 #if DS18X20_EEPROMSUPPORT
35 // for 10ms delay in copy scratchpad
36 #include <util/delay.h>
37 #endif /* DS18X20_EEPROMSUPPORT */
38
39 /*----------- start of "debug-functions" ---------------*/
40
41 #if DS18X20_VERBOSE
42 #if (!DS18X20_DECICELSIUS)
43 #error "DS18X20_DECICELSIUS must be enabled for verbose-mode"
44 #endif
45
46 /* functions for debugging-output - undef DS18X20_VERBOSE in .h
47 if you run out of program-memory */
48 #include <string.h>
49 #include "uart.h"
50 #include "uart_addon.h"
51
52 static int16_t DS18X20_raw_to_decicelsius( uint8_t fc, uint8_t sp[] );
53
54 void DS18X20_show_id_uart( uint8_t *id, size_t n )
55 {
56 size_t i;
57
58 for( i = 0; i < n; i++ ) {
59 if ( i == 0 ) { uart_puts_P( "FC:" ); }
60 else if ( i == n-1 ) { uart_puts_P( "CRC:" ); }
61 if ( i == 1 ) { uart_puts_P( "SN: " ); }
62 uart_puthex_byte(id[i]);
63 uart_puts_P(" ");
64 if ( i == 0 ) {
65 if ( id[0] == DS18S20_FAMILY_CODE ) { uart_puts_P ("(18S)"); }
66 else if ( id[0] == DS18B20_FAMILY_CODE ) { uart_puts_P ("(18B)"); }
67 else if ( id[0] == DS1822_FAMILY_CODE ) { uart_puts_P ("(22)"); }
68 else { uart_puts_P ("( ? )"); }
69 }
70 }
71 if ( crc8( id, OW_ROMCODE_SIZE) )
72 uart_puts_P( " CRC FAIL " );
73 else
74 uart_puts_P( " CRC O.K. " );
75 }
76
77 static void show_sp_uart( uint8_t *sp, size_t n )
78 {
79 size_t i;
80
81 uart_puts_P( "SP:" );
82 for( i = 0; i < n; i++ ) {
83 if ( i == n-1 ) { uart_puts_P( "CRC:" ); }
84 uart_puthex_byte(sp[i]);
85 uart_puts_P(" ");
86 }
87 }
88
89 /*
90 convert raw value from DS18x20 to Celsius
91 input is:
92 - familycode fc (0x10/0x28 see header)
93 - scratchpad-buffer
94 output is:
95 - cel full celsius
96 - fractions of celsius in millicelsius*(10^-1)/625 (the 4 LS-Bits)
97 - subzero =0 positiv / 1 negativ
98 always returns DS18X20_OK
99 */
100 static uint8_t DS18X20_meas_to_cel( uint8_t fc, uint8_t *sp,
101 uint8_t* subzero, uint8_t* cel, uint8_t* cel_frac_bits)
102 {
103 uint16_t meas;
104 uint8_t i;
105
106 meas = sp[0]; // LSB
107 meas |= ( (uint16_t)sp[1] ) << 8; // MSB
108
109 // only work on 12bit-base
110 if( fc == DS18S20_FAMILY_CODE ) { // 9 -> 12 bit if 18S20
111 /* Extended res. measurements for DS18S20 contributed by Carsten Foss */
112 meas &= (uint16_t) 0xfffe; // Discard LSB, needed for later extended precicion calc
113 meas <<= 3; // Convert to 12-bit, now degrees are in 1/16 degrees units
114 meas += ( 16 - sp[6] ) - 4; // Add the compensation and remember to subtract 0.25 degree (4/16)
115 }
116
117 // check for negative
118 if ( meas & 0x8000 ) {
119 *subzero=1; // mark negative
120 meas ^= 0xffff; // convert to positive => (twos complement)++
121 meas++;
122 }
123 else {
124 *subzero=0;
125 }
126
127 // clear undefined bits for B != 12bit
128 if ( fc == DS18B20_FAMILY_CODE || fc == DS1822_FAMILY_CODE ) {
129 i = sp[DS18B20_CONF_REG];
130 if ( (i & DS18B20_12_BIT) == DS18B20_12_BIT ) { ; }
131 else if ( (i & DS18B20_11_BIT) == DS18B20_11_BIT ) {
132 meas &= ~(DS18B20_11_BIT_UNDF);
133 } else if ( (i & DS18B20_10_BIT) == DS18B20_10_BIT ) {
134 meas &= ~(DS18B20_10_BIT_UNDF);
135 } else { // if ( (i & DS18B20_9_BIT) == DS18B20_9_BIT ) {
136 meas &= ~(DS18B20_9_BIT_UNDF);
137 }
138 }
139
140 *cel = (uint8_t)(meas >> 4);
141 *cel_frac_bits = (uint8_t)(meas & 0x000F);
142
143 return DS18X20_OK;
144 }
145
146 static void DS18X20_uart_put_temp(const uint8_t subzero,
147 const uint8_t cel, const uint8_t cel_frac_bits)
148 {
149 char buffer[sizeof(int)*8+1];
150 size_t i;
151
152 uart_putc((subzero)?'-':'+');
153 uart_put_int((int)cel);
154 uart_puts_P(".");
155 itoa(cel_frac_bits*DS18X20_FRACCONV,buffer,10);
156 for ( i = 0; i < 4-strlen(buffer); i++ ) {
157 uart_puts_P("0");
158 }
159 uart_puts(buffer);
160 uart_puts_P("�C");
161 }
162
163 /* verbose output rom-search follows read-scratchpad in one loop */
164 uint8_t DS18X20_read_meas_all_verbose( void )
165 {
166 uint8_t id[OW_ROMCODE_SIZE], sp[DS18X20_SP_SIZE], diff;
167 uint8_t i;
168 uint16_t meas;
169 int16_t decicelsius;
170 char s[10];
171 uint8_t subzero, cel, cel_frac_bits;
172
173 for( diff = OW_SEARCH_FIRST; diff != OW_LAST_DEVICE; )
174 {
175 diff = ow_rom_search( diff, &id[0] );
176
177 if( diff == OW_PRESENCE_ERR ) {
178 uart_puts_P( "No Sensor found\r" );
179 return OW_PRESENCE_ERR; // <--- early exit!
180 }
181
182 if( diff == OW_DATA_ERR ) {
183 uart_puts_P( "Bus Error\r" );
184 return OW_DATA_ERR; // <--- early exit!
185 }
186
187 DS18X20_show_id_uart( id, OW_ROMCODE_SIZE );
188
189 if( id[0] == DS18B20_FAMILY_CODE || id[0] == DS18S20_FAMILY_CODE ||
190 id[0] == DS1822_FAMILY_CODE ) {
191 // temperature sensor
192
193 uart_putc ('\r');
194
195 ow_byte_wr( DS18X20_READ ); // read command
196
197 for ( i=0 ; i< DS18X20_SP_SIZE; i++ ) {
198 sp[i]=ow_byte_rd();
199 }
200
201 show_sp_uart( sp, DS18X20_SP_SIZE );
202
203 if ( crc8( &sp[0], DS18X20_SP_SIZE ) ) {
204 uart_puts_P( " CRC FAIL " );
205 } else {
206 uart_puts_P( " CRC O.K. " );
207 }
208 uart_putc ('\r');
209
210 meas = sp[0]; // LSB Temp. from Scrachpad-Data
211 meas |= (uint16_t) (sp[1] << 8); // MSB
212
213 uart_puts_P( " T_raw=");
214 uart_puthex_byte( (uint8_t)(meas >> 8) );
215 uart_puthex_byte( (uint8_t)meas );
216 uart_puts_P( " " );
217
218 if( id[0] == DS18S20_FAMILY_CODE ) { // 18S20
219 uart_puts_P( "S20/09" );
220 }
221 else if ( id[0] == DS18B20_FAMILY_CODE ||
222 id[0] == DS1822_FAMILY_CODE ) { // 18B20 or 1822
223 i=sp[DS18B20_CONF_REG];
224 if ( (i & DS18B20_12_BIT) == DS18B20_12_BIT ) {
225 uart_puts_P( "B20/12" );
226 }
227 else if ( (i & DS18B20_11_BIT) == DS18B20_11_BIT ) {
228 uart_puts_P( "B20/11" );
229 }
230 else if ( (i & DS18B20_10_BIT) == DS18B20_10_BIT ) {
231 uart_puts_P( " B20/10 " );
232 }
233 else { // if ( (i & DS18B20_9_BIT) == DS18B20_9_BIT ) {
234 uart_puts_P( "B20/09" );
235 }
236 }
237 uart_puts_P(" ");
238
239 DS18X20_meas_to_cel( id[0], sp, &subzero, &cel, &cel_frac_bits );
240 DS18X20_uart_put_temp( subzero, cel, cel_frac_bits );
241
242 decicelsius = DS18X20_raw_to_decicelsius( id[0], sp );
243 if ( decicelsius == DS18X20_INVALID_DECICELSIUS ) {
244 uart_puts_P("* INVALID *");
245 } else {
246 uart_puts_P(" conv: ");
247 uart_put_int(decicelsius);
248 uart_puts_P(" deci�C ");
249 DS18X20_format_from_decicelsius( decicelsius, s, 10 );
250 uart_puts_P(" fmt: ");
251 uart_puts(s);
252 uart_puts_P(" �C ");
253 }
254
255 uart_puts("\r");
256
257 } // if meas-sensor
258
259 } // loop all sensors
260
261 uart_puts_P( "\r" );
262
263 return DS18X20_OK;
264 }
265
266 #endif /* DS18X20_VERBOSE */
267
268 #if DS18X20_VERBOSE
269 #define uart_puts_P_verbose(s__) uart_puts_P(s__)
270 #else
271 #define uart_puts_P_verbose(s__)
272 #endif
273
274
275 /*----------- end of "debug-functions" ---------------*/
276
277
278 /* find DS18X20 Sensors on 1-Wire-Bus
279 input/ouput: diff is the result of the last rom-search
280 *diff = OW_SEARCH_FIRST for first call
281 output: id is the rom-code of the sensor found */
282 uint8_t DS18X20_find_sensor( uint8_t *diff, uint8_t id[] )
283 {
284 uint8_t go;
285 uint8_t ret;
286
287 ret = DS18X20_OK;
288 go = 1;
289 do {
290 *diff = ow_rom_search( *diff, &id[0] );
291 if ( *diff == OW_PRESENCE_ERR || *diff == OW_DATA_ERR ||
292 *diff == OW_LAST_DEVICE ) {
293 go = 0;
294 ret = DS18X20_ERROR;
295 } else {
296 if ( id[0] == DS18B20_FAMILY_CODE || id[0] == DS18S20_FAMILY_CODE ||
297 id[0] == DS1822_FAMILY_CODE ) {
298 go = 0;
299 }
300 }
301 } while (go);
302
303 return ret;
304 }
305
306 /* get power status of DS18x20
307 input: id = rom_code
308 returns: DS18X20_POWER_EXTERN or DS18X20_POWER_PARASITE */
309 uint8_t DS18X20_get_power_status( uint8_t id[] )
310 {
311 uint8_t pstat;
312
313 ow_reset();
314 ow_command( DS18X20_READ_POWER_SUPPLY, id );
315 pstat = ow_bit_io( 1 );
316 ow_reset();
317 return ( pstat ) ? DS18X20_POWER_EXTERN : DS18X20_POWER_PARASITE;
318 }
319
320 /* start measurement (CONVERT_T) for all sensors if input id==NULL
321 or for single sensor where id is the rom-code */
322 uint8_t DS18X20_start_meas( uint8_t with_power_extern, uint8_t id[])
323 {
324 uint8_t ret;
325
326 ow_reset();
327 if( ow_input_pin_state() ) { // only send if bus is "idle" = high
328 if ( with_power_extern != DS18X20_POWER_EXTERN ) {
329 ow_command_with_parasite_enable( DS18X20_CONVERT_T, id );
330 /* not longer needed: ow_parasite_enable(); */
331 } else {
332 ow_command( DS18X20_CONVERT_T, id );
333 }
334 ret = DS18X20_OK;
335 }
336 else {
337 uart_puts_P_verbose( "DS18X20_start_meas: Short Circuit!\r" );
338 ret = DS18X20_START_FAIL;
339 }
340
341 return ret;
342 }
343
344 // returns 1 if conversion is in progress, 0 if finished
345 // not available when parasite powered.
346 uint8_t DS18X20_conversion_in_progress(void)
347 {
348 return ow_bit_io( 1 ) ? DS18X20_CONVERSION_DONE : DS18X20_CONVERTING;
349 }
350
351 static uint8_t read_scratchpad( uint8_t id[], uint8_t sp[], uint8_t n )
352 {
353 uint8_t i;
354 uint8_t ret;
355
356 ow_command( DS18X20_READ, id );
357 for ( i = 0; i < n; i++ ) {
358 sp[i] = ow_byte_rd();
359 }
360 if ( crc8( &sp[0], DS18X20_SP_SIZE ) ) {
361 ret = DS18X20_ERROR_CRC;
362 } else {
363 ret = DS18X20_OK;
364 }
365
366 return ret;
367 }
368
369
370 #if DS18X20_DECICELSIUS
371
372 /* convert scratchpad data to physical value in unit decicelsius */
373 static int16_t DS18X20_raw_to_decicelsius( uint8_t familycode, uint8_t sp[] )
374 {
375 uint16_t measure;
376 uint8_t negative;
377 int16_t decicelsius;
378 uint16_t fract;
379
380 measure = sp[0] | (sp[1] << 8);
381 //measure = 0xFF5E; // test -10.125
382 //measure = 0xFE6F; // test -25.0625
383
384 if( familycode == DS18S20_FAMILY_CODE ) { // 9 -> 12 bit if 18S20
385 /* Extended measurements for DS18S20 contributed by Carsten Foss */
386 measure &= (uint16_t)0xfffe; // Discard LSB, needed for later extended precicion calc
387 measure <<= 3; // Convert to 12-bit, now degrees are in 1/16 degrees units
388 measure += (16 - sp[6]) - 4; // Add the compensation and remember to subtract 0.25 degree (4/16)
389 }
390
391 // check for negative
392 if ( measure & 0x8000 ) {
393 negative = 1; // mark negative
394 measure ^= 0xffff; // convert to positive => (twos complement)++
395 measure++;
396 }
397 else {
398 negative = 0;
399 }
400
401 // clear undefined bits for DS18B20 != 12bit resolution
402 if ( familycode == DS18B20_FAMILY_CODE || familycode == DS1822_FAMILY_CODE ) {
403 switch( sp[DS18B20_CONF_REG] & DS18B20_RES_MASK ) {
404 case DS18B20_9_BIT:
405 measure &= ~(DS18B20_9_BIT_UNDF);
406 break;
407 case DS18B20_10_BIT:
408 measure &= ~(DS18B20_10_BIT_UNDF);
409 break;
410 case DS18B20_11_BIT:
411 measure &= ~(DS18B20_11_BIT_UNDF);
412 break;
413 default:
414 // 12 bit - all bits valid
415 break;
416 }
417 }
418
419 decicelsius = (measure >> 4);
420 decicelsius *= 10;
421
422 // decicelsius += ((measure & 0x000F) * 640 + 512) / 1024;
423 // 625/1000 = 640/1024
424 fract = ( measure & 0x000F ) * 640;
425 if ( !negative ) {
426 fract += 512;
427 }
428 fract /= 1024;
429 decicelsius += fract;
430
431 if ( negative ) {
432 decicelsius = -decicelsius;
433 }
434
435 if ( /* decicelsius == 850 || */ decicelsius < -550 || decicelsius > 1250 ) {
436 return DS18X20_INVALID_DECICELSIUS;
437 } else {
438 return decicelsius;
439 }
440 }
441
442 /* format decicelsius-value into string, itoa method inspired
443 by code from Chris Takahashi for the MSP430 libc, BSD-license
444 modifications mthomas: variable-types, fixed radix 10, use div(),
445 insert decimal-point */
446 uint8_t DS18X20_format_from_decicelsius( int16_t decicelsius, char str[], uint8_t n)
447 {
448 uint8_t sign = 0;
449 char temp[7];
450 int8_t temp_loc = 0;
451 uint8_t str_loc = 0;
452 div_t dt;
453 uint8_t ret;
454
455 // range from -550:-55.0�C to 1250:+125.0�C -> min. 6+1 chars
456 if ( n >= (6+1) && decicelsius > -1000 && decicelsius < 10000 ) {
457
458 if ( decicelsius < 0) {
459 sign = 1;
460 decicelsius = -decicelsius;
461 }
462
463 // construct a backward string of the number.
464 do {
465 dt = div(decicelsius,10);
466 temp[temp_loc++] = dt.rem + '0';
467 decicelsius = dt.quot;
468 } while ( decicelsius > 0 );
469
470 if ( sign ) {
471 temp[temp_loc] = '-';
472 } else {
473 ///temp_loc--;
474 temp[temp_loc] = '+';
475 }
476
477 // reverse the string.into the output
478 while ( temp_loc >=0 ) {
479 str[str_loc++] = temp[(uint8_t)temp_loc--];
480 if ( temp_loc == 0 ) {
481 str[str_loc++] = DS18X20_DECIMAL_CHAR;
482 }
483 }
484 str[str_loc] = '\0';
485
486 ret = DS18X20_OK;
487 } else {
488 ret = DS18X20_ERROR;
489 }
490
491 return ret;
492 }
493
494 /* reads temperature (scratchpad) of sensor with rom-code id
495 output: decicelsius
496 returns DS18X20_OK on success */
497 uint8_t DS18X20_read_decicelsius( uint8_t id[], int16_t *decicelsius )
498 {
499 uint8_t sp[DS18X20_SP_SIZE];
500 uint8_t ret;
501
502 ow_reset();
503 ret = read_scratchpad( id, sp, DS18X20_SP_SIZE );
504 if ( ret == DS18X20_OK ) {
505 *decicelsius = DS18X20_raw_to_decicelsius( id[0], sp );
506 }
507 return ret;
508 }
509
510 /* reads temperature (scratchpad) of sensor without id (single sensor)
511 output: decicelsius
512 returns DS18X20_OK on success */
513 uint8_t DS18X20_read_decicelsius_single( uint8_t familycode, int16_t *decicelsius )
514 {
515 uint8_t sp[DS18X20_SP_SIZE];
516 uint8_t ret;
517
518 ret = read_scratchpad( NULL, sp, DS18X20_SP_SIZE );
519 if ( ret == DS18X20_OK ) {
520 *decicelsius = DS18X20_raw_to_decicelsius( familycode, sp );
521 }
522 return ret;
523 }
524
525 #endif /* DS18X20_DECICELSIUS */
526
527
528 #if DS18X20_MAX_RESOLUTION
529
530 static int32_t DS18X20_raw_to_maxres( uint8_t familycode, uint8_t sp[] )
531 {
532 uint16_t measure;
533 uint8_t negative;
534 int32_t temperaturevalue;
535
536 measure = sp[0] | (sp[1] << 8);
537 //measure = 0xFF5E; // test -10.125
538 //measure = 0xFE6F; // test -25.0625
539
540 if( familycode == DS18S20_FAMILY_CODE ) { // 9 -> 12 bit if 18S20
541 /* Extended measurements for DS18S20 contributed by Carsten Foss */
542 measure &= (uint16_t)0xfffe; // Discard LSB, needed for later extended precicion calc
543 measure <<= 3; // Convert to 12-bit, now degrees are in 1/16 degrees units
544 measure += ( 16 - sp[6] ) - 4; // Add the compensation and remember to subtract 0.25 degree (4/16)
545 }
546
547 // check for negative
548 if ( measure & 0x8000 ) {
549 negative = 1; // mark negative
550 measure ^= 0xffff; // convert to positive => (twos complement)++
551 measure++;
552 }
553 else {
554 negative = 0;
555 }
556
557 // clear undefined bits for DS18B20 != 12bit resolution
558 if ( familycode == DS18B20_FAMILY_CODE || familycode == DS1822_FAMILY_CODE ) {
559 switch( sp[DS18B20_CONF_REG] & DS18B20_RES_MASK ) {
560 case DS18B20_9_BIT:
561 measure &= ~(DS18B20_9_BIT_UNDF);
562 break;
563 case DS18B20_10_BIT:
564 measure &= ~(DS18B20_10_BIT_UNDF);
565 break;
566 case DS18B20_11_BIT:
567 measure &= ~(DS18B20_11_BIT_UNDF);
568 break;
569 default:
570 // 12 bit - all bits valid
571 break;
572 }
573 }
574
575 temperaturevalue = (measure >> 4);
576 temperaturevalue *= 10000;
577 temperaturevalue +=( measure & 0x000F ) * DS18X20_FRACCONV;
578
579 if ( negative ) {
580 temperaturevalue = -temperaturevalue;
581 }
582
583 return temperaturevalue;
584 }
585
586 uint8_t DS18X20_read_maxres( uint8_t id[], int32_t *temperaturevalue )
587 {
588 uint8_t sp[DS18X20_SP_SIZE];
589 uint8_t ret;
590
591 ow_reset();
592 ret = read_scratchpad( id, sp, DS18X20_SP_SIZE );
593 if ( ret == DS18X20_OK ) {
594 *temperaturevalue = DS18X20_raw_to_maxres( id[0], sp );
595 }
596 return ret;
597 }
598
599 uint8_t DS18X20_read_maxres_single( uint8_t familycode, int32_t *temperaturevalue )
600 {
601 uint8_t sp[DS18X20_SP_SIZE];
602 uint8_t ret;
603
604 ret = read_scratchpad( NULL, sp, DS18X20_SP_SIZE );
605 if ( ret == DS18X20_OK ) {
606 *temperaturevalue = DS18X20_raw_to_maxres( familycode, sp );
607 }
608 return ret;
609
610 }
611
612 uint8_t DS18X20_format_from_maxres( int32_t temperaturevalue, char str[], uint8_t n)
613 {
614 uint8_t sign = 0;
615 char temp[10];
616 int8_t temp_loc = 0;
617 uint8_t str_loc = 0;
618 ldiv_t ldt;
619 uint8_t ret;
620
621 // range from -550000:-55.0000�C to 1250000:+125.0000�C -> min. 9+1 chars
622 if ( n >= (9+1) && temperaturevalue > -1000000L && temperaturevalue < 10000000L ) {
623
624 if ( temperaturevalue < 0) {
625 sign = 1;
626 temperaturevalue = -temperaturevalue;
627 }
628
629 do {
630 ldt = ldiv( temperaturevalue, 10 );
631 temp[temp_loc++] = ldt.rem + '0';
632 temperaturevalue = ldt.quot;
633 } while ( temperaturevalue > 0 );
634
635 // mk 20110209
636 if ((temp_loc < 4)&&(temp_loc > 1)) {
637 temp[temp_loc++] = '0';
638 } // mk end
639
640 if ( sign ) {
641 temp[temp_loc] = '-';
642 } else {
643 temp[temp_loc] = '+';
644 }
645
646 while ( temp_loc >= 0 ) {
647 str[str_loc++] = temp[(uint8_t)temp_loc--];
648 if ( temp_loc == 3 ) {
649 str[str_loc++] = DS18X20_DECIMAL_CHAR;
650 }
651 }
652 str[str_loc] = '\0';
653
654 ret = DS18X20_OK;
655 } else {
656 ret = DS18X20_ERROR;
657 }
658
659 return ret;
660 }
661
662 #endif /* DS18X20_MAX_RESOLUTION */
663
664
665 #if DS18X20_EEPROMSUPPORT
666
667 uint8_t DS18X20_write_scratchpad( uint8_t id[],
668 uint8_t th, uint8_t tl, uint8_t conf)
669 {
670 uint8_t ret;
671
672 ow_reset();
673 if( ow_input_pin_state() ) { // only send if bus is "idle" = high
674 ow_command( DS18X20_WRITE_SCRATCHPAD, id );
675 ow_byte_wr( th );
676 ow_byte_wr( tl );
677 if ( id[0] == DS18B20_FAMILY_CODE || id[0] == DS1822_FAMILY_CODE ) {
678 ow_byte_wr( conf ); // config only available on DS18B20 and DS1822
679 }
680 ret = DS18X20_OK;
681 }
682 else {
683 uart_puts_P_verbose( "DS18X20_write_scratchpad: Short Circuit!\r" );
684 ret = DS18X20_ERROR;
685 }
686
687 return ret;
688 }
689
690 uint8_t DS18X20_read_scratchpad( uint8_t id[], uint8_t sp[], uint8_t n )
691 {
692 uint8_t ret;
693
694 ow_reset();
695 if( ow_input_pin_state() ) { // only send if bus is "idle" = high
696 ret = read_scratchpad( id, sp, n );
697 }
698 else {
699 uart_puts_P_verbose( "DS18X20_read_scratchpad: Short Circuit!\r" );
700 ret = DS18X20_ERROR;
701 }
702
703 return ret;
704 }
705
706 uint8_t DS18X20_scratchpad_to_eeprom( uint8_t with_power_extern,
707 uint8_t id[] )
708 {
709 uint8_t ret;
710
711 ow_reset();
712 if( ow_input_pin_state() ) { // only send if bus is "idle" = high
713 if ( with_power_extern != DS18X20_POWER_EXTERN ) {
714 ow_command_with_parasite_enable( DS18X20_COPY_SCRATCHPAD, id );
715 /* not longer needed: ow_parasite_enable(); */
716 } else {
717 ow_command( DS18X20_COPY_SCRATCHPAD, id );
718 }
719 _delay_ms(DS18X20_COPYSP_DELAY); // wait for 10 ms
720 if ( with_power_extern != DS18X20_POWER_EXTERN ) {
721 ow_parasite_disable();
722 }
723 ret = DS18X20_OK;
724 }
725 else {
726 uart_puts_P_verbose( "DS18X20_copy_scratchpad: Short Circuit!\r" );
727 ret = DS18X20_START_FAIL;
728 }
729
730 return ret;
731 }
732
733 uint8_t DS18X20_eeprom_to_scratchpad( uint8_t id[] )
734 {
735 uint8_t ret;
736 uint8_t retry_count=255;
737
738 ow_reset();
739 if( ow_input_pin_state() ) { // only send if bus is "idle" = high
740 ow_command( DS18X20_RECALL_E2, id );
741 while( retry_count-- && !( ow_bit_io( 1 ) ) ) {
742 ;
743 }
744 if ( retry_count ) {
745 ret = DS18X20_OK;
746 } else {
747 uart_puts_P_verbose( "DS18X20_recall_E2: timeout!\r" );
748 ret = DS18X20_ERROR;
749 }
750 }
751 else {
752 uart_puts_P_verbose( "DS18X20_recall_E2: Short Circuit!\r" );
753 ret = DS18X20_ERROR;
754 }
755
756 return ret;
757 }
758
759 #endif /* DS18X20_EEPROMSUPPORT */
760