cancel
Showing results for 
Search instead for 
Did you mean: 

Problem with SPI Communication - Nucleo U575ZI-Q/STEVAL-MKI168V1

N_A_S
Associate II

Hello everyone. I am currently learning by working on a project in which I have to establish a SPI communication between a Nucleo U575ZI-Q and a STEVAL-MKI168V1 (IIS2DH eval board). To set up the Nucleo board and its peripherals, I used the STM32CubeIDE interface. First, I set the HSE to crystal/ceramic Resonator (this will be the source of the SYSCLK through the PLLCLK). Using the APB3 Prescaler, I configured the APB3 peripheral clocks to 10 MHz (in the tests shown below, this was set to 5MHz using the AHB Prescaler). Then, in the SPI3 Clock MUX source selection, the PCLK3 is selected.

N_A_S_0-1719844677021.jpeg

N_A_S_1-1719844698012.jpeg

N_A_S_2-1719844752019.jpeg

 

The IIS2DH uses a High clock polarity and data is captured on the rising edge of the SCL.

N_A_S_3-1719844838321.jpeg

In the SPI3 tab, the mode was set to Full-Duplex Master. The data size is set to 8 bits and the first bit is the MSB. I believe the baud rate sets the frequency for SPC pin, but changing it didn’t seem to have any effect on the code output (I tried them all). The clock polarity (CPOL) was set to High and the clock phase (CPHA) was set to 2 Edge.

N_A_S_4-1719845046077.jpeg

The pins used are as followed: PC9 – IIS2DH_CS (Set as GPIO Output), PC10 – SPI3_SCK, PC11 – SPI3_MISO, PC12 – SPI3_MOSI.

N_A_S_5-1719845094337.jpeg

The problem I am currently facing is that I can rarely communicate with
consistency. I used the HAL_SPI_Transmit and HAL_SPI_Receive to write some functions
to control the Nucleo to communicate with the accelerometer. The codes are:


/* USER CODE BEGIN PTD */
uint8_t iddata[1];
uint8_t deviceid = 0;
/* USER CODE END PTD */


/* USER CODE BEGIN 0 */
void SPI_write (uint8_t address, uint8_t value)
{
  uint8_t data[2];
  data[0] = address;
  data[1] = value;
  HAL_GPIO_WritePin (GPIOC, GPIO_PIN_9, GPIO_PIN_RESET);
  HAL_SPI_Transmit(&hspi3, data, 2, 100);
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_SET);
}

void ID_read (uint8_t address,uint8_t bytes)
{
  address |= 0x80; //Read bit
  if (bytes > 1)
  {
  address |= 0x40; //Multibyte bit
  }
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_RESET);
    HAL_SPI_Transmit(&hspi3, &address, 1, 100);
    HAL_SPI_Receive (&hspi3, iddata, bytes, 100);
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_SET);
  }


void IIS2DH_init (void)
{
  HAL_Delay(100);
  SPI_write (0x20, 0x19); //(CTRL_REG1) ODR and axis selection and LP or Normal mode
  HAL_Delay(100);
  SPI_write (0x23, 0x00); //(CTRL_REG4) Select range, SPI 3 or 4-wire
  modes and HR or Normal mode
  HAL_Delay(100);
}
/* USER CODE END 0 */

/* USER CODE BEGIN 2 */
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_SET);
IIS2DH_init();
/* USER CODE END 2 */

