onewire DS18B20 DS2450

Dependencies:   mbed

Committer:
fblanc
Date:
Thu Jun 30 13:18:22 2011 +0000
Revision:
0:df0e3c8895f4
2011_06_30

Who changed what in which revision?

UserRevisionLine numberNew contents of line
fblanc 0:df0e3c8895f4 1 /**
fblanc 0:df0e3c8895f4 2 * @file DS18x20.c
fblanc 0:df0e3c8895f4 3 * @brief library of DS18X20 1-Wire digital thermometer (http://www.maxim-ic.com/datasheet/index.mvp/id/2812)
fblanc 0:df0e3c8895f4 4 * @author Maciej Rajtar (Published 10 May 2010 www.mbed.org)
fblanc 0:df0e3c8895f4 5 * @author Frederic BLANC
fblanc 0:df0e3c8895f4 6 */
fblanc 0:df0e3c8895f4 7 #include "mbed.h"
fblanc 0:df0e3c8895f4 8 #include "onewire.h"
fblanc 0:df0e3c8895f4 9 #include "DS18X20.h"
fblanc 0:df0e3c8895f4 10 #include "crc8.h"
fblanc 0:df0e3c8895f4 11 #include "utils.h"
fblanc 0:df0e3c8895f4 12 /**
fblanc 0:df0e3c8895f4 13 * @brief get power status of DS18x20
fblanc 0:df0e3c8895f4 14 * @param [in] uint8_t id[] = rom_code
fblanc 0:df0e3c8895f4 15 * @return DS18X20_POWER_EXTERN or DS18X20_POWER_PARASITE
fblanc 0:df0e3c8895f4 16 * @date 20/06/2011
fblanc 0:df0e3c8895f4 17 */
fblanc 0:df0e3c8895f4 18 uint8_t DS18X20_get_power_status(uint8_t id[]) {
fblanc 0:df0e3c8895f4 19 uint8_t pstat;
fblanc 0:df0e3c8895f4 20 ow_reset();
fblanc 0:df0e3c8895f4 21 ow_command(DS18X20_READ_POWER_SUPPLY, id);
fblanc 0:df0e3c8895f4 22 pstat=ow_bit_io(1); // pstat 0=is parasite/ !=0 ext. powered
fblanc 0:df0e3c8895f4 23 ow_reset();
fblanc 0:df0e3c8895f4 24 return (pstat) ? DS18X20_POWER_EXTERN:DS18X20_POWER_PARASITE;
fblanc 0:df0e3c8895f4 25 }
fblanc 0:df0e3c8895f4 26
fblanc 0:df0e3c8895f4 27
fblanc 0:df0e3c8895f4 28
fblanc 0:df0e3c8895f4 29 /**
fblanc 0:df0e3c8895f4 30 * @brief start measurement (CONVERT_T) for all sensors if input id==NULL
fblanc 0:df0e3c8895f4 31 or for single sensor. then id is the rom-code
fblanc 0:df0e3c8895f4 32 * @param [in] uint8_t with_power_extern
fblanc 0:df0e3c8895f4 33 * @param [in] uint8_t id[] = rom_code
fblanc 0:df0e3c8895f4 34 * @return DS18X20_OK or DS18X20_START_FAIL
fblanc 0:df0e3c8895f4 35 * @date 20/06/2011
fblanc 0:df0e3c8895f4 36 */
fblanc 0:df0e3c8895f4 37 uint8_t DS18X20_start_meas( uint8_t with_power_extern, uint8_t id[]) {
fblanc 0:df0e3c8895f4 38 ow_reset(); //**
fblanc 0:df0e3c8895f4 39 if ( ow_test_pin() ) { // only send if bus is "idle" = high
fblanc 0:df0e3c8895f4 40 ow_command( DS18X20_CONVERT_T, id );
fblanc 0:df0e3c8895f4 41 if (with_power_extern != DS18X20_POWER_EXTERN)
fblanc 0:df0e3c8895f4 42 ow_parasite_enable();
fblanc 0:df0e3c8895f4 43 return DS18X20_OK;
fblanc 0:df0e3c8895f4 44 }
fblanc 0:df0e3c8895f4 45 return DS18X20_START_FAIL;
fblanc 0:df0e3c8895f4 46
fblanc 0:df0e3c8895f4 47 }
fblanc 0:df0e3c8895f4 48
fblanc 0:df0e3c8895f4 49 /**
fblanc 0:df0e3c8895f4 50 * @brief reads temperature (scratchpad) of sensor with rom-code id
fblanc 0:df0e3c8895f4 51 output: subzero==1 if temp.<0, cel: full celsius, mcel: frac
fblanc 0:df0e3c8895f4 52 in millicelsius*0.1
fblanc 0:df0e3c8895f4 53 i.e.: subzero=1, cel=18, millicel=5000 = -18,5000&#65533;C
fblanc 0:df0e3c8895f4 54 * @param [in] id[] = rom_code
fblanc 0:df0e3c8895f4 55 * @param [out] subzero
fblanc 0:df0e3c8895f4 56 * @param [out] cel
fblanc 0:df0e3c8895f4 57 * @param [out] cel_frac_bits
fblanc 0:df0e3c8895f4 58 * @return DS18X20_OK or DS18X20_ERROR_CRC
fblanc 0:df0e3c8895f4 59 * @date 20/06/2011
fblanc 0:df0e3c8895f4 60 */
fblanc 0:df0e3c8895f4 61 uint8_t DS18X20_read_meas(uint8_t id[], uint8_t *subzero,
fblanc 0:df0e3c8895f4 62 uint8_t *cel, uint8_t *cel_frac_bits) {
fblanc 0:df0e3c8895f4 63 uint8_t i;
fblanc 0:df0e3c8895f4 64 uint8_t sp[DS18X20_SP_SIZE];
fblanc 0:df0e3c8895f4 65
fblanc 0:df0e3c8895f4 66 ow_reset();
fblanc 0:df0e3c8895f4 67 ow_command(DS18X20_READ, id);
fblanc 0:df0e3c8895f4 68 for ( i=0 ; i< DS18X20_SP_SIZE; i++ )
fblanc 0:df0e3c8895f4 69 sp[i]=ow_byte_rd();
fblanc 0:df0e3c8895f4 70 if ( crc8( &sp[0], DS18X20_SP_SIZE ) ){
fblanc 0:df0e3c8895f4 71 if ((sp[DS18X20_SP_SIZE-1]==0xFF) && (sp[DS18X20_SP_SIZE-2]==0xFF))
fblanc 0:df0e3c8895f4 72 return OW_ERROR; // bus error
fblanc 0:df0e3c8895f4 73 return DS18X20_ERROR_CRC; // data error
fblanc 0:df0e3c8895f4 74 }
fblanc 0:df0e3c8895f4 75
fblanc 0:df0e3c8895f4 76 DS18X20_meas_to_cel(id[0], sp, subzero, cel, cel_frac_bits);
fblanc 0:df0e3c8895f4 77 return DS18X20_OK;
fblanc 0:df0e3c8895f4 78 }
fblanc 0:df0e3c8895f4 79
fblanc 0:df0e3c8895f4 80 /**
fblanc 0:df0e3c8895f4 81 * @brief convert raw value from DS18x20 to Celsius
fblanc 0:df0e3c8895f4 82 input is:
fblanc 0:df0e3c8895f4 83 - familycode fc (0x10/0x28 see header)
fblanc 0:df0e3c8895f4 84 - scratchpad-buffer
fblanc 0:df0e3c8895f4 85 output is:
fblanc 0:df0e3c8895f4 86 - cel full celsius
fblanc 0:df0e3c8895f4 87 - fractions of celsius in millicelsius*(10^-1)/625 (the 4 LS-Bits)
fblanc 0:df0e3c8895f4 88 - subzero =0 positiv / 1 negativ
fblanc 0:df0e3c8895f4 89 always returns DS18X20_OK
fblanc 0:df0e3c8895f4 90 TODO invalid-values detection (but should be covered by CRC)
fblanc 0:df0e3c8895f4 91 * @param [in] fc
fblanc 0:df0e3c8895f4 92 * @param [in] sp
fblanc 0:df0e3c8895f4 93 * @param [out] subzero
fblanc 0:df0e3c8895f4 94 * @param [out] cel
fblanc 0:df0e3c8895f4 95 * @param [out] cel_frac_bits
fblanc 0:df0e3c8895f4 96 * @return DS18X20_OK
fblanc 0:df0e3c8895f4 97 * @date 20/06/2011
fblanc 0:df0e3c8895f4 98 */
fblanc 0:df0e3c8895f4 99 uint8_t DS18X20_meas_to_cel( uint8_t fc, uint8_t *sp,
fblanc 0:df0e3c8895f4 100 uint8_t* subzero, uint8_t* cel, uint8_t* cel_frac_bits) {
fblanc 0:df0e3c8895f4 101 uint16_t meas;
fblanc 0:df0e3c8895f4 102 uint8_t i;
fblanc 0:df0e3c8895f4 103
fblanc 0:df0e3c8895f4 104 meas = sp[0]; // LSB
fblanc 0:df0e3c8895f4 105 meas |= ((uint16_t)sp[1])<<8; // MSB
fblanc 0:df0e3c8895f4 106 //meas = 0xff5e; meas = 0xfe6f;
fblanc 0:df0e3c8895f4 107
fblanc 0:df0e3c8895f4 108 // only work on 12bit-base
fblanc 0:df0e3c8895f4 109 if ( fc == DS18S20_ID ) { // 9 -> 12 bit if 18S20
fblanc 0:df0e3c8895f4 110 /* Extended measurements for DS18S20 contributed by Carsten Foss */
fblanc 0:df0e3c8895f4 111 meas &= (uint16_t) 0xfffe; // Discard LSB , needed for later extended precicion calc
fblanc 0:df0e3c8895f4 112 meas <<= 3; // Convert to 12-bit , now degrees are in 1/16 degrees units
fblanc 0:df0e3c8895f4 113 meas += (16 - sp[6]) - 4; // Add the compensation , and remember to subtract 0.25 degree (4/16)
fblanc 0:df0e3c8895f4 114 }
fblanc 0:df0e3c8895f4 115
fblanc 0:df0e3c8895f4 116 // check for negative
fblanc 0:df0e3c8895f4 117 if ( meas & 0x8000 ) {
fblanc 0:df0e3c8895f4 118 *subzero=1; // mark negative
fblanc 0:df0e3c8895f4 119 meas ^= 0xffff; // convert to positive => (twos complement)++
fblanc 0:df0e3c8895f4 120 meas++;
fblanc 0:df0e3c8895f4 121 } else *subzero=0;
fblanc 0:df0e3c8895f4 122
fblanc 0:df0e3c8895f4 123 // clear undefined bits for B != 12bit
fblanc 0:df0e3c8895f4 124 if ( fc == DS18B20_ID ) { // check resolution 18B20
fblanc 0:df0e3c8895f4 125 i = sp[DS18B20_CONF_REG];
fblanc 0:df0e3c8895f4 126 if ( (i & DS18B20_12_BIT) == DS18B20_12_BIT ) ;
fblanc 0:df0e3c8895f4 127 else if ( (i & DS18B20_11_BIT) == DS18B20_11_BIT )
fblanc 0:df0e3c8895f4 128 meas &= ~(DS18B20_11_BIT_UNDF);
fblanc 0:df0e3c8895f4 129 else if ( (i & DS18B20_10_BIT) == DS18B20_10_BIT )
fblanc 0:df0e3c8895f4 130 meas &= ~(DS18B20_10_BIT_UNDF);
fblanc 0:df0e3c8895f4 131 else { // if ( (i & DS18B20_9_BIT) == DS18B20_9_BIT ) {
fblanc 0:df0e3c8895f4 132 meas &= ~(DS18B20_9_BIT_UNDF);
fblanc 0:df0e3c8895f4 133 }
fblanc 0:df0e3c8895f4 134 }
fblanc 0:df0e3c8895f4 135
fblanc 0:df0e3c8895f4 136 *cel = (uint8_t)(meas >> 4);
fblanc 0:df0e3c8895f4 137 *cel_frac_bits = (uint8_t)(meas & 0x000F);
fblanc 0:df0e3c8895f4 138
fblanc 0:df0e3c8895f4 139 return DS18X20_OK;
fblanc 0:df0e3c8895f4 140 }
fblanc 0:df0e3c8895f4 141
fblanc 0:df0e3c8895f4 142 /**
fblanc 0:df0e3c8895f4 143 * @brief converts to decicelsius
fblanc 0:df0e3c8895f4 144 input is ouput from meas_to_cel
fblanc 0:df0e3c8895f4 145 i.e.: sz=0, c=28, frac=15 returns 289 (=28.9&#65533;C)
fblanc 0:df0e3c8895f4 146 0 0 0
fblanc 0:df0e3c8895f4 147 1 625 625 1
fblanc 0:df0e3c8895f4 148 2 1250 250
fblanc 0:df0e3c8895f4 149 3 1875 875 3
fblanc 0:df0e3c8895f4 150 4 2500 500 4
fblanc 0:df0e3c8895f4 151 5 3125 125
fblanc 0:df0e3c8895f4 152 6 3750 750 6
fblanc 0:df0e3c8895f4 153 7 4375 375
fblanc 0:df0e3c8895f4 154 8 5000 0
fblanc 0:df0e3c8895f4 155 9 5625 625 9
fblanc 0:df0e3c8895f4 156 10 6250 250
fblanc 0:df0e3c8895f4 157 11 6875 875 11
fblanc 0:df0e3c8895f4 158 12 7500 500 12
fblanc 0:df0e3c8895f4 159 13 8125 125
fblanc 0:df0e3c8895f4 160 14 8750 750 14
fblanc 0:df0e3c8895f4 161 15 9375 375
fblanc 0:df0e3c8895f4 162 * @param [in] subzero
fblanc 0:df0e3c8895f4 163 * @param [in] cel
fblanc 0:df0e3c8895f4 164 * @param [in] cel_frac_bits
fblanc 0:df0e3c8895f4 165 * @return absolute value of temperatur in decicelsius
fblanc 0:df0e3c8895f4 166 * @date 20/06/2011
fblanc 0:df0e3c8895f4 167 */
fblanc 0:df0e3c8895f4 168 uint16_t DS18X20_temp_to_decicel(uint8_t subzero, uint8_t cel,
fblanc 0:df0e3c8895f4 169 uint8_t cel_frac_bits) {
fblanc 0:df0e3c8895f4 170 uint16_t h;
fblanc 0:df0e3c8895f4 171 uint8_t i;
fblanc 0:df0e3c8895f4 172 uint8_t need_rounding[] = { 1, 3, 4, 6, 9, 11, 12, 14 };
fblanc 0:df0e3c8895f4 173
fblanc 0:df0e3c8895f4 174 h = cel_frac_bits*DS18X20_FRACCONV/1000;
fblanc 0:df0e3c8895f4 175 h += cel*10;
fblanc 0:df0e3c8895f4 176 if (!subzero) {
fblanc 0:df0e3c8895f4 177 for (i=0; i<sizeof(need_rounding); i++) {
fblanc 0:df0e3c8895f4 178 if ( cel_frac_bits == need_rounding[i] ) {
fblanc 0:df0e3c8895f4 179 h++;
fblanc 0:df0e3c8895f4 180 break;
fblanc 0:df0e3c8895f4 181 }
fblanc 0:df0e3c8895f4 182 }
fblanc 0:df0e3c8895f4 183 }
fblanc 0:df0e3c8895f4 184 return h;
fblanc 0:df0e3c8895f4 185 }
fblanc 0:df0e3c8895f4 186 /**
fblanc 0:df0e3c8895f4 187 * @brief compare temperature values (full celsius only)
fblanc 0:df0e3c8895f4 188 * @param [in] subzero1
fblanc 0:df0e3c8895f4 189 * @param [in] cel1
fblanc 0:df0e3c8895f4 190 * @param [in] subzero2
fblanc 0:df0e3c8895f4 191 * @param [in] cel2
fblanc 0:df0e3c8895f4 192 * @return -1 if param-pair1 < param-pair2
fblanc 0:df0e3c8895f4 193 0 if ==
fblanc 0:df0e3c8895f4 194 1 if >
fblanc 0:df0e3c8895f4 195 * @date 20/06/2011
fblanc 0:df0e3c8895f4 196 */
fblanc 0:df0e3c8895f4 197 int8_t DS18X20_temp_cmp(uint8_t subzero1, uint16_t cel1,
fblanc 0:df0e3c8895f4 198 uint8_t subzero2, uint16_t cel2) {
fblanc 0:df0e3c8895f4 199 int16_t t1 = (subzero1) ? (cel1*(-1)) : (cel1);
fblanc 0:df0e3c8895f4 200 int16_t t2 = (subzero2) ? (cel2*(-1)) : (cel2);
fblanc 0:df0e3c8895f4 201
fblanc 0:df0e3c8895f4 202 if (t1<t2) return -1;
fblanc 0:df0e3c8895f4 203 if (t1>t2) return 1;
fblanc 0:df0e3c8895f4 204 return 0;
fblanc 0:df0e3c8895f4 205 }