How do I use the STM32CUBEF4 HAL library to read out the sensor data with i2c?

36,364

First, I would advise you to use STMCube. It will set up the clock and the I2C bus for you.

It is very good practice to check what the HAL functions return. If you don't have HAL_OK, something went wrong.

Try at 100KHz first, and then increase to 400KHz.

The I2C address of the device is 0x18 (if SDO is grounded, which I assume it is). But in the HAL driver, you have to define:

#‎define‬ I2C_ADDRESS (0x18<<1)

What you want to do is to read a register, so don't use HAL_I2C_Master_Receive or HAL_I2C_Master_Transmit, but HAL_I2C_Mem_Read or HAL_I2C_Mem_Write, like this:

#define REG_CHIP_ID 0x00
HAL_I2C_Mem_Read(&I2cHandle, I2C_ADDRESS, REG_CHIP_ID, I2C_MEMADD_SIZE_8BIT, &aRxBuffer, 1, 10000);

Also, note that the HAL takes care of the R/W bit of the address, so you don't need to do:

I2C_ADDRESS|0x01
Share:
36,364
elecbuggy
Author by

elecbuggy

Updated on December 06, 2020

Comments

  • elecbuggy
    elecbuggy over 3 years

    I want to use the latest HAL library instead of Standard Peripheral Library.

    And i want to readout the BMA250E G-sensor's chip_id, but it doesn't work.

    Value of aRxBuffer always keep at 0x00. But it should be 0xf9!

    What's wrong in my code?

    ‪#‎include‬ "stm32f4xx_hal.h" 
    
    #define I2Cx_SDA_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
    #define I2Cx_SDA_PIN GPIO_PIN_9
    #define I2Cx_SDA_GPIO_PORT GPIOB
    #define I2Cx_SDA_AF GPIO_AF4_I2C1
    
    #define I2Cx_SCL_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
    #define I2Cx_SCL_PIN GPIO_PIN_6
    #define I2Cx_SCL_GPIO_PORT GPIOB
    #define I2Cx_SCL_AF GPIO_AF4_I2C1
    
    #define I2Cx_CLK_ENABLE() __HAL_RCC_I2C1_CLK_ENABLE()
    #define I2Cx_FORCE_RESET() __HAL_RCC_I2C1_FORCE_RESET()
    #define I2Cx_RELEASE_RESET() __HAL_RCC_I2C1_RELEASE_RESET() 
    
    ‪#‎define‬ I2C_ADDRESS 0x18 
    
    static void SystemClock_Config(void); 
    
    uint8_t aTxBuffer[2],aRxBuffer; 
    
    int main()
    { 
        HAL_Init(); 
        SystemClock_Config(); 
        I2C_HandleTypeDef I2cHandle;
    
        I2cHandle.Instance = I2C1;
        I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
        I2cHandle.Init.ClockSpeed = 400000;
        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 = 0; 
    
        HAL_I2C_Init(&I2cHandle); 
    
        aTxBuffer[0]=0x00;
        HAL_I2C_Master_Transmit(&I2cHandle, I2C_ADDRESS,aTxBuffer, 1, 10000);  
        HAL_I2C_Master_Receive(&I2cHandle,I2C_ADDRESS|0x01 ,&aRxBuffer, 1, 10000);  
        HAL_Delay(1000);
    } 
    
    static void SystemClock_Config(void) 
    { 
        RCC_ClkInitTypeDef RCC_ClkInitStruct;
        RCC_OscInitTypeDef RCC_OscInitStruct;
    
        __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
        RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; 
        RCC_OscInitStruct.HSEState = RCC_HSE_ON; 
        RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; 
        RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
        RCC_OscInitStruct.PLL.PLLM = 8; 
        RCC_OscInitStruct.PLL.PLLN = 360;
        RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; 
        RCC_OscInitStruct.PLL.PLLQ = 7; 
        HAL_RCC_OscConfig(&RCC_OscInitStruct); 
        RCC_ClkInitStruct.ClockType = 
            (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | 
             RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
        RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; 
        RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; 
        RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;         
        RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; 
        HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5); 
    }
    
    void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c) 
    {
        GPIO_InitTypeDef GPIO_InitStruct; 
    
        I2Cx_SCL_GPIO_CLK_ENABLE(); 
        I2Cx_SDA_GPIO_CLK_ENABLE(); 
    
        GPIO_InitStruct.Pin = I2Cx_SCL_PIN;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
        GPIO_InitStruct.Pull = GPIO_PULLUP; 
        GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
        GPIO_InitStruct.Alternate = I2Cx_SCL_AF; 
        HAL_GPIO_Init(I2Cx_SCL_GPIO_PORT, &GPIO_InitStruct);
    
        GPIO_InitStruct.Pin = I2Cx_SDA_PIN; 
        GPIO_InitStruct.Alternate = I2Cx_SDA_AF; 
        HAL_GPIO_Init(I2Cx_SDA_GPIO_PORT, &GPIO_InitStruct);
    } 
    
    void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c) 
    {  
        I2Cx_FORCE_RESET(); 
        I2Cx_RELEASE_RESET();  
        HAL_GPIO_DeInit(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_PIN);
        HAL_GPIO_DeInit(I2Cx_SDA_GPIO_PORT, I2Cx_SDA_PIN); 
    }
    
    • imbearr
      imbearr almost 8 years
      First: fromat your code - it is unreadable now. Second: if you use HAL - you must check returned HAL status value always.
    • imbearr
      imbearr almost 8 years
      So have you tried my second advice? What value returned when you call HAL_I2C_Init, HAL_I2C_Master_Transmit, HAL_I2C_Master_Receive functions, are it everytime equal HAL_OK?
    • elecbuggy
      elecbuggy almost 8 years
      thank you very much
  • Alaa M.
    Alaa M. almost 7 years
    What's the difference between HAL_I2C_Master_Receive/HAL_I2C_Master_Transmit and HAL_I2C_Mem_Read/HAL_I2C_Mem_Write?
  • Guillaume Michel
    Guillaume Michel almost 7 years
    HAL_I2C_Master_Receive performs a I2C read operation of N bytes (start, I2C address + Read, N bytes, stop). HAL_I2C_Master_Transmit performs a I2C write operation of N bytes (start, I2C address + Write, N bytes, stop).
  • Guillaume Michel
    Guillaume Michel almost 7 years
    HAL_I2C_Mem_Read performs a I2C write operation to select the memory address to read and then reads N bytes (start, I2C address + Write, Memory address, repeated start, I2C address + Read, N bytes, stop) HAL_I2C_Mem_Write performs a I2C write operation to select the memory address to read and then writes N bytes (start, I2C address + Write, Memory address, repeated start, I2C address + Write, N bytes, stop)
  • tarabyte
    tarabyte over 5 years
    HAL_I2C_Mem_Read saved the day. HAL_I2C_Master_Receive was definitely the reason for failure. I wish I understood the nuance between them better.