cancel
Showing results for 
Search instead for 
Did you mean: 

Unable to set up SPI between 2 stm32 devices

JTurn.2
Senior

I am trying to get 2 stm32f411's to communicate via SPI. From my understanding, there should be 1 master device while the others should be its slaves.

For my master device, I am using full-duplex master and I have disabled NSS and enabled the NSS pin as an GPIO OUTPUT pin.

0693W00000Hoa0tQAB.png 

For my slave device, I am using full-duplex slave and have enabled NSS INPUT SIGNAL so it knows when it needs to read.

0693W00000Hoa1DQAR.png 

Here are my problems:

  1. I have set the prescalar of the master device to 64 but am unable to set the prescalar of the slave device as there is no option to do so. I am unsure if this is a problem as I have seen an example where it is possible to set the prescalar for the slave device. However, am I unsure if it is necessary as the option disappears for me every time I set a device to slave.
  2. I am unsure if I need to change anything in the "clock configuration". I noticed that there is a option to enable PLLCLK for CSS but I am not sure if I need to do this or if leaving it set to HSI is ok.
  3. I am unable to send and receive any data.

Here is a screenshot of the clock configuration I am talking about.0693W00000Hoa3nQAB.png 

Here is the code for my master device:

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_SPI2_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);
  uint8_t TX_Data[] = "abcdefgh";
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);
  HAL_SPI_Transmit(&hspi2, TX_Data, sizeof(TX_Data), 5000);
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
static void MX_SPI2_Init(void)
{
 
  /* USER CODE BEGIN SPI2_Init 0 */
 
  /* USER CODE END SPI2_Init 0 */
 
  /* USER CODE BEGIN SPI2_Init 1 */
 
  /* USER CODE END SPI2_Init 1 */
  /* SPI2 parameter configuration*/
  hspi2.Instance = SPI2;
  hspi2.Init.Mode = SPI_MODE_MASTER;
  hspi2.Init.Direction = SPI_DIRECTION_1LINE;
  hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi2.Init.NSS = SPI_NSS_SOFT;
  hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
  hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi2.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI2_Init 2 */
 
  /* USER CODE END SPI2_Init 2 */
 
}

Here is the code for my slave device:

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_SPI2_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
  int8_t RX_Data[1652];
  // Receive SPI Data (Blocking Mode) Polling
  HAL_SPI_Receive(&hspi2, RX_Data, sizeof(RX_Data), 5000);
  HAL_UART_Transmit(&huart1, RX_Data, sizeof(RX_Data), 5000);
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
 
static void MX_SPI2_Init(void)
{
 
  /* USER CODE BEGIN SPI2_Init 0 */
 
  /* USER CODE END SPI2_Init 0 */
 
  /* USER CODE BEGIN SPI2_Init 1 */
 
  /* USER CODE END SPI2_Init 1 */
  /* SPI2 parameter configuration*/
  hspi2.Instance = SPI2;
  hspi2.Init.Mode = SPI_MODE_SLAVE;
  hspi2.Init.Direction = SPI_DIRECTION_2LINES;
  hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi2.Init.NSS = SPI_NSS_HARD_INPUT;
  hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi2.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI2_Init 2 */
 
  /* USER CODE END SPI2_Init 2 */
 
}

Also, please let me know if there are any good and detailed guides on spi, i2c, uart, etc.

Thank you very much for your time and help!

4 REPLIES 4
KnarfB
Principal III

Hi,

the slave gets its clock from the master, you don't setup a slave clock.

Note that you are using blocking functions. I.e.sizeof(RX_Data) should match sizeof(TX_Data) for the beginning, or you will get a timeout (Receiver waiting for 1652 bytes to come).

Put the SPI releated code in the main loop such that sender and receiver meet, independently of boot order/timing.

If possible, use a (simple USB) logic analyzer for watching the signals.

hth

KnarfB

S.Ma
Principal

Use exti nss edge interrupt on the spave side to lock onto the incoming packet. Just imagine if you push the slave reset button few seconds after the master's....

Then use slave in dma ram tx and rx buffer dma cycic mode so slave can mostly avoid short latency interrupts. Once nss goes up on slave side, reset spi and dma and prepare the next data exchange. HAL doesn't provide EXTI on alternate function configured pin, register hack needed. Beware some stm32 slave max speed is div4 while master max speed is div2...

Hi, thank you for your advice. I have adjusted the sizeof(RX_Data) to 8 and now it outputs something. However, the output is garbage text and I'm not quite sure why.

"Put the SPI releated code in the main loop such that sender and receiver meet, independently of boot order/timing." I'm not quite sure what this means. Do you mean I should add the configurations for SPI2 in main()?

Once again, thank you for your help.

Edit: The garbage text I'm consistently getting is "È.. ...."

Hi, I'm not quite sure I understand what you mean. Maybe it's because I'm a beginner in stm32. How do I set exti nss edge interrupt and could you provide an example or elaborate a bit more on how to do this "Once nss goes up on slave side, reset spi and dma and prepare the next data exchange"? Thank you for your help!