cancel
Showing results for 
Search instead for 
Did you mean: 

Problem reading registers with HAL_I2C_Mem_Read(_IT)() and temperature sensor LM75B

Dimitris Paraskevopoulos
Associate III
Posted on September 17, 2017 at 06:17

I have an STM32F401RE-Nucleo board and I have bought the mbed Application Shield to toy with the STM ecosystem.

Lately I have been trying to talk to the temperature sensor LM75B and I have achieved some success by being able to read the temperature register which is also the default register by using a call toHAL_I2C_Mem_Read andHAL_I2C_Mem_Read_IT. My problem is that I can't seem to be able to read the configuration register, the hysteresis register and the overtemperature shutdown register.

My code is this:

main.c

/* Includes ------------------------------------------------------------------*/
#include 'main.h'
#define I2C_ADDRESS 0x90
I2C_HandleTypeDef I2cHandle;
/* Buffer used for reception */
uint8_t aRxBuffer[512];
/* Private function prototypes -----------------------------------------------*/
static void SystemClock_Config(void);
static void Error_Handler(void);
int main(void)
{
 volatile float temp = 0.0; /* Temperature */
 volatile float thyst = 0.0; /* Hysteresis register default 75deg C */
 volatile float tos = 0.0; /* Overtemperature shutdown default 80deg C */
 HAL_Init();
 
 /* Configure LED2 */
 BSP_LED_Init(LED2);
 /* Configure the System clock to 84 MHz */
 SystemClock_Config();
 
 /*##-1- Configure the I2C peripheral ######################################*/
 I2cHandle.Instance = I2Cx;
 I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
 I2cHandle.Init.ClockSpeed = 100000;
 I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
 I2cHandle.Init.DutyCycle = I2C_DUTYCYCLE_16_9;
 I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
 I2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
 I2cHandle.Init.OwnAddress1 = 0;
 I2cHandle.Init.OwnAddress2 = 0xFE;
 if(HAL_I2C_Init(&I2cHandle) != HAL_OK)
 {
 /* Initialization Error */
 Error_Handler();
 }
 /* Infinite loop */
 while (1)
 {
 /*##-4- Put I2C peripheral in reception process ############################*/
 do
 {
 if(HAL_I2C_Mem_Read_IT(&I2cHandle, (uint16_t)I2C_ADDRESS, 0, I2C_MEMADD_SIZE_8BIT, (uint8_t *)&aRxBuffer[0], 8) != HAL_OK)
 {
 /* Error_Handler() function is called in case of error. */
 Error_Handler();
 }
 /* When Acknowledge failure occurs (Slave don't acknowledge its address)
 Master restarts communication */
 }
 while(HAL_I2C_GetError(&I2cHandle) == HAL_I2C_ERROR_AF);
 while (HAL_I2C_GetState(&I2cHandle) != HAL_I2C_STATE_READY)
 {
 }
 /* Convert register data to temperatures */
 temp = 0.125*(aRxBuffer[0]*8.0+ (aRxBuffer[1]>>5));
 thyst = 0.125*(aRxBuffer[4]*8.0+ (aRxBuffer[5]>>5));
 tos = 0.125*(aRxBuffer[6]*8.0+ (aRxBuffer[7]>>5));
 BSP_LED_Toggle(LED2);
 HAL_Delay(500);
 }
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

main.h

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H
/* Includes ------------------------------------------------------------------*/
#include 'stm32f4xx_hal.h'
#include 'stm32f4xx_nucleo.h'
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* User can use this section to tailor I2Cx/I2Cx instance used and associated
 resources */
/* Definition for I2Cx clock resources */
#define I2Cx I2C1
#define I2Cx_CLK_ENABLE() __HAL_RCC_I2C1_CLK_ENABLE()
#define I2Cx_SDA_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define I2Cx_SCL_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
#define I2Cx_FORCE_RESET() __HAL_RCC_I2C1_FORCE_RESET()
#define I2Cx_RELEASE_RESET() __HAL_RCC_I2C1_RELEASE_RESET()
/* Definition for I2Cx Pins */
#define I2Cx_SCL_PIN GPIO_PIN_8
#define I2Cx_SCL_GPIO_PORT GPIOB
#define I2Cx_SCL_AF GPIO_AF4_I2C1
#define I2Cx_SDA_PIN GPIO_PIN_9
#define I2Cx_SDA_GPIO_PORT GPIOB
#define I2Cx_SDA_AF GPIO_AF4_I2C1
/* Definition for I2Cx's NVIC */
#define I2Cx_EV_IRQn I2C1_EV_IRQn
#define I2Cx_EV_IRQHandler I2C1_EV_IRQHandler
#define I2Cx_ER_IRQn I2C1_ER_IRQn
#define I2Cx_ER_IRQHandler I2C1_ER_IRQHandler
/* Size of Transmission buffer */
#define TXBUFFERSIZE (COUNTOF(aTxBuffer) - 1)
/* Size of Reception buffer */
#define RXBUFFERSIZE TXBUFFERSIZE
/* Exported macro ------------------------------------------------------------*/
#define COUNTOF(__BUFFER__) (sizeof(__BUFFER__) / sizeof(*(__BUFFER__)))
/* Exported functions ------------------------------------------------------- */
#endif /* __MAIN_H */
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

And the files stm32f4xx_hal_msp.c and stm32f4xx_it.c have the default structure.

For those of you too lazy to look into the datasheet

temp is in address 00

conf is in address 01

hyst temp in adress 02

and overshoot temp in address 03

So the expected temperatures reported should be room temperature in temp, 75 degrees C in hysteresis temperature and 80 degrees C for shutdown temperature as the last two are the default values of these registers.

The output that I get is room temperature (varying in steps of 0.125) for all three of them.

Can someone point out why that happens?

Datasheet link

https://www.nxp.com/docs/en/data-sheet/LM75B.pdf

Juice is in Chapter 7

#hal_i2c_mem_read #stm32f4 #nucleo #stm32f4-i2c-hal-driver #lm75b
1 REPLY 1
Dimitris Paraskevopoulos
Associate III
Posted on September 17, 2017 at 06:30

Ok I just found out why that happens and it seems to be partly because I misread the datasheet and partly because the HAL_I2C_Mem_Read function API is a bit misleading.

You can only read one register at a time so you would have to break this:

HAL_I2C_Mem_Read_IT(&I2cHandle, (uint16_t)I2C_ADDRESS, 0, I2C_MEMADD_SIZE_8BIT, (uint8_t *)&aRxBuffer[0], 8)
�?�?�?

into three function calls:

HAL_I2C_Mem_Read_IT(&I2cHandle, (uint16_t)I2C_ADDRESS, 0, I2C_MEMADD_SIZE_8BIT, (uint8_t *)&aRxBuffer[0], 2)
HAL_I2C_Mem_Read_IT(&I2cHandle, (uint16_t)I2C_ADDRESS, 2, I2C_MEMADD_SIZE_8BIT, (uint8_t *)&aRxBuffer[2], 2)
HAL_I2C_Mem_Read_IT(&I2cHandle, (uint16_t)I2C_ADDRESS, 3, I2C_MEMADD_SIZE_8BIT, (uint8_t *)&aRxBuffer[4], 2)�?�?�?�?�?�?�?�?�?�?�?�?

So the size of bytes in the end IMO is a bit misleading. I was under the impression that it would read 8 bytes from address 0 which would return temp, conf, hyst, tos instead what you get is temp, temp, temp, temp.

So if you want to read multiple registers the only option is to use one function call for each register. At least that's the only obvious solution to me.

Can someone from STM propose a better one?

P.S. Another bit which I found confusing is theMemAddSize argument because it is not clear whether it means that the size is measured in bytes or bits.