Skip to main content
Associate
September 8, 2026
Question

SPI communication with POWERSTEP – receiving same data as transmitted

  • September 8, 2026
  • 3 replies
  • 24 views

Hello everyone,

I’m trying to communicate with a POWERSTEP motor driver via SPI using an STM32 (STM32F4) and the HAL library. I have a basic test where I send three bytes and read back the same number of bytes, but I always receive exactly the same data that I transmit (i.e., a loopback effect). The POWERSTEP does not seem to respond with its expected status bytes.

SPI configuration (from CubeMX):

hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;    // CPOL = 1
hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;         // CPHA = 1  => SPI mode 3
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
 

Code snippet (simplified):

uint8_t tx[3];
uint8_t rx[3];

tx[0] = 0x3B;   // example command
tx[1] = 0x00;
tx[2] = 0x00;

 

// Reset chip
HAL_GPIO_WritePin(rstPOWERSTEP_GPIO_Port, rstPOWERSTEP_Pin, GPIO_PIN_RESET);
HAL_Delay(5);
HAL_GPIO_WritePin(rstPOWERSTEP_GPIO_Port, rstPOWERSTEP_Pin, GPIO_PIN_SET);
HAL_Delay(5);

HAL_GPIO_WritePin(csPOWERSTEP_GPIO_Port, csPOWERSTEP_Pin, GPIO_PIN_SET);
HAL_Delay(10);

uint8_t i = 0;
while (i < 3)
{
    // CS Low
    HAL_GPIO_WritePin(csPOWERSTEP_GPIO_Port, csPOWERSTEP_Pin, GPIO_PIN_RESET);

    // Send 1 byte and receive 1 byte
    HAL_SPI_Transmit(&hspi1, &tx[i], 1, 100);
    HAL_SPI_Receive(&hspi1, &rx[i], 1, 100);

    // CS High
    HAL_GPIO_WritePin(csPOWERSTEP_GPIO_Port, csPOWERSTEP_Pin, GPIO_PIN_SET);

    HAL_Delay(100);
    ++i;
}

3 replies

Peter BENSCH
ST Technical Moderator
September 8, 2026

The issue is most likely caused by the SPI transaction handling rather than the POWERSTEP itself.

You should not toggle CS for every byte and you should not use separate HAL_SPI_Transmit() and HAL_SPI_Receive() calls for this device. The POWERSTEP typically needs one full SPI frame under a single CS low, and its status/data is often returned on the next transaction, not immediately.

Use HAL_SPI_TransmitReceive() with all 3 bytes at once, keep CS low for the whole frame, and then perform a second SPI transfer if you want to read back the device response.

Regards
/Peter

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
HRusevAuthor
Associate
September 9, 2026

Hi Peter,

Thank you for the advice. I changed the code as you suggested and tested it.

Here is what I tried:

// Reset chip
HAL_GPIO_WritePin(rstPOWERSTEP_GPIO_Port, rstPOWERSTEP_Pin, GPIO_PIN_RESET);
HAL_Delay(5);
HAL_GPIO_WritePin(rstPOWERSTEP_GPIO_Port, rstPOWERSTEP_Pin, GPIO_PIN_SET);
HAL_Delay(5);
HAL_GPIO_WritePin(csPOWERSTEP_GPIO_Port, csPOWERSTEP_Pin, GPIO_PIN_SET);
HAL_Delay(100);

uint8_t tx[3] = {0xD0, 0x00, 0x00};
uint8_t rx[3] = {0x00};

HAL_GPIO_WritePin(csPOWERSTEP_GPIO_Port, csPOWERSTEP_Pin, GPIO_PIN_RESET);
HAL_SPI_TransmitReceive(&hspi1, tx, rx, 3, 100);
HAL_GPIO_WritePin(csPOWERSTEP_GPIO_Port, csPOWERSTEP_Pin, GPIO_PIN_SET);
HAL_Delay(100);

uint8_t txResponse[2] = {0x00};
uint8_t rxResponse[2] = {0x00};

HAL_GPIO_WritePin(csPOWERSTEP_GPIO_Port, csPOWERSTEP_Pin, GPIO_PIN_RESET);
HAL_SPI_TransmitReceive(&hspi1, txResponse, rxResponse, 2, 100);
HAL_GPIO_WritePin(csPOWERSTEP_GPIO_Port, csPOWERSTEP_Pin, GPIO_PIN_SET);

 

Result:

  • rx = {0x00, 0xD0, 0x00}
  • rxResponse = {0x00, 0x00}

According to Figure 28 in the datasheet, I understand that I should send something like {0xD0, 0xD0, 0x00} and receive {0x00, response byte 1, response byte 0} in a single transfer.

I’m a bit confused, because from the figure it looks like the response should come in the same SPI frame, not only in a second transaction.

I’m using the X-NUCLEO-IHM03A1 board.

Any further suggestions would be greatly appreciated.

Best regards

Peter BENSCH
ST Technical Moderator
September 9, 2026

Your SPI handling now looks much closer to the expected POWERSTEP behaviour.

The key point is that POWERSTEP replies are typically pipelined: the bytes you receive during one SPI frame usually belong to the previous command/frame, not necessarily the command you are sending right now.

So:

  • rx = {0x00, 0xD0, 0x00} is not necessarily a loopback fault
  • it can simply mean the device is returning data according to its frame pipeline
  • the meaningful response is available on the next full 3-byte transaction
  • a 2-byte follow-up transfer may not match the device’s expected frame length

Suggestion:

  1. Keep CS low for the full frame
  2. Use a full 3-byte HAL_SPI_TransmitReceive() transaction (as mentioned before)
  3. Follow it with another full 3-byte transaction to read back the previous response
  4. Verify the exact command and frame length in the datasheet
  5. Check the SPI timing with a logic analyser if possible

Regards
/Peter

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.