cancel
Showing results for 
Search instead for 
Did you mean: 

(SOLVED) SPI communication problem with sensors

irene
Associate II

I'm using STEVAL-STWINKT1 (MCU STM32L4R9ZIJ6) and I'm trying to communicate with the motion sensors (ISM330DHCX, IIS3DWB, IIS2DH) by SPI3 interface (polling). I wrote a code very similar to that one present in the "Serial_DataLog" project, using HALs (I'm using STM32CubeIDE and STM32CubeMX generated code). I'm trying to get the WHO_AM_I value from register address 0x0F, but my code gives me cyclically a wrong value every time I call this function.

Here it is my code:

- in main.c

static void MX_SPI3_Init(void)
{
 
  /* USER CODE BEGIN SPI3_Init 0 */
 
  /* USER CODE END SPI3_Init 0 */
 
  /* USER CODE BEGIN SPI3_Init 1 */
 
  /* USER CODE END SPI3_Init 1 */
  /* SPI3 parameter configuration*/
  hspi3.Instance = SPI3;
  hspi3.Init.Mode = SPI_MODE_MASTER;
  hspi3.Init.Direction = SPI_DIRECTION_2LINES;
  hspi3.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi3.Init.CLKPolarity = SPI_POLARITY_HIGH;
  hspi3.Init.CLKPhase = SPI_PHASE_2EDGE;
  hspi3.Init.NSS = SPI_NSS_SOFT;
  hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
  hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi3.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi3.Init.CRCPolynomial = 7;
  hspi3.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
  hspi3.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
  if (HAL_SPI_Init(&hspi3) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI3_Init 2 */
  __HAL_SPI_ENABLE(&hspi3);
  /* USER CODE END SPI3_Init 2 */
 
}

- in sensor_bsp.c

#include "stm32l4xx_hal.h"
#include "vibro.h"
#include "main.h"
#include "stm32l4xx_hal_spi.h"
 
extern SPI_HandleTypeDef hspi3;
 
/*  #define + typedef */
#define TIMEOUT_DURATION			1000u				
#define VIBRO_CS_GPIO_CLK_ENABLE()	__GPIOF_CLK_ENABLE()
GPIO_InitTypeDef  GPIO_InitStruct;
 
#define SPI3_SIZE	SPI_DATASIZE_8BIT
 
/* register addresses */
#define VIBRO_SENSE_REG_MANID 	0x0Fu
 
/*  private functions */
static HAL_StatusTypeDef VIBRO_SPI3_Send(uint8_t *pdata, uint16_t len);
static HAL_StatusTypeDef VIBRO_SPI3_Receive(uint8_t *pdata, uint16_t len);
static HAL_StatusTypeDef VIBRO_SPI3_ReadReg(uint16_t Reg, uint8_t *pdata, uint16_t len);
 
/* public functions (impl) */
void VIBRO_Init(void)
{
       /* Peripheral clock enable */
	__HAL_RCC_SPI3_CLK_ENABLE();
	/**SPI3 GPIO Configuration
	PB4 (NJTRST)  		 ------> SPI3_MISO
	PB5    				 ------> SPI3_MOSI
	PB3 (JTDO/TRACESWO)  ------> SPI3_SCK
	*/
	GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_3;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	GPIO_InitStruct.Alternate = GPIO_AF6_SPI3;
	HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
			
	__GPIOF_CLK_ENABLE();
	GPIO_InitStruct.Pin = CS_ADWB_Pin;
	HAL_GPIO_Init(CS_ADWB_GPIO_Port, &GPIO_InitStruct);
	
	/* Configure ISM330DHC pin */
	HAL_GPIO_WritePin(CS_DHC_GPIO_Port, CS_DHC_Pin, GPIO_PIN_SET);  
}
 
 
HAL_StatusTypeDef VIBRO_ReadManID(uint8_t* manId)
{
	return VIBRO_SPI3_ReadReg(VIBRO_SENSE_REG_MANID, manId, 0x01u);
}
 
/*  private functions (impl) */
static HAL_StatusTypeDef VIBRO_SPI3_Send(uint8_t* pdata, uint16_t len)
{
	return HAL_SPI_Transmit(&hspi3, pdata, len, TIMEOUT_DURATION);
}
 
static HAL_StatusTypeDef VIBRO_SPI3_Receive(uint8_t* pdata, uint16_t len)
{
	return HAL_SPI_Receive(&hspi3, pdata, len, TIMEOUT_DURATION);
}
 
 
static HAL_StatusTypeDef VIBRO_SPI3_ReadReg(uint16_t Reg, uint8_t* pdata, uint16_t len)
{
	uint8_t dataReg = (uint8_t)Reg;
	dataReg |= 0x80U;
	
	HAL_StatusTypeDef retval = HAL_OK;
 
	/* 1 select slave */
	HAL_GPIO_WritePin(CS_DHC_GPIO_Port, CS_DHC_Pin, GPIO_PIN_RESET);
 
	/* 2 do transaction */
	  if (VIBRO_SPI3_Send(&dataReg, 1) != HAL_OK)
	  {
		retval = HAL_ERROR;
	  }
 
	  if (VIBRO_SPI3_Receive(pdata, len) != HAL_OK)
	  {
		retval = HAL_ERROR;
	  }
	/* 3 de-select slave */
	HAL_GPIO_WritePin(CS_DHC_GPIO_Port, CS_DHC_Pin, GPIO_PIN_SET);
 
	return retval;
}

I tried also with a different SPI3 initialization CLK polarity and phase, but the result is the same as before:

 hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;

 hspi3.Init.CLKPhase = SPI_PHASE_1EDGE;

What's the problem?

P.S.: I don't really understand the command dataReg |= 0x80U. I looked up at the sensor datasheet and I didn't find this info: where'd that come from?

P.P.S.: I checked the pinout and it's correct.

1 ACCEPTED SOLUTION

Accepted Solutions

Bit7 is NOT for multi-read but for READ. Multibyte is bit6, The target device does not know if you are reading or writing its register without setting bit7 appropriately. The SPI interface and bits are described in detail in the datasheets.

I believe your initial code polarity and phase are right but check with an oscillscope. Perhaps add some additional debug messages throughout the code to solve this issue. The general concept looks correct.

View solution in original post

7 REPLIES 7
S.Ma
Principal

The 0x80 (bit 7 set) is usually for multi-byte read/write: If the bit is set, you read registers in incremental address. Otherwise, you keep reading the same register (for example waiting for a flag to be set).

S.Ma
Principal

Some mems in SPI mode boot in 4 wire, others in 3 wire mode.

irene
Associate II

Understood. After a deep reading of the sensors datasheets I found the point "bit 0: READ bit. The value is 1.", that corresponds to 80h.

irene
Associate II

And so, according to my problem, what's the point?

Bit7 is NOT for multi-read but for READ. Multibyte is bit6, The target device does not know if you are reading or writing its register without setting bit7 appropriately. The SPI interface and bits are described in detail in the datasheets.

I believe your initial code polarity and phase are right but check with an oscillscope. Perhaps add some additional debug messages throughout the code to solve this issue. The general concept looks correct.

Thank you for the oscilloscope suggestion, it was very useful: I noticed that the problem was the Chip Select management. Hence I modified the GPIO initialization of the CS pin and then it worked:

/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOF, CS_ADWB_Pin|CS_DHC_Pin, GPIO_PIN_SET);
 
/*Configure GPIO pins : CS_ADWB_Pin CS_DHC_Pin */
GPIO_InitStruct.Pin = CS_ADWB_Pin|CS_DHC_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

sema11111
Associate

Hello, I'm also using the IIS2DH sensor, and I'm getting the same error you're getting. Can you share your code? Thank you.