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