0
votes

I am trying to read accelerometer data over i2c. The i2c address of the accelerometer is 0x19 for reading and 0x18 for writing. To check for correct communication with the accelerometer, I should read register 0x00 and it must return 0x12 as the result. But I am not able to get acknowledgement from the accelerometer. I am using the HAL libraries and code generated using CubeMX. Here is the code:

#include "main.h"
#include "stm32l0xx_hal.h"

I2C_HandleTypeDef hi2c1;

void SystemClock_Config(void);
void Error_Handler(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);


uint8_t data[2];
uint8_t result;


int main(void)
{
    HAL_Init();

    /* Configure the system clock */
    SystemClock_Config();

    /* Initialize all configured peripherals */
    MX_GPIO_Init();
    MX_I2C1_Init();

    while (1)
    {

          //    HAL_I2C_Mem_Read_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
                HAL_I2C_Mem_Read_DMA(&hi2c1, 0x19, 0x00, 1, &result, 1);
                HAL_Delay(100);
     }
}

 void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_PeriphCLKInitTypeDef PeriphClkInit;

  /**Configure the main internal regulator output voltage  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

   /**Initializes the CPU, AHB and APB busses clocks  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
  RCC_OscInitStruct.MSIState = RCC_MSI_ON;
  RCC_OscInitStruct.MSICalibrationValue = 0;
  RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_5;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

    /**Initializes the CPU, AHB and APB busses clocks */

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                          |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }

  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_I2C1;
  PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
     Error_Handler();
  }

  /**Configure the Systick interrupt time   */
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

   /**Configure the Systick    */
   HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
   HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/* I2C1 init function */
static void MX_I2C1_Init(void)
{

   hi2c1.Instance = I2C1;
   hi2c1.Init.Timing = 0x00000708;
   hi2c1.Init.OwnAddress1 = 0x18;
   hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
   hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
   hi2c1.Init.OwnAddress2 = 0;
   hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
   hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
   hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
   if (HAL_I2C_Init(&hi2c1) != HAL_OK)
   {
     Error_Handler();
   }

     /**Configure Analogue filter  */
   if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
   {
     Error_Handler();
   }

 }

 static void MX_GPIO_Init(void)
 {

   /* GPIO Ports Clock Enable */
   __HAL_RCC_GPIOC_CLK_ENABLE();
   __HAL_RCC_GPIOA_CLK_ENABLE();

 }

2 external pull up resistors of 4,7kOhms are used.

mc pins: https://developer.mbed.org/platforms/ST-Nucleo-L011K4/

pins D4 and D5 to SDA and SCL respectively. GND and 3.3V are connected to accelerometers respective power connections.

1
You do not have to set the R/W bit at the end of the address field manually, HAL handles it for you. So the address is 0x18 shift it to left by one and as the top 7 bit is the address, the first bit (bit 0.) will be set to 1 by the HAL read function. HAL_I2C_Mem_Read_DMA(&hi2c1, ((0x18)<<1), 0x00, 1, &result, 1);Bence Kaulics
Thank you for your reply. I tried changing the device address to ((0x18)<<1). I still get acknowledgement failure error code.nayak
In the MX_I2C1_Init the following line is wrong I think: hi2c1.Init.OwnAddress1 = 0x18;. The 0x18 is the slave address, the accelerometer's address do not set the MCU's own address to it. You can set it to 0 instead. Probably this is not the root cause.Bence Kaulics
Also I can't see the DMA initialization in your code but you are using HAL_I2C_Mem_Read_DMA function. You should give it a try first using HAL_I2C_Mem_Read.Bence Kaulics
Thank you once again. I tried both of your suggestions, changing hi2c1.Init.OwnAddress1 to 0 and using HAL_I2C_Mem_Read. I still get acknowledgement failure.nayak

1 Answers

0
votes

The SDA pin of board is PB7 and SCL pin is PB6. However, you don't initialize these pins clock. You should enable port B clock in MX_GPIO_Init function.

static void MX_GPIO_Init(void)
 {

   /* GPIO Ports Clock Enable */
   __HAL_RCC_GPIOC_CLK_ENABLE();
   __HAL_RCC_GPIOA_CLK_ENABLE();
   __HAL_RCC_GPIOB_CLK_ENABLE();

 }

You should set OwnAddress1 to 0 in MX_I2C1_Init function.

hi2c1.Init.OwnAddress1 = 0;

Also read address should be 0x18 in HAL_I2C_Mem_Read_DMA or HAL_I2C_Mem_Read function. I am not sure Timing is correct. Most of I2C devices clock speed is between 100-400Khz. What is your I2C device clock speed? You can try at 100 or 400Khz.

hi2c1.Init.Timing = 400000;