Skip to main content
Graduate II
July 1, 2024
Question

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

  • July 1, 2024
  • 2 replies
  • 2402 views

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.

 

    This topic has been closed for replies.

    2 replies

    Visitor II
    July 1, 2024

    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?

     

    N_A_SAuthor
    Graduate II
    July 5, 2024

    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.

    Super User
    July 1, 2024

    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) 

     

    N_A_SAuthor
    Graduate II
    July 5, 2024

    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.