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