cancel
Showing results for 
Search instead for 
Did you mean: 

SPI slave doesn't receive information from SPI master in STM32h7

DGast.1
Associate III

I want to send data from one SPI master to an SPI slave in the same MCU. I don't have separated bards for master and slave, they are in the same board. I'm using an STM32H7 MCU with the following configuration:

SPI master:

0693W00000aI8hDQAS.pngSPI slave:

0693W00000aI8hXQAS.pngWith the following pins:

  • Master
    • MISO: PA6
    • MOSI: PD7
    • SCK: PA5
    • NSS (by SW): PC7
  • Slave
    • MISO: PB4
    • MOSI: PB5
    • SCK: PB3
    • NSS: PA4

I have connected wired the pins as following, by looking at the provided table:

In order to have both SPI master and slave in the same board, I have needed to use PD7 for the SPI master, which is described as an USART pin in the following table, but I'm not using the USART so I can use it for SPI.

0693W00000aI8ifQAC.png0693W00000aI8lFQAS.png0693W00000aI8jnQAC.png 

And here is my source code (I will provide only my custom code, not the one generated by CubeMX):

int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SPI1_Init();
  MX_SPI3_Init();
  /* USER CODE BEGIN 2 */
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  uint8_t buf[8] = {0x55, 2, 3, 4, 5, 6, 7, 8};
  uint8_t recv = 0;
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET);
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET);
    HAL_SPI_Transmit(&hspi1, (void*)buf, 1, 1000);
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET);
 
    HAL_StatusTypeDef rc = HAL_SPI_Receive(&hspi3, &recv, 1, 1000);
 
    if (rc == HAL_OK)
    {
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
    }
    else
    {
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_SET);
    }
 
    HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_1);
    HAL_Delay(1000);
  }
  /* USER CODE END 3 */
}

The result I see is the yellow LED blinking, and the red one set, which means the slave reception didn't go well, I'm assuming because of a timeout. Also, I'm able to see the master SPI transactions in my logic analyzer:

0693W00000aI8kMQAS.png 

What I'm expecting to happen is that the master sends the data to the slave, the slave receives it and puts it in its RxFIFO, and then (after the master finishes) I can read it.

What am I doing wrong?

1 ACCEPTED SOLUTION

Accepted Solutions
gbm
Lead III

With the code above, slave is not enabled during Master transmission. Call Receive_IT for slave before calling Transmit for master. MOSI should be connected to MOSI and MISO to MISO.

View solution in original post

5 REPLIES 5
AScha.3
Chief II

read in rm : is in/out swapped in slave mode ?

or just try: set "IO Swap " -> enabled . on slave device, then try again.

If you feel a post has answered your question, please click "Accept as Solution".
DGast.1
Associate III

> read in rm : is in/out swapped in slave mode ?

Do you mean like in a UART, that source and destination need to 'swap' Rx/Tx? In SPI, MISO is MISO in both sides and the same for MOSI, isn't it?

Anyway, I tried IO Swap and it didn't work.

AScha.3
Chief II

no, not both sides. only the slave device needs io swap set.

because: when setting spi-> master to -> slave, the i/o pins are swapped ! so you need to set io swap -> enabled to get them "back" to the position as in master state.

see in rm :

0693W00000aI97BQAS.pngso : when using slave mode , you need to change miso/mosi pins or select IO swap enable on this slave device (not on the master ! ).

++ or you connect it this way: miso-miso , mosi-mosi.

0693W00000aI8uAQAS.png

If you feel a post has answered your question, please click "Accept as Solution".
gbm
Lead III

With the code above, slave is not enabled during Master transmission. Call Receive_IT for slave before calling Transmit for master. MOSI should be connected to MOSI and MISO to MISO.

DGast.1
Associate III

I see @gbm​ , I was expecting the SPI device to be able to receive and store some data without any interaction of the SW, but you are right. In summary, I have enabled SPI3 global interrupts in the SPI3's NVIC tab, in STMCube32MX, and replaced my code by this:

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
#define STATUS_BUSY 0
#define STATUS_DATA_RECV 1
 
static int status = STATUS_BUSY;
 
void green_led(void)
{
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
}
 
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
  // HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
  if (hspi == &hspi3)
  {
    status = STATUS_DATA_RECV;
  }
}
 
/* USER CODE END 0 */
 
/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SPI1_Init();
  MX_SPI3_Init();
  /* USER CODE BEGIN 2 */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
  HAL_Delay(1000);
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  uint8_t buf[8] = {0x55, 2, 3, 4, 5, 6, 7, 8};
  uint8_t recv = 0;
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET);
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
    HAL_StatusTypeDef rc = HAL_SPI_Receive_IT(&hspi3, &recv, 1);
    if (rc != HAL_OK)
    {
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_SET);
      continue;
    }
 
    status = STATUS_BUSY;
 
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET);
    HAL_SPI_Transmit(&hspi1, (void*)buf, 1, 1000);
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET);
 
    while (status == STATUS_BUSY) { }
 
    if (recv == 0x55)
    {
      HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
      recv = 0;
    }
 
    HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_1);
    HAL_Delay(1000);
  }
  /* USER CODE END 3 */
}