Things to mention in this post:
* Temperature Sensors
* Tmp116n
In this post, we are writing Tmp116n temperature sensor Ilibrary using HAL I2C library.
About Temperature Sensors
The basic principle of working of the temperature sensors is the voltage across the diode terminals. If the voltage increases, the temperature also rises, followed by a voltage drop between the transistor terminals of base and emitter in a diode.
In Regards to these informations, we are going to program our temperature sensor’s registers to involve in different modes or specify the thresholds.
About TMP116N
In this link , you can get the datasheet of related device.

In this post we are not going into the datasheet, you can check the registers over the datasheet from this table while reading this post.
Let’s Code
First of all, we need an Init function like always we did. Thanks to this function, we are assigning the handlers, address and timeout just 1 time. Because for generic design, we do not prefer to write them as a parameter every time.
/**
* @brief TMP116N_Init Init Task
* @param[in] me : Handle Pointer
* @param[in] i2cHandler : Register Address
* @param[in] deviceAddress : Target Device Address
* @param[in] TimeOut : Program TimeOut
* @retval value
*/
TMP_StatusTypeDef_e TMP116N_Init(TMP116N_ts *me, I2C_HandleTypeDef *i2cHandler, uint8_t deviceAddress, uint16_t TimeOut){
me->i2chandle = i2cHandler;
me->DeviceAddress = deviceAddress;
me->ProgramTimeOut = TimeOut;
return TMP116N_isConnected(me);
}
This function also controlls the device, is it connected or not ?
/**
* @brief TMP116N_isConnected checks the device is connected or not.
* @param[in] me : Handle pointer
* @retval FlagStatus
*/
TMP_StatusTypeDef_e TMP116N_isConnected(TMP116N_ts *me){
if(HAL_I2C_IsDeviceReady(me->i2chandle, me->DeviceAddress, 3, me->ProgramTimeOut) == HAL_OK)
return TMP_OK;
return TMP_ERROR;
}
With pre-configured values which are in the header file, we can set the low and high thresholds thanks to these functions :
/**
* @brief tmp116n_setLowTH sets the low thresh hold value to device for the interrupt.
* @param[in] none
* @retval none
*/
void TMP116N_setLowTH(void){
// 1 LSB equals 7.8125 m°C.( 2^-7)
TMP116N_Write(TMP116N_REG_LIMIT_LOW, TEMPERATURE_LOW_TH <<7);
}
/**
* @brief TMP116N_setHighTH sets the high thresh hold value to device for the interrupt.
* @param[in] none
* @retval none
*/
void TMP116N_setHighTH(void){
// 1 LSB equals 7.8125 m°C.( 2^-7)
TMP116N_Write(TMP116N_REG_LIMIT_HIGH, TEMPERATURE_HIGH_TH <<7);
}
To writing into a register we are design this function to make a library more understandable:
/**
* @brief TMP116N_Write writes the data to the given register address.
* @param[in] RegAddr : Register Address
* @param[in] pData : Data to writing at the given register address.
* @retval TMP_StatusTypeDef_e
*/
TMP_StatusTypeDef_e TMP116N_Write(uint8_t RegAddr, int16_t pData ){
TMP_StatusTypeDef_e status = TMP_OK;
pData = ((pData &0x00FF)<<8 | (pData &0xFF00)>> 8);
status = (TMP_StatusTypeDef_e)HAL_I2C_Mem_Write(&TMP116N_I2C, TMP116N_I2C_SAD, RegAddr, I2C_MEMADD_SIZE_8BIT, (uint8_t*)&pData, 2, 1000);
if (status!=HAL_OK ) printHS((HAL_StatusTypeDef)status);
return status;
}
Thanks to all these functions, we can write a static function that makes us comfortable in this library. With this function we can put in different modes and also we can read the temperature value.
/* Static function --------------------------------------------------------------------------*/
static int TMP116N_LL(TMP116N_ts *me, TMP_OperationTypeDef_e Tmp_Operation, uint8_t RegAddr){
uint8_t retval[2]={0};
TMP_StatusTypeDef_e status = TMP_OK;
switch(Tmp_Operation)
{
case TMP_RESET:
TMP116N_Write(TMP116N_REG_TEMP, 0x8000);
TMP116N_Write(TMP116N_REG_CONF, 0x0220);
TMP116N_Write(TMP116N_REG_LIMIT_HIGH, 0x6000);
TMP116N_Write(TMP116N_REG_LIMIT_LOW, 0x8000);
TMP116N_Write(TMP116N_REG_EEPROM_UNLOCK, 0x0000);
TMP116N_Write(TMP116N_REG_EEPROM1, 0x0000);
TMP116N_Write(TMP116N_REG_EEPROM2, 0x0000);
TMP116N_Write(TMP116N_REG_EEPROM3, 0x0000);
TMP116N_Write(TMP116N_REG_EEPROM4, 0x0000);
TMP116N_Write(TMP116N_REG_DEVICE_ID, 0x1116);
break;
case TMP_READ:
status = (TMP_StatusTypeDef_e)HAL_I2C_Mem_Read(me->i2chandle, me->DeviceAddress, RegAddr, I2C_MEMADD_SIZE_8BIT, retval, 2, me->ProgramTimeOut);
if (status != TMP_OK )
{
#if TMP_DEBUG
printHS((HAL_StatusTypeDef)status);
#endif
return 0;
}
return retval[0]<<8 | retval[1];
case TMP_SHUTDOWN:
TMP116N_Write(TMP116N_REG_CONF, 0x0400);
break;
case TMP_INTERRUPT:
TMP116N_setLowTH();
#if TMP_DEBUG
DBG_PRINT("\ntmp116n_setLowTH set as %f", convertRawTemperature2Temperature(TMP116N_LL(me, TMP_READ, TMP116N_REG_LIMIT_LOW)));
#endif
TMP116N_setHighTH();
#if TMP_DEBUG
DBG_PRINT("\ntmp116n_setHighTH set as %f\n", convertRawTemperature2Temperature(TMP116N_LL(me, TMP_READ, TMP116N_REG_LIMIT_HIGH)));
#endif
TMP116N_LL(me, TMP_READ, TMP116N_REG_CONF); // to clear alert bit
TMP116N_Write(TMP116N_REG_CONF,0x0380); // 0x0400 shutdown mode
break;
default: break;
}
return 0;
}
For rest of the functions, it is easier now.
Reset Function API :
/**
* @brief TMP116N_Reset resets the device.
* @param[in] me : Handle pointer
* @retval value
*/
int TMP116N_Reset(TMP116N_ts *me){
return TMP116N_LL(me, TMP_RESET, 0);
}
Reading the temperature value API :
/**
* @brief TMP116N_ReadTemperature reads the temperature value from device.
* @param[in] me : Handle pointer
* @retval value
*/
float TMP116N_ReadTemperature(TMP116N_ts *me){
return TMP116N_convertRawTemp(TMP116N_LL(me, TMP_READ, TMP116N_REG_TEMP));
}
/**
* @brief TMP116N_convertRawTemp converts the raw value came from device.
* @param[in] rawTemp : The parameter value that comes from the device.
* @retval value
*/
float TMP116N_convertRawTemp(int16_t rawTemp){
return (float)(rawTemp)/128.0f;
}
To Sum Up, we designed the library that have simple API’s which are belongs into the static function in the Tmp116n Library.
You can check the GitHub Link,
