cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 HAL_SPI_Library on Blue Pill

NicoNX650
Associate III

Title edited to note that this relates to a Blue Pill board.


Hello everyone,
I'm starting a learning journey into the STM32 world, specifically studying the HAL library (my past programming experiences didn't rely on ready-made libraries).
Right now (after tinkering with GPIOs, LCD management, etc.) I'm working on the SPI dialogue. I have two STM32F103CBT6A development boards, one configured for "Full Duplex Master" and one for "Full Duplex Slave."
When trying to send 10 static bytes (10, 20, 30, 100) from both the master and slave sides using the "HAL_SPI_TransmitReceive_IT(&hspi1, TX_Buffer, RX_Buffer, 10)" function, I expect the oscilloscope to see the MOSI line equal to the MISO line without any offsets. This happens for a few seconds after resetting the slave (image 1), but then the bytes on the MISO line shift (image 2). Furthermore (I'm viewing the data received from the slave on an LCD) when this problem occurs, the slave also doesn't receive correctly.
After adjusting the codes for 10-byte transmission, I wanted to expand it to 150 bytes.
Thanks in advance to anyone who can point out where I'm going wrong.

27 REPLIES 27
TDK
Super User

The slave has to be ready to send before the master starts clocking SCK. This is a code issue. How are you ensuring the slave is ready to send before the master starts?

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

I don't know the exact Cube/HAL example you talk about here.
But historically, the F103 is a very early model, and most examples published by ST utilized the SPL, a predecessor of the current library.
I'm still using SPL code for many of my examples, because it's much less complicated, less resource-intensive, and better readable - and the examples were usually tested well.

Anyway, most of the SPL firmware packages I reviewed (F0, F3, F4) contained a SPI/DMA example with two identical boards, one as slave and one as master. The example is usually named "SPI_TwoBoards" (or similiar).

Even if you stick with your Cube code, I would recommend to download such a package (usually the more generic one named "STM32xxxx_DSP_StdPeriph_Lib_Vx.x.x"), and compare the configuration process and setup sequence of your code with the example.

Dear TDK,

thanks a lot for your reply.

How can I load data into the slave's buffer before the master starts generating the clock?

Best Regards

 

TDK
Super User

Here is one way to properly handle SPI interrupt-based communications between master and slave:

https://github.com/STMicroelectronics/STM32CubeF1/blob/8cdc2027b0a4652897d540a15614aece650361dd/Projects/STM32F103RB-Nucleo/Examples/SPI/SPI_FullDuplex_ComIT/Src/main.c

 

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

Dear TDK,

I'm sorry to bother you again, but I can't figure out what I'm doing wrong in your example. I've attached the code for my master and slave. Any help would be greatly appreciated.

MASTER CODE:

 
while (1)
{
 /* USER CODE END WHILE */
 /* USER CODE BEGIN 3 */

 Lcd_cursor(&lcd, 0,0);
 Lcd_int(&lcd, RX_Buffer[0]);
 Lcd_cursor(&lcd, 0,4);
 Lcd_int(&lcd, RX_Buffer[1]);
 Lcd_cursor(&lcd, 0,8);
 Lcd_int(&lcd, RX_Buffer[2]);
 Lcd_cursor(&lcd, 0,12);
 Lcd_int(&lcd, RX_Buffer[3]);
 Lcd_cursor(&lcd, 0,16);
 Lcd_int(&lcd, RX_Buffer[4]);
 Lcd_cursor(&lcd, 1,0);
 Lcd_int(&lcd, RX_Buffer[5]);
 Lcd_cursor(&lcd, 1,4);
 Lcd_int(&lcd, RX_Buffer[6]);
 Lcd_cursor(&lcd, 1,8);
 Lcd_int(&lcd, RX_Buffer[7]);
 Lcd_cursor(&lcd, 1,12);
 Lcd_int(&lcd, RX_Buffer[8]);
 Lcd_cursor(&lcd, 1,16);
 Lcd_int(&lcd, RX_Buffer[9]);

 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
 HAL_SPI_TransmitReceive_IT(&hspi1, TX_Buffer, RX_Buffer, 10);
 HAL_Delay(1);
 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);

 HAL_Delay(500);
}

/* USER CODE END 3 */
}

SLAVE CODE:

 
while (1)
{
 /* USER CODE END WHILE */
 /* USER CODE BEGIN 3 */
 
 Lcd_cursor(&lcd, 0,0);
 Lcd_int(&lcd, RX_Buffer[0]);
 Lcd_cursor(&lcd, 0,4);
 Lcd_int(&lcd, RX_Buffer[1]);
 Lcd_cursor(&lcd, 0,8);
 Lcd_int(&lcd, RX_Buffer[2]);
 Lcd_cursor(&lcd, 0,12);
 Lcd_int(&lcd, RX_Buffer[3]);
 Lcd_cursor(&lcd, 0,16);
 Lcd_int(&lcd, RX_Buffer[4]);
 Lcd_cursor(&lcd, 1,0);
 Lcd_int(&lcd, RX_Buffer[5]);
 Lcd_cursor(&lcd, 1,4);
 Lcd_int(&lcd, RX_Buffer[6]);
 Lcd_cursor(&lcd, 1,8);
 Lcd_int(&lcd, RX_Buffer[7]);
 Lcd_cursor(&lcd, 1,12);
 Lcd_int(&lcd, RX_Buffer[8]);
 Lcd_cursor(&lcd, 1,16);
 Lcd_int(&lcd, RX_Buffer[9]);

 HAL_SPI_TransmitReceive_IT(&hspi1, TX_Buffer, RX_Buffer, 10);
 }

/* USER CODE END 3 */
}

Best Regards


Edited to apply source code formatting - please see How to insert source code for future reference.

Andrew Neil
Super User

Welcome to the forum.

Please see How to write your question to maximize your chances to find a solution for best results.

 


@NicoNX650 wrote:

 I have two STM32F103CBT6A development boards, .


What boards are they, exactly ?

 

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.

Dear Andrew,

thanks for your reply.

The boards are two STM32F103CBT6A.

Best Regards


@NicoNX650 wrote:

The boards are two STM32F103CBT6A.


That's not a board - that's just the part number of the MCU chip.

You need to give details of the board on which the chip is mounted.

 

How to write your question to maximize your chances to find a solution

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.

Dear Andrew,

you're right. If I remember well the board name is Blue Pill.

For be sure I attached the picture of them.

Thanks 

IMG_20260209_183218.jpg