cancel
Showing results for 
Search instead for 
Did you mean: 

ST MEMS L3GD20 interfacing with STM32F429ZI

AS Na
Associate II

Hello,

I need help using L3GD20 gyroscope that comes with stm32f429ZI DISC! board. I have used code in this thread as the example and this video to generate code using cube MX

/* Includes ------------------------------------------------------------------*/
#include "main.h"
 
/* Private variables ---------------------------------------------------------*/
SPI_HandleTypeDef hspi5;
 
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI5_Init(void);
 
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint8_t spiTxBuf[2], spiRxBuf[2];
int16_t x;
 
/* USER CODE END 0 */
 
/* This function enables slave select, writes one byte to SPI1,
   wait for transmission complete and deassert slave select. */
void SPI5_write(unsigned char data) {
    while (!(SPI5->SR & 2)) {}      /* wait until Transfer buffer Empty */
    SPI5->DR = data;                /* write data */
    while (SPI5->SR & 0x80) {}      /* wait for transmission done */
}
 
/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
	uint8_t x1, x2;
	
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SPI5_Init();
  /* USER CODE BEGIN 2 */
	
	// ***** Spi Transmit ***** //
	// 1. Bring slave select low
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET);
	// 2. Transmit register + data
	spiTxBuf[0] = 0x20;
	spiTxBuf[1] = 0xFF;
	HAL_SPI_Transmit(&hspi5, spiTxBuf, 2, 50);
	
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET);
	
	// 1. Bring slave select low
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET);
	// 2. Transmit register + data
	spiTxBuf[0] = 0x21;
	spiTxBuf[1] = 0x00;
	HAL_SPI_Transmit(&hspi5, spiTxBuf, 2, 50);
	
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET);
	
	// 1. Bring slave select low
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET);
	// 2. Transmit register + data
	spiTxBuf[0] = 0x24;
	spiTxBuf[1] = 0x10;
	HAL_SPI_Transmit(&hspi5, spiTxBuf, 2, 50);
	
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET);
	
	// 1. Bring slave select low
	
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET);
	// 2. Transmit register + data
	spiTxBuf[0] = 0x23;
	spiTxBuf[1] = 0x20;
	HAL_SPI_Transmit(&hspi5, spiTxBuf, 2, 50);
	SPI5_write(spiTxBuf[0]);
	SPI5_write(spiTxBuf[1]);
	
	
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET);
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		
		// 1. Bring slave select low
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET);
		// 2. Transmit register + data
		spiTxBuf[0] = 0x28 | 0x80;
		HAL_SPI_Transmit(&hspi5, spiTxBuf, 1, 50);
		// 3. Receive data
		HAL_SPI_Receive(&hspi5, &x1, 1, 50);
		// 4. Bring slave select high
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET);
		
		// 1. Bring slave select low
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET);
		// 2. Transmit register + data
		spiTxBuf[0] = 0x29 | 0x80;
		HAL_SPI_Transmit(&hspi5, spiTxBuf, 1, 50);
		// 3. Receive data
		HAL_SPI_Receive(&hspi5, &x2, 1, 50);
		// 4. Bring slave select high
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET);
		
		//x = ((int16_t)x1 | (x2 << 8));
		
		x = (int16_t)x2;
		x = x << 8;
		x |= (int16_t)x1;
		
		HAL_Delay(500);
		
	}
}
 
/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
 
  /**Configure the main internal regulator output voltage 
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
  /**Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  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_HSI;
  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();
  }
}
 
/**
  * @brief SPI5 Initialization Function
  * @param None
  * @retval None
  */
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_32;
  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 */
 
}
 
/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
 
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOF_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
 
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET);
 
  /*Configure GPIO pin : PC1 */
  GPIO_InitStruct.Pin = GPIO_PIN_1;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
 
  /*Configure GPIO pin : PA2 */
  GPIO_InitStruct.Pin = GPIO_PIN_2;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
  /* EXTI interrupt init*/
  HAL_NVIC_SetPriority(EXTI2_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(EXTI2_IRQn);
 
}
 
/* USER CODE BEGIN 4 */
 
/* USER CODE END 4 */
 
/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
 
  /* USER CODE END Error_Handler_Debug */
}
 
#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{ 
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

Can some one help me figure out the issue?

4 REPLIES 4
Eleon BORLINI
ST Employee

hi, maybe I did't catch the issue... are you saying that this code is not working properly? If you are using a STM32F429I-DISC1 Discovery Kit, I suggest you to download the related project of the STM32CubeF4, select the STM32F429I-Discovery and start from SPI example you can initialize SPI5 and define data transmission through this buffer declared in the main

/* Buffer used for transmission */

uint8_t aTxBuffer[] = "****SPI - Two Boards communication based on Polling **** SPI Message ******** SPI Message ******** SPI Message ****";

AS Na
Associate II

Thanks for the reply

Yeah this code is not working.