/* USER CODE BEGIN WHILE */
while (1)
{
  //Get device ID
  ID_read(0x0F, 1);
  deviceid = iddata[0];
  HAL_Delay(10);
/* USER CODE END WHILE */

 

/* SPI3 parameter configuration*/


>>>>>>>>>>>>>>(I didn’t edit below here)<<<<<<<<<<<<<


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_2;
hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi3.Init.TIMode = SPI_TIMODE_DISABLE;
hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi3.Init.CRCPolynomial = 0x7;
hspi3.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
hspi3.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;
hspi3.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;
hspi3.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;
hspi3.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;
hspi3.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;
hspi3.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;
hspi3.Init.IOSwap = SPI_IO_SWAP_DISABLE;
hspi3.Init.ReadyMasterManagement = SPI_RDY_MASTER_MANAGEMENT_INTERNALLY;
hspi3.Init.ReadyPolarity = SPI_RDY_POLARITY_HIGH;


if (HAL_SPI_Init(&hspi3) != HAL_OK)
{
  Error_Handler();
}
HAL_SPI_AutonomousMode_Cfg_Struct.TriggerState = SPI_AUTO_MODE_DISABLE;
HAL_SPI_AutonomousMode_Cfg_Struct.TriggerSelection = SPI_GRP2_LPDMA_CH0_TCF_TRG;
HAL_SPI_AutonomousMode_Cfg_Struct.TriggerPolarity = SPI_TRIG_POLARITY_RISING;


if (HAL_SPIEx_SetConfigAutonomousMode(&hspi3, &HAL_SPI_AutonomousMode_Cfg_Struct) != HAL_OK)
{
    Error_Handler();
}
/* USER CODE BEGIN SPI3_Init 2 */

To confirm that the accelerometer was working, I wrote a code for an ESP32 with the
SPI.h library in the Arduino IDE, so its not any advanced coding. Using this configuration I
could read the ID with stability and also all 3 axis.

 

ESP32 ID Reading at 1 MHz

N_A_S_7-1719845835931.png

 

The signal is very disrupted at high frequencies, but it still managed to get a stable reading (at 10 MHz).

With the Nucleo board, I used lower frequencies to avoid miscommunication between the two components. It is clear that the Nucleo is interpreting the code correctly and sending the correct sequence of signals to the accelerometer. However, in this case, the accelerometer isn’t sending back any data. I do see some errors with the signals, such as spikes in the signals with each rise/fall of the SCL line and the slow decay of the clock after communication is complete (which I would also like to fix), but I can’t see why the accelerometer isn’t answering back in this case.

ID Reading at 5MHz/128 baud rate prescaler with Nucleo U575ZI-Q.

N_A_S_10-1719846788312.png

Slow decay of the SCL line

N_A_S_13-1719846900520.jpeg

These tests were done on two completely different sets of Nucleo U575ZI-Q and STEVAL-MKI168V1 and the results were the same. Vcc pins are connected to the 3v3 socket and the GND, INT1 and INT2 pins are connected to the GND socket on the Nucleo board, both on the CN8 ZIO connector.

Is there some configuration error that I am doing? Why can the ESP32 communicate while the Nucleo isn't getting any response? I feel like there is a fundamental error in something I am doing but I can't identify it.

 

6 REPLIES 6
AA1
Senior III

Don't insert code as if it was text. When you insert code, you should click in </> icon in the toolbar.

SPI3_SCK and SPI3_MOSI output type should be push-pull. Where is GPIO configuration?

 

AScha.3
Chief II

Hi,

>Is there some configuration error that I am doing?

Seems so. 🙂

1.

Maybe you have to adjust your setting for the SPI:

set it to 16bit data , (Motorola) MSB first, and clock CPOL high + CPHA 2 edge .

Try...  (and write/read uint_16  size , 1 x . (not 2 bytes, as now.) )

about this:

AScha3_0-1719856795121.png

Then do the SPI... (with hard nss, dont need to care for /CS , nss doing this)

ret = HAL_SPI_TransmitReceive(&hspi2, sendData, receiveData, 1, 5);

Transmitted word/upper 8 bits is address, response (read=answer) comes in received word, lower 8bits ;

so you always have to do a (16bit) word transmit/receive , and set the important byte (= address), and in received word only use the lower byte (=response).

 

 

+

if not working: verify with scope, what you do (if possible) 

 

If you feel a post has answered your question, please click "Accept as Solution".
N_A_S
Associate II

Hi AA1, Thanks for the feedback, I'll keep that in mind for future posts.

About the SCK and MOSI pins, I didn't change their configuration. I haven't had any time this week to tinker around with the components, but I'll post a screenshot of the GPIO configuration when I can.

Hi AScha.3, thanks for responding. I have tried using the HAL_SPI_TransmitReceive function before, but not with the 16bit data size. I haven't had any time to tinker with the code this week, but I'll give you some feedback when I can.

N_A_S
Associate II

Hello,

I apologize for the delayed response. As previously mentioned, the configuration of the SPI pins and the GPIO used for the CS line have not been altered. The only available option for the SPI pins is Alternate Function Push Pull. I noticed that the default maximum output speed was set to low, so I attempted to change this setting. However, the issue of inconsistent readings persists.

I configured the SPI_SCK pin to GPIO Pull-up, suspecting that the rise of the clock signal after the CS line goes low might be interpreted by the accelerometer. This adjustment appeared to help for one of my Nucleo boards, but it did not completely resolve the problem on the other one. I am still investigating the issue. For the other board, the readings remain highly inconsistent, and interestingly, placing my hand close to the wires seems to result in correct readings from the ID register.

DO you know of any specific configurations that might help reduce this interference?

 

N_A_S_0-1723057596026.jpeg

 

Hi AScha.3,

Sorry for the delay in response. I applied the parameters you specified and read the signals. I am currently able to read the ID, but the readings are not stable. I have been testing with 2 different boards in different locations. For one board, after adjusting some GPIO configurations, the readings of the ID started working. I plan on doing some more tests in a few days to check if I can read the acceleration data. Here is the code I plan on using (and used for the ID reading):

/* USER CODE BEGIN PTD */
uint16_t senddata[1];
uint16_t receivedata[1];
uint16_t accel_senddata[4];
uint16_t accel_receivedata[4];
uint8_t deviceid;
uint8_t xL = 0;
uint8_t xH = 0;
uint8_t yL = 0;
uint8_t yH = 0;
uint8_t zL = 0;
uint8_t zH = 0;
/* USER CODE END PTD */

/* USER CODE BEGIN 0 */
void spi_write (uint8_t address, uint8_t value)
{
	uint8_t data[2];
	data[0] = address; //| 0x40; //Set the 0x40 bit high for multibyte communication
	data[1] = value;
	HAL_SPI_Transmit(&hspi3, data, 2, 100);
}

void spi_read (uint8_t address)
{
	uint16_t byte_sent = (address | 0xC0) << 8;
	senddata[0] = byte_sent;
	HAL_SPI_TransmitReceive(&hspi3, senddata, receivedata, 1, 5);
}

void acceldata_read (uint8_t address)
{
	uint16_t byte_sent = (address | 0xC0) << 8;
	accel_senddata[0] = byte_sent;
	HAL_SPI_TransmitReceive(&hspi3, accel_senddata, accel_receivedata, 4, 5);
}

void IIS2DH_init (void)
{
	HAL_Delay(100);
	spi_write (0x20, 0x7F); // (CTRL_REG1) ODR and axis selection and LP or Normal mode
	HAL_Delay(100);
	spi_write (0x23, 0x00); // (CTRL_REG4) Select range, SPI 3 or 4-wire modes and HR or Normal mode
	HAL_Delay(100);
}
/* USER CODE END 0 */

/* USER CODE BEGIN 2 */
  IIS2DH_init();
  /* USER CODE END 2 */

/* USER CODE BEGIN WHILE */
  while (1)
  {
	  //Read device ID
	  spi_read(0x0F);
	  deviceid = receivedata[0];
	  HAL_Delay(50);

	  //Read acceleration data
	  acceldata_read(0x28);
	  xL = (uint8_t)accel_receivedata[0];
	  xH = ((uint8_t)accel_receivedata[1]) >> 8;
	  yL = (uint8_t)accel_receivedata[1];
	  yH = ((uint8_t)accel_receivedata[2]) >> 8;
	  zL = (uint8_t)accel_receivedata[2];
	  zH = ((uint8_t)accel_receivedata[3]) >> 8;
	  HAL_Delay(50);
    /* USER CODE END WHILE */

 Comparing the reading from the ESP32 and the Nucleo, I noticed that the first clock rise was interfering with the communication since it was being put to high after the CS line goes low. I set the SCK line to pull-up in the GPIO configurations and that solved the issue for one of the boards. Here are the oscilloscope readings:

Without pull-up on SCK

N_A_S_0-1723067034477.jpeg


With pull-up on SCK

N_A_S_1-1723067076957.jpeg

I don't have an oscilloscope to read the signals on the other board, so I can't really see what is going on, but the codes and configuration are exactly the same on both boards. Here are the SPI configurations:

N_A_S_2-1723067393178.jpeg

I noticed the readings for the device ID and acceleration data are always 255. When I put my hand closer to the wires, the ID reading oscillates between 0, 51 and 255. I believe the value 51 indicates that the communication is being done correctly, but there is too much interference. I tried reducing the baud rate, but this didn't solve my issue. I am using 5cm jumper wires and my board is being fed through the USB port.

Do you know if there is some other configuration that would cause this interference on the signals? Are there any known issues or quirks with the SPI peripheral on the Nucleo boards that might affect communication with this type of sensor? Are there any specific tests or diagnostics that can be performed to isolate and identify the source of the interference?