frederic blanc
/
OneWireDrv
onewire DS18B20 DS2450
DS18X20.c@0:df0e3c8895f4, 2011-06-30 (annotated)
- Committer:
- fblanc
- Date:
- Thu Jun 30 13:18:22 2011 +0000
- Revision:
- 0:df0e3c8895f4
2011_06_30
Who changed what in which revision?
User | Revision | Line number | New 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�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�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 | } |