I already have cube MX. and I generated start code (like configuring SPI5, Clock and GPIO) done using CubeMX. I am new to st micro controllers(only have some experience with AVR). I don't wanna use L3GD20 driver that come with example project. Because I wanna know how to use the Sensor only by using HAL API to send and receive data, that way I will get an idea to use other sensors that doesn't have library.

Is there anything wrong with the code?

This is the thread & video that I used as reference

In the thread it says that, sensor X, Y & Z values are two's compliment, so they are not unsigned. But HAL_SPI_Receive() function stores data in uint8_t * .

How to get signed data using HAL??

I have downloaded example code for my board from here, but I think they use Standard Peripheral Libraries. The link you provided, they use HAL??

Eleon BORLINI
ST Employee

for my understanding, is the code not compiling or is not reading the correct values from the sensor? In this second case, can you check the WHO_AM_I register (0Fh) value D4h and/or share the oscilloscope screenshot? thanks

AS Na
Associate II

Code is compiling but not reading value from the sensor.

I have used the example code for my board downloaded from here, and it works. So sensor is okay

I don't have a oscilloscope, but i have captured the value of x and WHO_AM_I register using STMStudio

Here's main part of my code, not modified any other part of code

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
	uint8_t x1, x2;
	
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SPI5_Init();
  /* USER CODE BEGIN 2 */
	
	// ***** Spi Transmit ***** //
	// 1. Bring slave select low
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET);
	// 2. Transmit register + data
	spiTxBuf[0] = 0x20;
	spiTxBuf[1] = 0xFF;
	HAL_SPI_Transmit(&hspi5, spiTxBuf, 2, 50);
	// 3. Bring slave select high
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET);
	
	// 1. Bring slave select low
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET);
	// 2. Transmit register + data
	spiTxBuf[0] = 0x21;
	spiTxBuf[1] = 0x00;
	HAL_SPI_Transmit(&hspi5, spiTxBuf, 2, 50);
	// 3. Bring slave select high
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET);
	
	// 1. Bring slave select low
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET);
	// 2. Transmit register + data
	spiTxBuf[0] = 0x24;
	spiTxBuf[1] = 0x10;
	HAL_SPI_Transmit(&hspi5, spiTxBuf, 2, 50);
	// 3. Bring slave select high
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET);
	
	// 1. Bring slave select low
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET);
	// 2. Transmit register + data
	spiTxBuf[0] = 0x23;
	spiTxBuf[1] = 0x20;
	HAL_SPI_Transmit(&hspi5, spiTxBuf, 2, 50);
	// 3. Bring slave select high
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET);
	
	
	// *** Code to read WHO_AM_I register *** //
		
		// 1. Bring slave select low
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET);
		// 2. Transmit register + data
		spiTxBuf[0] = 0x0F | 0x80;
		HAL_SPI_Transmit(&hspi5, spiTxBuf, 1, 50);
		// 3. Receive data
		HAL_SPI_Receive(&hspi5, &who_am_i, 1, 50);
		// 4. Bring slave select high
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET);
		
		
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		// 1. Bring slave select low
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET);
		// 2. Transmit register + data
		spiTxBuf[0] = 0x28 | 0x80;
		HAL_SPI_Transmit(&hspi5, spiTxBuf, 1, 50);
		// 3. Receive data
		HAL_SPI_Receive(&hspi5, &x1, 1, 50);
		// 4. Bring slave select high
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET);
		
		// 1. Bring slave select low
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET);
		// 2. Transmit register + data
		spiTxBuf[0] = 0x29 | 0x80;
		HAL_SPI_Transmit(&hspi5, spiTxBuf, 1, 50);
		// 3. Receive data
		HAL_SPI_Receive(&hspi5, &x2, 1, 50);
		// 4. Bring slave select high
		HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET);
		
		//x = ((int16_t)x1 | (x2 << 8));
		
		x = (int16_t)x2;
		x = x << 8;
		x |= (int16_t)x1;
		
		HAL_Delay(500);
	}
}

who_am_i is a uint8_t variable declared globally and the value I got from STM studio is 212(0xD4) comparing with data sheet it's the correct value. right??

0690X0000087v17QAA.png

But one thing I noticed is, value of x is changing after every reset.

Following are the screen shots of value of x after each reset (Board is not moved)

0690X0000087v2ZQAQ.png

0690X0000087v2jQAA.png

Screenshot after moving the board and resetting it0690X0000087v3DQAQ.png

After reset even if I move the board, value is not changing

Are these the proper values given to the registers of L3GD20

addr value

0x20 ===> 0xFF

0x21 ===> 0x00

0x24 ===> 0x10

0x23 ===> 0x20

When generating code using cube MX, I have used HSI as clock source and all peripherals are running at 16 MHz. Would this cause any issue?

0690X0000087v6lQAA.png

0690X0000087v7FQAQ.png

 Please see this thread too, I have used his code too, but not working

Thanks