Problem with SPI Communication - Nucleo U575ZI-Q/STEVAL-MKI168V1
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.



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

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.

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

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

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.

Slow decay of the SCL line

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.
