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.
Dependents: mbed-os5-F303-18650-Manager-tp4056
MCP9808.cpp
00001 /** 00002 * @brief MCP9808.cpp 00003 * @details ±0.5°C Maximum Accuracy Digital Temperature Sensor. 00004 * Function file. 00005 * 00006 * 00007 * @return N/A 00008 * 00009 * @author Manuel Caballero 00010 * @date 25/April/2019 00011 * @version 25/April/2019 The ORIGIN 00012 * @pre N/A. 00013 * @warning N/A 00014 * @pre This code belongs to AqueronteBlog ( http://unbarquero.blogspot.com ). All rights reserved. 00015 */ 00016 00017 #include "MCP9808.h" 00018 00019 00020 MCP9808::MCP9808 ( PinName sda, PinName scl, uint32_t addr, uint32_t freq ) 00021 : _i2c ( sda, scl ) 00022 , _MCP9808_Addr ( addr ) 00023 { 00024 _i2c.frequency( freq ); 00025 } 00026 00027 00028 MCP9808::~MCP9808() 00029 { 00030 } 00031 00032 00033 00034 /** 00035 * @brief MCP9808_GetCONFIG ( MCP9808_config_reg_t* ) 00036 * 00037 * @details It gets CONFIG register value. 00038 * 00039 * @param[in] N/A. 00040 * 00041 * @param[out] myCONFIG: CONFIG register value. 00042 * 00043 * 00044 * @return Status of MCP9808_GetCONFIG. 00045 * 00046 * 00047 * @author Manuel Caballero 00048 * @date 25/April/2019 00049 * @version 25/April/2019 The ORIGIN 00050 * @pre N/A 00051 * @warning N/A. 00052 */ 00053 MCP9808::MCP9808_status_t MCP9808::MCP9808_GetCONFIG ( MCP9808_config_reg_t* myCONFIG ) 00054 { 00055 char cmd[2] = { 0U }; 00056 uint16_t myConfigAux = 0U; 00057 uint32_t aux; 00058 00059 /* Read the register */ 00060 cmd[0] = MCP9808_CONFIG ; 00061 aux = _i2c.write ( _MCP9808_Addr, &cmd[0], 1U, true ); 00062 aux = _i2c.read ( _MCP9808_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) ); 00063 00064 /* Mask it and update it with the new value */ 00065 myConfigAux = cmd[0]; 00066 myConfigAux <<= 8U; 00067 myConfigAux |= cmd[1]; 00068 00069 myCONFIG->t_hyst = (MCP9808_config_thyst_t)( myConfigAux & CONFIG_T_HYST_MASK ); 00070 myCONFIG->shdn = (MCP9808_config_shdn_t )( myConfigAux & CONFIG_SHDN_MASK ); 00071 myCONFIG->t_crit = (MCP9808_config_crit_lock_t )( myConfigAux & CONFIG_CRIT_LOCK_MASK ); 00072 myCONFIG->t_win_lock = (MCP9808_config_win_lock_t )( myConfigAux & CONFIG_WIN_LOCK_MASK ); 00073 myCONFIG->int_clear = (MCP9808_conf_int_clear_t )( myConfigAux & CONFIG_INT_CLEAR_MASK ); 00074 myCONFIG->alert_stat = (MCP9808_config_alert_stat_t )( myConfigAux & CONFIG_ALERT_STAT_MASK ); 00075 myCONFIG->alert_cnt = (MCP9808_config_alert_cnt_t )( myConfigAux & CONFIG_ALERT_CNT_MASK ); 00076 myCONFIG->alert_sel = (MCP9808_config_alert_sel_t )( myConfigAux & CONFIG_ALERT_SEL_MASK ); 00077 myCONFIG->alert_pol = (MCP9808_config_alert_pol_t )( myConfigAux & CONFIG_ALERT_POL_MASK ); 00078 myCONFIG->alert_mod = (MCP9808_config_alert_mod_t )( myConfigAux & CONFIG_ALERT_MOD_MASK ); 00079 00080 00081 00082 if ( aux == I2C_SUCCESS ) 00083 { 00084 return MCP9808_SUCCESS; 00085 } 00086 else 00087 { 00088 return MCP9808_FAILURE; 00089 } 00090 } 00091 00092 00093 00094 /** 00095 * @brief MCP9808_SetCONFIG ( MCP9808_config_reg_t ) 00096 * 00097 * @details It sets CONFIG register value. 00098 * 00099 * @param[in] myCONFIG: CONFIG register value. 00100 * 00101 * @param[out] N/A. 00102 * 00103 * 00104 * @return Status of MCP9808_SetCONFIG. 00105 * 00106 * 00107 * @author Manuel Caballero 00108 * @date 25/April/2019 00109 * @version 25/April/2019 The ORIGIN 00110 * @pre MCP9808_GetCONFIG function should be called first to mask the bits. 00111 * @warning Be aware that some commands can NOT be written depending on Crit.Lock and/or Win.Lock values. 00112 */ 00113 MCP9808::MCP9808_status_t MCP9808::MCP9808_SetCONFIG ( MCP9808_config_reg_t myCONFIG ) 00114 { 00115 char cmd[3] = { 0U }; 00116 uint16_t myConfigAux = 0U; 00117 uint32_t aux; 00118 00119 /* Update CONFI register */ 00120 myConfigAux = ( myCONFIG.t_hyst | myCONFIG.shdn | myCONFIG.t_crit | myCONFIG.t_win_lock | myCONFIG.int_clear | 00121 myCONFIG.alert_stat | myCONFIG.alert_cnt | myCONFIG.alert_sel | myCONFIG.alert_pol | myCONFIG.alert_mod ); 00122 00123 cmd[0] = MCP9808_CONFIG ; 00124 cmd[1] = (uint8_t)( myConfigAux >> 8U ); 00125 cmd[2] = (uint8_t)( myConfigAux & 0xFF ); 00126 aux = _i2c.write ( _MCP9808_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), false ); 00127 00128 00129 00130 00131 if ( aux == I2C_SUCCESS ) 00132 { 00133 return MCP9808_SUCCESS; 00134 } 00135 else 00136 { 00137 return MCP9808_FAILURE; 00138 } 00139 } 00140 00141 00142 00143 /** 00144 * @brief MCP9808_GetRawTA ( MCP9808_data_t* ) 00145 * 00146 * @details It gets ambient temperature register ( raw value ). 00147 * 00148 * @param[in] N/A 00149 * 00150 * @param[out] myRawTA: Raw T_A data. 00151 * 00152 * 00153 * @return Status of MCP9808_GetRawTA. 00154 * 00155 * 00156 * @author Manuel Caballero 00157 * @date 25/April/2019 00158 * @version 25/April/2019 The ORIGIN 00159 * @pre N/A 00160 * @warning N/A. 00161 */ 00162 MCP9808::MCP9808_status_t MCP9808::MCP9808_GetRawTA ( MCP9808_data_t* myRawTA ) 00163 { 00164 char cmd[2] = { 0U }; 00165 uint32_t aux; 00166 00167 /* Read the register */ 00168 cmd[0] = MCP9808_TA ; 00169 aux = _i2c.write ( _MCP9808_Addr, &cmd[0], 1U, true ); 00170 aux = _i2c.read ( _MCP9808_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) ); 00171 00172 /* Mask it and update it with the new value */ 00173 myRawTA->t_a_raw = cmd[0]; 00174 myRawTA->t_a_raw <<= 8U; 00175 myRawTA->t_a_raw |= cmd[1]; 00176 00177 00178 00179 00180 if ( aux == I2C_SUCCESS ) 00181 { 00182 return MCP9808_SUCCESS; 00183 } 00184 else 00185 { 00186 return MCP9808_FAILURE; 00187 } 00188 } 00189 00190 00191 00192 /** 00193 * @brief MCP9808_GetTA ( MCP9808_data_t* ) 00194 * 00195 * @details It gets ambient temperature register ( Celsius degrees ). 00196 * 00197 * @param[in] N/A 00198 * 00199 * @param[out] myTA: T_A value and flags. 00200 * 00201 * 00202 * @return Status of MCP9808_GetTA. 00203 * 00204 * 00205 * @author Manuel Caballero 00206 * @date 25/April/2019 00207 * @version 25/April/2019 The ORIGIN 00208 * @pre This function also updates the comparison flags. 00209 * @warning N/A. 00210 */ 00211 MCP9808::MCP9808_status_t MCP9808::MCP9808_GetTA ( MCP9808_data_t* myTA ) 00212 { 00213 uint8_t myUpperByte = 0U; 00214 uint8_t myLowerByte = 0U; 00215 MCP9808::MCP9808_status_t aux; 00216 00217 /* Read the register */ 00218 aux = MCP9808::MCP9808_GetRawTA ( &(*myTA) ); 00219 00220 /* Mask it and update it with the new value */ 00221 /* Mask the flags */ 00222 myTA->ta_vs_tcrit = (MCP9808_t_a_ta_vs_tcrit_t)( myTA->t_a_raw & T_A_TA_VS_TCRIT_MASK ); 00223 myTA->ta_vs_tupper = (MCP9808_t_a_ta_vs_tupper_t )( myTA->t_a_raw & T_A_TA_VS_TUPPER_MASK ); 00224 myTA->t_lower = (MCP9808_t_a_ta_vs_tlower_t )( myTA->t_a_raw & T_A_TA_VS_TLOWER_MASK ); 00225 myTA->t_a_sign = (MCP9808_t_a_sign_t )( myTA->t_a_raw & T_A_TA_SIGN_MASK ); 00226 00227 /* Mask the ambient temperature value */ 00228 myUpperByte = (uint8_t)( myTA->t_a_raw >> 8U ); 00229 myLowerByte = (uint8_t)( myTA->t_a_raw & 0xFF ); 00230 00231 /* Clean the flags */ 00232 myUpperByte &= ~(uint8_t)( ( T_A_TA_VS_TCRIT_MASK | T_A_TA_VS_TUPPER_MASK | T_A_TA_VS_TLOWER_MASK ) >> 8U ); 00233 00234 /* Check if T_A is negative/positive */ 00235 if ( myTA->t_a_sign == T_A_TA_SIGN_NEGATIVE ) 00236 { 00237 /* Ambient uint8_t is NEGATIVE */ 00238 myUpperByte &= ~(uint8_t)( T_A_TA_SIGN_MASK >> 8U ); // Clear the SIGN flag 00239 myTA->t_a = 256.0f - (float)( ( myUpperByte * 16.0f ) + ( myLowerByte / 16.0f ) ); // Ambient temperature value 00240 } 00241 else 00242 { 00243 /* Ambient temperature is POSITIVE */ 00244 myTA->t_a = (float)( ( myUpperByte * 16.0f ) + ( myLowerByte / 16.0f ) ); // Ambient temperature value 00245 } 00246 00247 00248 return aux; 00249 } 00250 00251 00252 00253 /** 00254 * @brief MCP9808_GetManufacturerID ( MCP9808_data_t* ) 00255 * 00256 * @details It gets manufacturer ID. 00257 * 00258 * @param[in] N/A. 00259 * 00260 * @param[out] myManufacturerID: Manufacturer ID code 00261 * 00262 * 00263 * @return Status of MCP9808_GetManufacturerID. 00264 * 00265 * 00266 * @author Manuel Caballero 00267 * @date 25/April/2019 00268 * @version 25/April/2019 The ORIGIN 00269 * @pre It should be 0x0054 ( hexadecimal ). 00270 * @warning N/A. 00271 */ 00272 MCP9808::MCP9808_status_t MCP9808::MCP9808_GetManufacturerID ( MCP9808_data_t* myManufacturerID ) 00273 { 00274 char cmd[2] = { 0U }; 00275 uint32_t aux; 00276 00277 /* Read the register */ 00278 cmd[0] = MCP9808_MANUFACTURER_ID ; 00279 aux = _i2c.write ( _MCP9808_Addr, &cmd[0], 1U, true ); 00280 aux = _i2c.read ( _MCP9808_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) ); 00281 00282 /* Mask it and update it with the new value */ 00283 myManufacturerID->manufacturerID = cmd[0]; 00284 myManufacturerID->manufacturerID <<= 8U; 00285 myManufacturerID->manufacturerID |= cmd[1]; 00286 00287 00288 00289 if ( aux == I2C_SUCCESS ) 00290 { 00291 return MCP9808_SUCCESS; 00292 } 00293 else 00294 { 00295 return MCP9808_FAILURE; 00296 } 00297 } 00298 00299 00300 00301 /** 00302 * @brief MCP9808_GetDeviceID ( MCP9808_data_t* ) 00303 * 00304 * @details It gets device ID and device revision. 00305 * 00306 * @param[in] N/A 00307 * 00308 * @param[out] myDeviceID: Both device ID and device revision 00309 * 00310 * 00311 * @return Status of MCP9808_GetDeviceID. 00312 * 00313 * 00314 * @author Manuel Caballero 00315 * @date 25/April/2019 00316 * @version 25/April/2019 The ORIGIN 00317 * @pre Device ID should be 0x04 ( hexadecimal ). 00318 * @warning N/A. 00319 */ 00320 MCP9808::MCP9808_status_t MCP9808::MCP9808_GetDeviceID ( MCP9808_data_t* myDeviceID ) 00321 { 00322 char cmd[2] = { 0U }; 00323 uint32_t aux; 00324 00325 /* Read the register */ 00326 cmd[0] = MCP9808_DEVICE_ID ; 00327 aux = _i2c.write ( _MCP9808_Addr, &cmd[0], 1U, true ); 00328 aux = _i2c.read ( _MCP9808_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ) ); 00329 00330 /* Mask it and update it with the new value */ 00331 myDeviceID->deviceID = cmd[0]; 00332 myDeviceID->deviceRevision = cmd[1]; 00333 00334 00335 00336 if ( aux == I2C_SUCCESS ) 00337 { 00338 return MCP9808_SUCCESS; 00339 } 00340 else 00341 { 00342 return MCP9808_FAILURE; 00343 } 00344 } 00345 00346 00347 00348 /** 00349 * @brief MCP9808_SetResolution ( MCP9808_data_t ) 00350 * 00351 * @details It sets the sensor resolution. 00352 * 00353 * @param[in] myResolution: Device resolution. 00354 * 00355 * @param[out] N/A 00356 * 00357 * 00358 * @return Status of MCP9808_SetResolution. 00359 * 00360 * 00361 * @author Manuel Caballero 00362 * @date 25/April/2019 00363 * @version 25/April/2019 The ORIGIN 00364 * @pre Resolution vs timing conversion: 00365 * · Resolution: +0.5°C ( t_CONV = 30ms typical ) 00366 * · Resolution: +0.25°C ( t_CONV = 65ms typical ) 00367 * · Resolution: +0.125°C ( t_CONV = 130ms typical ) 00368 * · Resolution: +0.0625°C ( power-up default, t_CONV = 250ms typical ) 00369 * @warning N/A. 00370 */ 00371 MCP9808::MCP9808_status_t MCP9808::MCP9808_SetResolution ( MCP9808_data_t myResolution ) 00372 { 00373 char cmd[2] = { 0U }; 00374 uint32_t aux; 00375 00376 /* Read the register */ 00377 cmd[0] = MCP9808_RESOLUTION ; 00378 cmd[1] = myResolution.resolution; 00379 aux = _i2c.write ( _MCP9808_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), false ); 00380 00381 00382 00383 if ( aux == I2C_SUCCESS ) 00384 { 00385 return MCP9808_SUCCESS; 00386 } 00387 else 00388 { 00389 return MCP9808_FAILURE; 00390 } 00391 } 00392 00393 00394 00395 /** 00396 * @brief MCP9808_GetResolution ( MCP9808_data_t* ) 00397 * 00398 * @details It gets the sensor resolution. 00399 * 00400 * @param[in] N/A. 00401 * 00402 * @param[out] myResolution: Device resolution. 00403 * 00404 * 00405 * @return Status of MCP9808_GetResolution. 00406 * 00407 * 00408 * @author Manuel Caballero 00409 * @date 25/April/2019 00410 * @version 25/April/2019 The ORIGIN 00411 * @pre Resolution vs timing conversion: 00412 * · Resolution: +0.5°C ( t_CONV = 30ms typical ) 00413 * · Resolution: +0.25°C ( t_CONV = 65ms typical ) 00414 * · Resolution: +0.125°C ( t_CONV = 130ms typical ) 00415 * · Resolution: +0.0625°C ( power-up default, t_CONV = 250ms typical ) 00416 * @warning N/A. 00417 */ 00418 MCP9808::MCP9808_status_t MCP9808::MCP9808_GetResolution ( MCP9808_data_t* myResolution ) 00419 { 00420 char cmd = 0U; 00421 uint32_t aux; 00422 00423 /* Read the register */ 00424 cmd = MCP9808_RESOLUTION ; 00425 aux = _i2c.write ( _MCP9808_Addr, &cmd, 1U, true ); 00426 aux = _i2c.read ( _MCP9808_Addr, &cmd, 1U ); 00427 00428 /* Mask it and update it with the new value */ 00429 myResolution->resolution = (MCP9808_resolution_t)cmd; 00430 00431 00432 00433 if ( aux == I2C_SUCCESS ) 00434 { 00435 return MCP9808_SUCCESS; 00436 } 00437 else 00438 { 00439 return MCP9808_FAILURE; 00440 } 00441 } 00442 00443 00444 00445 /** 00446 * @brief MCP9808_SetT_Limit ( MCP9808_registers_t, MCP9808_data_t ) 00447 * 00448 * @details It sets temperature limit for: T_UPPER, T_LOWER or T_CRIT. 00449 * 00450 * @param[in] myTLimit: Temperature limit register: T_UPPER, T_LOWER or T_CRIT. 00451 * @param[in] myTValue_Limit: Temperature limit value. 00452 * 00453 * @param[out] N/A. 00454 * 00455 * 00456 * @return Status of MCP9808_SetT_Limit. 00457 * 00458 * 00459 * @author Manuel Caballero 00460 * @date 25/April/2019 00461 * @version 25/April/2019 The ORIGIN 00462 * @pre N/A. 00463 * @warning N/A. 00464 */ 00465 MCP9808::MCP9808_status_t MCP9808::MCP9808_SetT_Limit ( MCP9808_registers_t myTLimit, MCP9808_data_t myTValue_Limit ) 00466 { 00467 char cmd[2] = { 0U }; 00468 int8_t myDecimal = 0U; 00469 int8_t myIntegral = 0U; 00470 uint32_t aux; 00471 00472 /* Only temperature limit registers can keep going */ 00473 if ( ( myTLimit != MCP9808_TUPPER ) || ( myTLimit != MCP9808_TLOWER ) || ( myTLimit != MCP9808_TCRIT ) ) 00474 { 00475 return MCP9808_FAILURE; 00476 } 00477 else 00478 { 00479 /* Parse the data */ 00480 myIntegral = (int8_t)myTValue_Limit.t_upper; 00481 myDecimal = (uint8_t)( ( myTValue_Limit.t_upper - myIntegral ) * 100.0f ); 00482 00483 /* Check the decimal part is correct; Valid decimal values: 0.00, 0.25, 0.50 or 0.75 */ 00484 myIntegral <<= 4U; 00485 myDecimal <<= 2U; 00486 if( ( myDecimal != TEMPERATURE_LIMIT_DECIMAL_PART_0_00C ) || ( myDecimal != TEMPERATURE_LIMIT_DECIMAL_PART_0_25C ) || 00487 ( myDecimal != TEMPERATURE_LIMIT_DECIMAL_PART_0_50C ) || ( myDecimal != TEMPERATURE_LIMIT_DECIMAL_PART_0_50C ) ) 00488 { 00489 return MCP9808_FAILURE; 00490 } 00491 else 00492 { 00493 /* Update the register with the new value */ 00494 cmd[0] = myTLimit; 00495 cmd[1] = ( myIntegral | myDecimal ); 00496 aux = _i2c.write ( _MCP9808_Addr, &cmd[0], sizeof( cmd )/sizeof( cmd[0] ), false ); 00497 00498 00499 if ( aux == I2C_SUCCESS ) 00500 { 00501 return MCP9808_SUCCESS; 00502 } 00503 else 00504 { 00505 return MCP9808_FAILURE; 00506 } 00507 } 00508 } 00509 } 00510 00511 00512 00513 /** 00514 * @brief MCP9808_GetT_Limit ( MCP9808_registers_t, MCP9808_data_t* ) 00515 * 00516 * @details It gets temperature limit for: T_UPPER, T_LOWER or T_CRIT. 00517 * 00518 * @param[in] myTLimit: Temperature limit register: T_UPPER, T_LOWER or T_CRIT. 00519 * 00520 * @param[out] myTValue_Limit: Temperature limit value for the chosen register. 00521 * 00522 * 00523 * @return Status of MCP9808_GetT_Limit. 00524 * 00525 * 00526 * @author Manuel Caballero 00527 * @date 25/April/2019 00528 * @version 25/April/2019 The ORIGIN 00529 * @pre N/A. 00530 * @warning N/A. 00531 */ 00532 MCP9808::MCP9808_status_t MCP9808::MCP9808_GetT_Limit ( MCP9808_registers_t myTLimit, MCP9808_data_t* myTValue_Limit ) 00533 { 00534 char cmd = 0U; 00535 uint8_t myDecimal = 0U; 00536 float myAuxValue = 0U; 00537 uint32_t aux; 00538 00539 /* Only temperature limit registers can keep going */ 00540 if ( ( myTLimit != MCP9808_TUPPER ) || ( myTLimit != MCP9808_TLOWER ) || ( myTLimit != MCP9808_TCRIT ) ) 00541 { 00542 return MCP9808_FAILURE; 00543 } 00544 else 00545 { 00546 /* Read the register */ 00547 cmd = myTLimit; 00548 aux = _i2c.write ( _MCP9808_Addr, &cmd, 1U, true ); 00549 aux = _i2c.read ( _MCP9808_Addr, &cmd, 1U ); 00550 00551 /* Process the data */ 00552 myAuxValue = (float)( ( cmd & TEMPERATURE_LIMIT_INTEGRAL_PART_MASK ) >> 4U ); 00553 myDecimal = ( ( cmd & TEMPERATURE_LIMIT_DECIMAL_PART_MASK ) >> 2U ); 00554 00555 /* Process the decimal part */ 00556 for( cmd = ( TEMPERATURE_LIMIT_DECIMAL_PART_0_00C >> 2U ); cmd < myDecimal; cmd++ ) 00557 { 00558 myAuxValue += 0.25f; 00559 } 00560 00561 /* Parse the data */ 00562 switch( myTLimit ) 00563 { 00564 case MCP9808_TUPPER : 00565 myTValue_Limit->t_upper = (float)myAuxValue; 00566 break; 00567 00568 case MCP9808_TLOWER : 00569 myTValue_Limit->t_lower = (float)myAuxValue; 00570 break; 00571 00572 case MCP9808_TCRIT : 00573 myTValue_Limit->t_crit = (float)myAuxValue; 00574 break; 00575 00576 default: 00577 return MCP9808_FAILURE; 00578 } 00579 00580 00581 00582 if ( aux == I2C_SUCCESS ) 00583 { 00584 return MCP9808_SUCCESS; 00585 } 00586 else 00587 { 00588 return MCP9808_FAILURE; 00589 } 00590 } 00591 }
Generated on Sat Jul 23 2022 05:40:28 by
1.7.2