Simple cpp wrapper of a ds18b20, onewire 'c' library. Supports multiple sensors.
Dependents: LPC11U68_DS18B20Sensor
Fork of DS18B20Sensor by
DS18X20.c
00001 /** 00002 * @file DS18x20.c 00003 * @brief library of DS18X20 1-Wire digital thermometer (http://www.maxim-ic.com/datasheet/index.mvp/id/2812) 00004 * @author Maciej Rajtar (Published 10 May 2010 www.mbed.org) 00005 * @author Frederic BLANC 00006 */ 00007 #include "mbed.h" 00008 #include "onewire.h" 00009 #include "DS18X20.h" 00010 #include "crc8.h" 00011 /** 00012 * @brief get power status of DS18x20 00013 * @param [in] uint8_t id[] = rom_code 00014 * @return DS18X20_POWER_EXTERN or DS18X20_POWER_PARASITE 00015 * @date 20/06/2011 00016 */ 00017 uint8_t DS18X20_get_power_status(uint8_t id[]) { 00018 uint8_t pstat; 00019 ow_reset(); 00020 ow_command(DS18X20_READ_POWER_SUPPLY, id); 00021 pstat=ow_bit_io(1); // pstat 0=is parasite/ !=0 ext. powered 00022 ow_reset(); 00023 return (pstat) ? DS18X20_POWER_EXTERN:DS18X20_POWER_PARASITE; 00024 } 00025 00026 00027 00028 /** 00029 * @brief start measurement (CONVERT_T) for all sensors if input id==NULL 00030 or for single sensor. then id is the rom-code 00031 * @param [in] uint8_t with_power_extern 00032 * @param [in] uint8_t id[] = rom_code 00033 * @return DS18X20_OK or DS18X20_START_FAIL 00034 * @date 20/06/2011 00035 */ 00036 uint8_t DS18X20_start_meas( uint8_t with_power_extern, uint8_t id[]) { 00037 ow_reset(); //** 00038 if ( ow_test_pin() ) { // only send if bus is "idle" = high 00039 ow_command( DS18X20_CONVERT_T, id ); 00040 if (with_power_extern != DS18X20_POWER_EXTERN) 00041 ow_parasite_enable(); 00042 return DS18X20_OK; 00043 } 00044 return DS18X20_START_FAIL; 00045 00046 } 00047 00048 /** 00049 * @brief reads temperature (scratchpad) of sensor with rom-code id 00050 output: subzero==1 if temp.<0, cel: full celsius, mcel: frac 00051 in millicelsius*0.1 00052 i.e.: subzero=1, cel=18, millicel=5000 = -18,5000�C 00053 * @param [in] id[] = rom_code 00054 * @param [out] subzero 00055 * @param [out] cel 00056 * @param [out] cel_frac_bits 00057 * @return DS18X20_OK or DS18X20_ERROR_CRC 00058 * @date 20/06/2011 00059 */ 00060 uint8_t DS18X20_read_meas(uint8_t id[], uint8_t *subzero, 00061 uint8_t *cel, uint8_t *cel_frac_bits) { 00062 uint8_t i; 00063 uint8_t sp[DS18X20_SP_SIZE]; 00064 00065 ow_reset(); 00066 ow_command(DS18X20_READ, id); 00067 for ( i=0 ; i< DS18X20_SP_SIZE; i++ ) 00068 sp[i]=ow_byte_rd(); 00069 if ( crc8( &sp[0], DS18X20_SP_SIZE ) ){ 00070 if ((sp[DS18X20_SP_SIZE-1]==0xFF) && (sp[DS18X20_SP_SIZE-2]==0xFF)) 00071 return OW_ERROR; // bus error 00072 return DS18X20_ERROR_CRC; // data error 00073 } 00074 00075 DS18X20_meas_to_cel(id[0], sp, subzero, cel, cel_frac_bits); 00076 return DS18X20_OK; 00077 } 00078 00079 /** 00080 * @brief convert raw value from DS18x20 to Celsius 00081 input is: 00082 - familycode fc (0x10/0x28 see header) 00083 - scratchpad-buffer 00084 output is: 00085 - cel full celsius 00086 - fractions of celsius in millicelsius*(10^-1)/625 (the 4 LS-Bits) 00087 - subzero =0 positiv / 1 negativ 00088 always returns DS18X20_OK 00089 TODO invalid-values detection (but should be covered by CRC) 00090 * @param [in] fc 00091 * @param [in] sp 00092 * @param [out] subzero 00093 * @param [out] cel 00094 * @param [out] cel_frac_bits 00095 * @return DS18X20_OK 00096 * @date 20/06/2011 00097 */ 00098 uint8_t DS18X20_meas_to_cel( uint8_t fc, uint8_t *sp, 00099 uint8_t* subzero, uint8_t* cel, uint8_t* cel_frac_bits) { 00100 uint16_t meas; 00101 uint8_t i; 00102 00103 meas = sp[0]; // LSB 00104 meas |= ((uint16_t)sp[1])<<8; // MSB 00105 //meas = 0xff5e; meas = 0xfe6f; 00106 00107 // only work on 12bit-base 00108 if ( fc == DS18S20_ID ) { // 9 -> 12 bit if 18S20 00109 /* Extended measurements for DS18S20 contributed by Carsten Foss */ 00110 meas &= (uint16_t) 0xfffe; // Discard LSB , needed for later extended precicion calc 00111 meas <<= 3; // Convert to 12-bit , now degrees are in 1/16 degrees units 00112 meas += (16 - sp[6]) - 4; // Add the compensation , and remember to subtract 0.25 degree (4/16) 00113 } 00114 00115 // check for negative 00116 if ( meas & 0x8000 ) { 00117 *subzero=1; // mark negative 00118 meas ^= 0xffff; // convert to positive => (twos complement)++ 00119 meas++; 00120 } else *subzero=0; 00121 00122 // clear undefined bits for B != 12bit 00123 if ( fc == DS18B20_ID ) { // check resolution 18B20 00124 i = sp[DS18B20_CONF_REG]; 00125 if ( (i & DS18B20_12_BIT) == DS18B20_12_BIT ) ; 00126 else if ( (i & DS18B20_11_BIT) == DS18B20_11_BIT ) 00127 meas &= ~(DS18B20_11_BIT_UNDF); 00128 else if ( (i & DS18B20_10_BIT) == DS18B20_10_BIT ) 00129 meas &= ~(DS18B20_10_BIT_UNDF); 00130 else { // if ( (i & DS18B20_9_BIT) == DS18B20_9_BIT ) { 00131 meas &= ~(DS18B20_9_BIT_UNDF); 00132 } 00133 } 00134 00135 *cel = (uint8_t)(meas >> 4); 00136 *cel_frac_bits = (uint8_t)(meas & 0x000F); 00137 00138 return DS18X20_OK; 00139 } 00140 00141 /** 00142 * @brief converts to decicelsius 00143 input is ouput from meas_to_cel 00144 i.e.: sz=0, c=28, frac=15 returns 289 (=28.9�C) 00145 0 0 0 00146 1 625 625 1 00147 2 1250 250 00148 3 1875 875 3 00149 4 2500 500 4 00150 5 3125 125 00151 6 3750 750 6 00152 7 4375 375 00153 8 5000 0 00154 9 5625 625 9 00155 10 6250 250 00156 11 6875 875 11 00157 12 7500 500 12 00158 13 8125 125 00159 14 8750 750 14 00160 15 9375 375 00161 * @param [in] subzero 00162 * @param [in] cel 00163 * @param [in] cel_frac_bits 00164 * @return absolute value of temperatur in decicelsius 00165 * @date 20/06/2011 00166 */ 00167 uint16_t DS18X20_temp_to_decicel(uint8_t subzero, uint8_t cel, 00168 uint8_t cel_frac_bits) { 00169 uint16_t h; 00170 uint8_t i; 00171 uint8_t need_rounding[] = { 1, 3, 4, 6, 9, 11, 12, 14 }; 00172 00173 h = cel_frac_bits*DS18X20_FRACCONV/1000; 00174 h += cel*10; 00175 if (!subzero) { 00176 for (i=0; i<sizeof(need_rounding); i++) { 00177 if ( cel_frac_bits == need_rounding[i] ) { 00178 h++; 00179 break; 00180 } 00181 } 00182 } 00183 return h; 00184 } 00185 /** 00186 * @brief compare temperature values (full celsius only) 00187 * @param [in] subzero1 00188 * @param [in] cel1 00189 * @param [in] subzero2 00190 * @param [in] cel2 00191 * @return -1 if param-pair1 < param-pair2 00192 0 if == 00193 1 if > 00194 * @date 20/06/2011 00195 */ 00196 int8_t DS18X20_temp_cmp(uint8_t subzero1, uint16_t cel1, 00197 uint8_t subzero2, uint16_t cel2) { 00198 int16_t t1 = (subzero1) ? (cel1*(-1)) : (cel1); 00199 int16_t t2 = (subzero2) ? (cel2*(-1)) : (cel2); 00200 00201 if (t1<t2) return -1; 00202 if (t1>t2) return 1; 00203 return 0; 00204 }
Generated on Wed Jul 13 2022 23:17:04 by 1.7.2