-1

I have Nucleo-F446RE board. I would like to send data by SPI1 and receive it by SPI2 only for educational purposes. Unfortunately SPI2 doesn't receive any data. Project is configured by STM32-CubeMX. I tried with blocking API and interrupts without success. What might be wrong with this configuration?

Clock configuration: enter image description here

SPI1 configuration:

enter image description here

SPI2 configuration:

enter image description here

Connections (checked it many times):

PA4 (SPI1 NSS)  ----> PB12 (SPI2 NSS)  
PA5 (SPI1 SCK)  ----> PB10 (SPI2 SCK) 
PA6 (SPI1 MISO) ----> PC2 (SPI2 MISO)
PA7 (SPI1 MOSI) ----> PC1 (SPI2 MOSI)

Code:

/* USER CODE BEGIN Header */

/**

  ******************************************************************************

  * @file           : main.c

  * @brief          : Main program body

  ******************************************************************************

  * @attention

  *

  * Copyright (c) 2022 STMicroelectronics.

  * All rights reserved.

  *

  * This software is licensed under terms that can be found in the LICENSE file

  * in the root directory of this software component.

  * If no LICENSE file comes with this software, it is provided AS-IS.

  *

  ******************************************************************************

  */

/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/

#include "main.h"

#include "spi.h"

#include "gpio.h"



/* Private includes ----------------------------------------------------------*/

/* USER CODE BEGIN Includes */



/* USER CODE END Includes */



/* Private typedef -----------------------------------------------------------*/

/* USER CODE BEGIN PTD */



/* USER CODE END PTD */



/* Private define ------------------------------------------------------------*/

/* USER CODE BEGIN PD */

/* USER CODE END PD */



/* Private macro -------------------------------------------------------------*/

/* USER CODE BEGIN PM */



/* USER CODE END PM */



/* Private variables ---------------------------------------------------------*/



/* USER CODE BEGIN PV */

//SPI_HandleTypeDef hspi1;

/* USER CODE END PV */



/* Private function prototypes -----------------------------------------------*/

void SystemClock_Config(void);

/* USER CODE BEGIN PFP */



/* USER CODE END PFP */



/* Private user code ---------------------------------------------------------*/

/* USER CODE BEGIN 0 */



/* 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_USART2_UART_Init();

  MX_SPI1_Init();

  MX_SPI2_Init();

  /* USER CODE BEGIN 2 */



  char uart_buf1[50] = {};

  auto uart_buf_len = sprintf(uart_buf1, "SPI Test");

  HAL_StatusTypeDef status1 = HAL_SPI_Transmit(&hspi1, (uint8_t *)uart_buf1, uart_buf_len, 1000);



  char uart_buf2[50] = {};

  HAL_StatusTypeDef status2 = HAL_SPI_Receive(&hspi2, (uint8_t *)uart_buf2, 50, 1000);



  /* USER CODE END 2 */



  /* Infinite loop */

  /* USER CODE BEGIN WHILE */

  while (1)

  {

    /* USER CODE END WHILE */



    /* USER CODE BEGIN 3 */

  }

  /* USER CODE END 3 */

}



/**

  * @brief System Clock Configuration

  * @retval None

  */

void SystemClock_Config(void)

{

  RCC_OscInitTypeDef RCC_OscInitStruct = {0};

  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};



  /** Configure the main internal regulator output voltage

  */

  __HAL_RCC_PWR_CLK_ENABLE();

  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);



  /** Initializes the RCC Oscillators according to the specified parameters

  * in the RCC_OscInitTypeDef structure.

  */

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;

  RCC_OscInitStruct.HSIState = RCC_HSI_ON;

  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;

  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;

  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)

  {

    Error_Handler();

  }



  /** Initializes the CPU, AHB and APB buses clocks

  */

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK

                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;

  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;

  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;

  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;



  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)

  {

    Error_Handler();

  }

}



/* USER CODE BEGIN 4 */



/* USER CODE END 4 */



/**

  * @brief  This function is executed in case of error occurrence.

  * @retval None

  */

void Error_Handler(void)

{

  /* USER CODE BEGIN Error_Handler_Debug */

  /* User can add his own implementation to report the HAL error return state */

  __disable_irq();

  while (1)

  {

  }

  /* USER CODE END Error_Handler_Debug */

}



#ifdef  USE_FULL_ASSERT

/**

  * @brief  Reports the name of the source file and the source line number

  *         where the assert_param error has occurred.

  * @param  file: pointer to the source file name

  * @param  line: assert_param error line source number

  * @retval None

  */

void assert_failed(uint8_t *file, uint32_t line)

{

  /* USER CODE BEGIN 6 */

  /* User can add his own implementation to report the file name and line number,

     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* USER CODE END 6 */

}

#endif /* USE_FULL_ASSERT */
hcheung
  • 3,377
  • 3
  • 11
  • 23
drewpol
  • 665
  • 1
  • 6
  • 26

1 Answers1

0

You are calling blocking transmit then blocking receive. The transmit is complete before the receiver starts listening.

You need to start a non-blocking receive, then do a blocking transmit, then check that the receive has finished.

Most of the STM32 cube packages include an example that does exactly this, try looking through the examples.

Tom V
  • 4,827
  • 2
  • 5
  • 22
  • I tested solution where SPI2 is handled by interrupt and result was faulty (no data received). By the way, as I understood, SPI has two hardware buffers (TX, RX) and data register. So when I send something to SPI2 then it goes to SPI2 RX buffer and when I need to read this, data are shifted to DataRegister and moved to buffer allocated by code. So there shouldn't be difference if use blocking or not blocking mode, because SPI RXNE registed should indicate that something is waiting in buffer for read. – drewpol Sep 28 '22 at 07:02
  • @drewpol no, only interrupt solution can work. Otherwise your function sends stuff out via SPI1, while SPI2 is not even receiving anything yet (it physically is, but you haven't called receive function as of that moment yet, so it's likely SPI2 is getting overflowed with input you're not processing immediately, it receives byte after byte after byte, while SPI2 receive hasn't been called yet). So it has to be interrupt based solution for both send and receive parts to happen simultaneously. But first, make sure there are actually valid waveforms physically on the lines, if possible. – Ilya Sep 29 '22 at 08:58