cancel
Showing results for 
Search instead for 
Did you mean: 

Getting wrong register value when reading "WHO_AM_I" register on I3G2450D mems. (STM32F429ZIT)

Fatih
Associate II

I'm using the following driver: STMems_Standard_C_drivers/i3g4250d_STdC at master · STMicroelectronics/STMems_Standard_C_drivers (github.com)

You can ignore the details of the driver code but the important thing to note is that

The driver requires you to write your own "platform_read" function since this is platform dependent.

I am using SPI and this is how my implementation looks like:

static int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp, uint16_t len)
{
  uint32_t msTimeOut = 1000;
  reg |= 0x80;
  //I3G2450D_CS_ENABLE;
  HAL_GPIO_WritePin(MEMS_CS_GPIO_Port, MEMS_CS_Pin, GPIO_PIN_RESET);
  HAL_SPI_Transmit(handle, &reg, 1, msTimeOut);
  HAL_SPI_Receive(handle, bufp, len, msTimeOut);
  //I3G2450D_CS_DISABLE;
  HAL_GPIO_WritePin(MEMS_CS_GPIO_Port, MEMS_CS_Pin, GPIO_PIN_SET);
 
  return 0;
}

When using this function to read the "WHO_AM_I" register (Address: 0x0FU) I am supposed to get the hex value "0xD3U" (Decimal: 211) but the function call sets the wrong value in "bufp". I get hex "0xd4", following is a screenshot from a debugging session:

 0693W000005AknEQAS.png"whoamI" is the value that gets sets from reading the register and "I3G240D_ID" is the expected value.

In binary the expected value is: 11010011, this is correct according to manual of the gyroscope, but what I get is: 11010100.

My SPI init:

static void MX_SPI5_Init(void)
{
 
  /* USER CODE BEGIN SPI5_Init 0 */
 
  /* USER CODE END SPI5_Init 0 */
 
  /* USER CODE BEGIN SPI5_Init 1 */
 
  /* USER CODE END SPI5_Init 1 */
  /* SPI5 parameter configuration*/
  hspi5.Instance = SPI5;
  hspi5.Init.Mode = SPI_MODE_MASTER;
  hspi5.Init.Direction = SPI_DIRECTION_2LINES;
  hspi5.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi5.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi5.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi5.Init.NSS = SPI_NSS_SOFT;
  hspi5.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
  hspi5.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi5.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi5.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi5.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi5) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI5_Init 2 */
 
  /* USER CODE END SPI5_Init 2 */
 
}

What I have tried (without success):

  • Changing the baud rate prescaler.
  • Changing first bit from MSB to LSB. (manual says data is sent MSB first but I thought trying was worth it.)
  • changing CPOL to "High"
  • changing CPHA to "2 Edges" (note when I change this in combination with CPOL I get different results (decimal 255) but still not the correct one)
  • double checked Chip Select line (according to manual PC1 is the correct CS line for the I3G2450D)
  • set a delay after setting CS line to high/low
  • set a delay before/after reading with SPI_Transmit / SPI_Recieve

I'm out of options as to what the problem could be (other than hardware related), google suggests trying the same things I did above so maybe someone with more experience knows a solution.

Regards,

Fatih

1 ACCEPTED SOLUTION

Accepted Solutions

Hi @Fatih​ ,

well, I believe I found the issue...

The fact is that on the STM32F429 the mounted device is the L3GD20 instead of I3G4250D, for which the WHO_AM_I is 0xD4.

You can see it by considering the software package related to this hardware platform, the STSW-STM32138. In the folder Utilities\STM32F429I-Discovery, you can see that in the stm32f429i_discovery_l3gd20.h is declared the following:

#define I_AM_L3GD20		    ((uint8_t)0xD4)

So I suggest you to use this code as starting point, instead of the C libraries on Github.

If it solved the issue, please mark this answer as Best answer so that t can be useful for future users.

-Eleon

View solution in original post

9 REPLIES 9
Eleon BORLINI
ST Employee

Hi @Fatih​ ,

yes, the WHO_AM_I value for the I3G2450D product should be 0xD3, not 0xD4...

My question are:

  • Did you test a single device or also other devices?
  • Regardless the WHO_AM_I response value, were you able to read/write other registers?

-Eleon

Hello Eleon thanks for the response,

On your questions:

  • No other Peripherals are connected to the MCU.
  • I have not tested it on another MCU since I do not have access to a 2nd STM32F429ZI.
  • When I try to read other registers like the I3G4250D_OUT_X_L I get random values that do not change in accordance with the device changing angle/moving.
  • I have not yet tried setting specific register values and then reading them to verify the reading/writing process. I will do that next, thanks for the tip.

Hi @Fatih,

And do you have the possibility to try another I3G4250D?

You can also send me a picture of the top marking of the device package, in order to understand if it is actually a I3G4250D device or something else.

By the way, before reading the output registers, it is however required to write some configuration registers and wait the proper timings, as described in i3g4250d_read_data_polling.c and in the datasheet.

-Eleon​ 

Hi @Eleon BORLINI​ ,

I also do not have access to another mems unit, I'm using the I3G4250D built into the STM32F429ZI (STM32F4-DISC1).

Here is a picture of the board 'm using:0693W000005B2GNQA0.jpgI have also succesfully set and read other registers:

  i3g4250d_data_rate_set(&dev_ctx, I3G4250D_ODR_800Hz);
 
  HAL_Delay(1000);
  i3g4250d_dr_t test_value;
  i3g4250d_data_rate_get(&dev_ctx, &test_value);

the value of "test_value" succesfully becomes "I3G4250D_ODR_800Hz". So setting/reading other registers works fine it seems.

Do you have any other idea what the problem might be?

Hi @Fatih​ ,

well, I believe I found the issue...

The fact is that on the STM32F429 the mounted device is the L3GD20 instead of I3G4250D, for which the WHO_AM_I is 0xD4.

You can see it by considering the software package related to this hardware platform, the STSW-STM32138. In the folder Utilities\STM32F429I-Discovery, you can see that in the stm32f429i_discovery_l3gd20.h is declared the following:

#define I_AM_L3GD20		    ((uint8_t)0xD4)

So I suggest you to use this code as starting point, instead of the C libraries on Github.

If it solved the issue, please mark this answer as Best answer so that t can be useful for future users.

-Eleon

Hi @Eleon BORLINI​ ,

Thanks a lot, this clarifies everything. But before I continue development I have one last question;

The manual of the STm32F429i says that the MEMS unit being used is a I34250D : Discovery kit with STM32F429ZI MCU - User manual (chapter 6.8)

Did I refer to the wrong manual? or is it a mistake in the manual.

Thanks in advance.

No it is the correct manual, but checking the 7.2 Board revision history chapter p.30 you can see that from Revision MB1075 - E01 there is a change:

>> U3: L3GD20 replaced by I3G4250D and R75, C54 added

Maybe the board you have is from another version, the B01 or the C01 (it looks "C" version from your picture, from MB1075C marking)

-Eleon

Thanks for clarifying everything @Eleon BORLINI​ . I am new to the ST eco system/community so I and many others appreciate the help a lot.

Regards,

Fatih

Thank you for the appreciation Fatih!

-Eleon