Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
DS18X20.cpp
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 (Published 01/03/2012 www.mbed.org) 00006 */ 00007 #include "mbed.h" 00008 #include "onewire.h" 00009 #include "DS18X20.h" 00010 #include "crc8.h" 00011 #include "utils.h" 00012 //********************************************************************************************************** 00013 //* DS18X20_show_temp 00014 //********************************************************************************************************** 00015 00016 /** 00017 * @brief DS18X20_show_temp 00018 * @param [in] id[] = rom_code 00019 * @param [in] n number of id[n] 00020 * @param [out] text temp in degre celsius 00021 00022 * @date 20/06/2011 00023 */ 00024 void DS18X20_show_temp(uint8_t subzero, uint8_t cel, uint8_t cel_frac_bits,char *text) { 00025 uint16_t decicelsius; 00026 char s[10]; 00027 float temperature; 00028 sprintf(text,""); 00029 sprintf(s,"%s", (subzero)?"-":""); 00030 strcat(text,s); 00031 decicelsius = DS18X20_temp_to_decicel(subzero, cel, cel_frac_bits); 00032 temperature = decicelsius; 00033 temperature = temperature/10; 00034 sprintf(s,"%4.1f", temperature); 00035 strcat(text,s); 00036 00037 } 00038 /** 00039 * @brief DS18X20_show_temp 00040 * @param [in] id[] = rom_code 00041 * @param [in] n number of id[n] 00042 * @return temp in degre celsius 00043 00044 * @date 21/10/2011 00045 */ 00046 float DS18X20_temp(uint8_t subzero, uint8_t cel, uint8_t cel_frac_bits) { 00047 return ((subzero)?-1:1)*DS18X20_temp_to_decicel(subzero, cel, cel_frac_bits)/10; 00048 } 00049 //********************************************************************************************************** 00050 //* DS18X20_get_power_status 00051 //********************************************************************************************************** 00052 00053 /** 00054 * @brief get power status of DS18x20 00055 * @param [in] id[] = rom_code 00056 * @return DS18X20_POWER_EXTERN or DS18X20_POWER_PARASITE 00057 * @date 20/06/2011 00058 */ 00059 uint8_t DS18X20_get_power_status(uint8_t id[]) { 00060 uint8_t pstat; 00061 ow_reset(); 00062 ow_command(DS18X20_READ_POWER_SUPPLY, id); 00063 pstat=ow_bit_io(1); // pstat 0=is parasite/ !=0 ext. powered 00064 ow_reset(); 00065 return (pstat) ? DS18X20_POWER_EXTERN:DS18X20_POWER_PARASITE; 00066 } 00067 00068 /** 00069 * @brief get power status of DS18x20 00070 * @param [in] n num bus onewire 00071 * @param [in] id[] = rom_code 00072 * @return DS18X20_POWER_EXTERN or DS18X20_POWER_PARASITE 00073 * @date 6/09/2011 00074 */ 00075 uint8_t DS18X20_get_power_status(uint8_t n,uint8_t id[]) { 00076 uint8_t pstat; 00077 ow_reset(n); 00078 ow_command(n,DS18X20_READ_POWER_SUPPLY, id); 00079 pstat=ow_bit_io(n,1); // pstat 0=is parasite/ !=0 ext. powered 00080 ow_reset(n); 00081 return (pstat) ? DS18X20_POWER_EXTERN:DS18X20_POWER_PARASITE; 00082 } 00083 //********************************************************************************************************** 00084 //* DS18X20_start_meas 00085 //********************************************************************************************************** 00086 /** 00087 * @brief reads temperature (scratchpad) of sensor with rom-code id 00088 output: subzero==1 if temp.<0, cel: full celsius, mcel: frac 00089 in millicelsius*0.1 00090 i.e.: subzero=1, cel=18, millicel=5000 = -18,5000�C 00091 * @param [in] n num bus onewire 00092 * @param [in] id[] = rom_code 00093 * @param [out] temperature 00094 * @return DS18X20_OK or DS18X20_ERROR_CRC 00095 * @date 07/12/2012 00096 */ 00097 uint8_t DS18X20_read_meas(uint8_t n,uint8_t id[], float* temperature) { 00098 uint8_t i; 00099 uint8_t sp[DS18X20_SP_SIZE]; 00100 uint8_t subzero; 00101 uint8_t cel; 00102 uint8_t cel_frac_bits; 00103 00104 ow_reset(n); 00105 ow_command(n,DS18X20_READ, id); 00106 for ( i=0 ; i< DS18X20_SP_SIZE; i++ ) 00107 sp[i]=ow_byte_rd(n); 00108 if ( crc8( &sp[0], DS18X20_SP_SIZE ) ){ 00109 if ((sp[DS18X20_SP_SIZE-1]==0xFF) && (sp[DS18X20_SP_SIZE-2]==0xFF)) 00110 return OW_ERROR; // bus error 00111 return DS18X20_ERROR_CRC; // data error 00112 } 00113 00114 DS18X20_meas_to_cel(id[0], sp, &subzero, &cel, &cel_frac_bits); 00115 *temperature = cel_frac_bits*.0625; 00116 *temperature += cel; 00117 if (subzero) 00118 *temperature *= -1; 00119 return DS18X20_OK; 00120 } 00121 /** 00122 * @brief start measurement (CONVERT_T) for all sensors if input id==NULL 00123 or for single sensor. then id is the rom-code 00124 * @param [in] with_power_extern 00125 * @param [in] rom_code 00126 * @return DS18X20_OK or DS18X20_START_FAIL 00127 * @date 20/06/2011 00128 */ 00129 uint8_t DS18X20_start_meas( uint8_t with_power_extern, uint8_t id[]) { 00130 ow_reset(); //** 00131 if ( ow_test_pin() ) { // only send if bus is "idle" = high 00132 ow_command( DS18X20_CONVERT_T, id ); 00133 if (with_power_extern != DS18X20_POWER_EXTERN) 00134 ow_parasite_enable(); 00135 return DS18X20_OK; 00136 } 00137 return DS18X20_START_FAIL; 00138 00139 } 00140 /** 00141 * @brief start measurement (CONVERT_T) for all sensors if input id==NULL 00142 or for single sensor. then id is the rom-code 00143 * @param [in] n num bus onewire 00144 * @param [in] with_power_extern 00145 * @param [in] rom_code 00146 * @return DS18X20_OK or DS18X20_START_FAIL 00147 * @date 06/09/2011 00148 */ 00149 uint8_t DS18X20_start_meas(uint8_t n, uint8_t with_power_extern, uint8_t id[]) { 00150 ow_reset(n); //** 00151 if ( ow_test_pin(n) ) { // only send if bus is "idle" = high 00152 ow_command(n, DS18X20_CONVERT_T, id ); 00153 if (with_power_extern != DS18X20_POWER_EXTERN) 00154 ow_parasite_enable(n); 00155 return DS18X20_OK; 00156 } 00157 return DS18X20_START_FAIL; 00158 00159 } 00160 //********************************************************************************************************** 00161 //* DS18X20_read_meas 00162 //********************************************************************************************************** 00163 00164 /** 00165 * @brief reads temperature (scratchpad) of sensor with rom-code id 00166 output: subzero==1 if temp.<0, cel: full celsius, mcel: frac 00167 in millicelsius*0.1 00168 i.e.: subzero=1, cel=18, millicel=5000 = -18,5000�C 00169 * @param [in] id[] = rom_code 00170 * @param [out] subzero 00171 * @param [out] cel 00172 * @param [out] cel_frac_bits 00173 * @return DS18X20_OK or DS18X20_ERROR_CRC 00174 * @date 20/06/2011 00175 */ 00176 uint8_t DS18X20_read_meas(uint8_t id[], uint8_t *subzero, 00177 uint8_t *cel, uint8_t *cel_frac_bits) { 00178 uint8_t i; 00179 uint8_t sp[DS18X20_SP_SIZE]; 00180 00181 ow_reset(); 00182 ow_command(DS18X20_READ, id); 00183 for ( i=0 ; i< DS18X20_SP_SIZE; i++ ) 00184 sp[i]=ow_byte_rd(); 00185 if ( crc8( &sp[0], DS18X20_SP_SIZE ) ){ 00186 if ((sp[DS18X20_SP_SIZE-1]==0xFF) && (sp[DS18X20_SP_SIZE-2]==0xFF)) 00187 return OW_ERROR; // bus error 00188 return DS18X20_ERROR_CRC; // data error 00189 } 00190 00191 DS18X20_meas_to_cel(id[0], sp, subzero, cel, cel_frac_bits); 00192 return DS18X20_OK; 00193 } 00194 /** 00195 * @brief reads temperature (scratchpad) of sensor with rom-code id 00196 output: subzero==1 if temp.<0, cel: full celsius, mcel: frac 00197 in millicelsius*0.1 00198 i.e.: subzero=1, cel=18, millicel=5000 = -18,5000�C 00199 * @param [in] n num bus onewire 00200 * @param [in] id[] = rom_code 00201 * @param [out] subzero 00202 * @param [out] cel 00203 * @param [out] cel_frac_bits 00204 * @return DS18X20_OK or DS18X20_ERROR_CRC 00205 * @date 06/09/2011 00206 */ 00207 uint8_t DS18X20_read_meas(uint8_t n,uint8_t id[], uint8_t *subzero, 00208 uint8_t *cel, uint8_t *cel_frac_bits) { 00209 uint8_t i; 00210 uint8_t sp[DS18X20_SP_SIZE]; 00211 00212 ow_reset(n); 00213 ow_command(n,DS18X20_READ, id); 00214 for ( i=0 ; i< DS18X20_SP_SIZE; i++ ) 00215 sp[i]=ow_byte_rd(n); 00216 if ( crc8( &sp[0], DS18X20_SP_SIZE ) ){ 00217 if ((sp[DS18X20_SP_SIZE-1]==0xFF) && (sp[DS18X20_SP_SIZE-2]==0xFF)) 00218 return OW_ERROR; // bus error 00219 return DS18X20_ERROR_CRC; // data error 00220 } 00221 00222 DS18X20_meas_to_cel(id[0], sp, subzero, cel, cel_frac_bits); 00223 return DS18X20_OK; 00224 } 00225 /** 00226 * @brief convert raw value from DS18x20 to Celsius 00227 input is: 00228 - familycode fc (0x10/0x28 see header) 00229 - scratchpad-buffer 00230 output is: 00231 - cel full celsius 00232 - fractions of celsius in millicelsius*(10^-1)/625 (the 4 LS-Bits) 00233 - subzero =0 positiv / 1 negativ 00234 always returns DS18X20_OK 00235 TODO invalid-values detection (but should be covered by CRC) 00236 * @param [in] fc 00237 * @param [in] sp 00238 * @param [out] subzero 00239 * @param [out] cel 00240 * @param [out] cel_frac_bits 00241 * @return DS18X20_OK 00242 * @date 20/06/2011 00243 */ 00244 uint8_t DS18X20_meas_to_cel( uint8_t fc, uint8_t *sp, 00245 uint8_t* subzero, uint8_t* cel, uint8_t* cel_frac_bits) { 00246 uint16_t meas; 00247 uint8_t i; 00248 00249 meas = sp[0]; // LSB 00250 meas |= ((uint16_t)sp[1])<<8; // MSB 00251 //meas = 0xff5e; meas = 0xfe6f; 00252 00253 // only work on 12bit-base 00254 if ( fc == DS18S20_ID ) { // 9 -> 12 bit if 18S20 00255 /* Extended measurements for DS18S20 contributed by Carsten Foss */ 00256 meas &= (uint16_t) 0xfffe; // Discard LSB , needed for later extended precicion calc 00257 meas <<= 3; // Convert to 12-bit , now degrees are in 1/16 degrees units 00258 meas += (16 - sp[6]) - 4; // Add the compensation , and remember to subtract 0.25 degree (4/16) 00259 } 00260 00261 // check for negative 00262 if ( meas & 0x8000 ) { 00263 *subzero=1; // mark negative 00264 meas ^= 0xffff; // convert to positive => (twos complement)++ 00265 meas++; 00266 } else *subzero=0; 00267 00268 // clear undefined bits for B != 12bit 00269 if ( fc == DS18B20_ID ) { // check resolution 18B20 00270 i = sp[DS18B20_CONF_REG]; 00271 if ( (i & DS18B20_12_BIT) == DS18B20_12_BIT ) ; 00272 else if ( (i & DS18B20_11_BIT) == DS18B20_11_BIT ) 00273 meas &= ~(DS18B20_11_BIT_UNDF); 00274 else if ( (i & DS18B20_10_BIT) == DS18B20_10_BIT ) 00275 meas &= ~(DS18B20_10_BIT_UNDF); 00276 else { // if ( (i & DS18B20_9_BIT) == DS18B20_9_BIT ) { 00277 meas &= ~(DS18B20_9_BIT_UNDF); 00278 } 00279 } 00280 00281 *cel = (uint8_t)(meas >> 4); 00282 *cel_frac_bits = (uint8_t)(meas & 0x000F); 00283 00284 return DS18X20_OK; 00285 } 00286 00287 /** 00288 * @brief converts to decicelsius 00289 input is ouput from meas_to_cel 00290 i.e.: sz=0, c=28, frac=15 returns 289 (=28.9�C) 00291 0 0 0 00292 1 625 625 1 00293 2 1250 250 00294 3 1875 875 3 00295 4 2500 500 4 00296 5 3125 125 00297 6 3750 750 6 00298 7 4375 375 00299 8 5000 0 00300 9 5625 625 9 00301 10 6250 250 00302 11 6875 875 11 00303 12 7500 500 12 00304 13 8125 125 00305 14 8750 750 14 00306 15 9375 375 00307 * @param [in] subzero 00308 * @param [in] cel 00309 * @param [in] cel_frac_bits 00310 * @return absolute value of temperatur in decicelsius 00311 * @date 20/06/2011 00312 */ 00313 uint16_t DS18X20_temp_to_decicel(uint8_t subzero, uint8_t cel, 00314 uint8_t cel_frac_bits) { 00315 uint16_t h; 00316 uint8_t i; 00317 uint8_t need_rounding[] = { 1, 3, 4, 6, 9, 11, 12, 14 }; 00318 00319 h = cel_frac_bits*DS18X20_FRACCONV/1000; 00320 h += cel*10; 00321 if (!subzero) { 00322 for (i=0; i<sizeof(need_rounding); i++) { 00323 if ( cel_frac_bits == need_rounding[i] ) { 00324 h++; 00325 break; 00326 } 00327 } 00328 } 00329 return h; 00330 } 00331 /** 00332 * @brief compare temperature values (full celsius only) 00333 * @param [in] subzero1 00334 * @param [in] cel1 00335 * @param [in] subzero2 00336 * @param [in] cel2 00337 * @return -1 if param-pair1 < param-pair2 00338 0 if == 00339 1 if > 00340 * @date 20/06/2011 00341 */ 00342 int8_t DS18X20_temp_cmp(uint8_t subzero1, uint16_t cel1, 00343 uint8_t subzero2, uint16_t cel2) { 00344 int16_t t1 = (subzero1) ? (cel1*(-1)) : (cel1); 00345 int16_t t2 = (subzero2) ? (cel2*(-1)) : (cel2); 00346 00347 if (t1<t2) return -1; 00348 if (t1>t2) return 1; 00349 return 0; 00350 }
Generated on Mon Jul 18 2022 20:45:44 by
1.7.2