Understanding STM32 SPI Communication (Master-Slave Dual Machine SPI Communication)

Understanding STM32 SPI Communication (Master-Slave Dual Machine SPI Communication)

Click the blue text

Follow us

STM32 SPI Communication

  • High-speed full-duplex communication bus

The SPI communication uses 3 lines and a chip select line. The 3 lines are SCK, MOSI, and MISO, and the chip select line is NSS (CS).

Understanding STM32 SPI Communication (Master-Slave Dual Machine SPI Communication)

  • The NSS signal line goes from high to low, which is the start signal for SPI communication. NSS is a signal line that is exclusively owned by each slave. When a slave detects the start signal on its own NSS line, it knows it has been selected by the master and begins to prepare for communication with the master. In the diagram, at the marked point , the NSS signal goes from low to high, which is the stop signal for SPI communication, indicating that the communication has ended and the slave’s selected state is canceled.

  • SPI uses the MOSI and MISO signal lines to transmit data, and the SCK signal line for data synchronization. The MOSI and MISO data lines transmit one bit of data on each clock cycle of SCK, and data input and output occur simultaneously.

  • There are four communication modes in SPI, and their main differences lie in the clock state of SCK when the bus is idle and the timing of data sampling. To facilitate explanation, we introduce the concepts of “Clock Polarity (CPOL)” and “Clock Phase (CPHA).”

  • Clock Polarity (CPOL) refers to the level signal of the SCK line when the SPI communication device is in an idle state (i.e., the state of SCK before SPI communication starts, when the NSS line is high). When CPOL=0, SCK is low in idle state; when CPOL=1, it is the opposite.

  • Clock Phase (CPHA) refers to the timing of data sampling. When CPHA=0, the signal on the MOSI or MISO data line will be sampled on the “odd edge” of the SCK clock line. When CPHA=1, the data line is sampled on the “even edge” of SCK.

Understanding STM32 SPI Communication (Master-Slave Dual Machine SPI Communication)

SPI communication mode when CPHA=0

Understanding STM32 SPI Communication (Master-Slave Dual Machine SPI Communication)

SPI communication mode when CPHA=1:

Understanding STM32 SPI Communication (Master-Slave Dual Machine SPI Communication)

1. First, pull the chip select line NSS low,

2. Write data into the transmission buffer, the SCK clock starts running, and MOSI will automatically send the data from the transmission buffer. After sending a frame of data, when the transmission buffer is empty, the TXE flag will change to 1, allowing further data to be sent.

3. By checking whether the receive buffer flag is 1 (the receive buffer is not empty), read the data from the receive buffer.

  • The SCLK signal line is controlled only by the master device; the slave device cannot control the signal line. Similarly, in an SPI-based device, there must be at least one master device;

  • In point-to-point communication, the SPI interface does not require addressing operations and is full-duplex communication, making it simple and efficient. In a system with multiple slave devices, each slave device requires an independent enable signal, making the hardware slightly more complex than an I2C system.

Is it MSB first (most significant bit first) or LSB first (least significant bit first)?

From the bit perspective, MSB in the SPI protocol indicates that the high bit is sent first. Similarly, LSB indicates that the low bit is sent first. This should not be confused with endianness.

Endianness issue (from the byte perspective)

Big endian means that the most significant byte is stored at the lowest address (big endian, high byte at low address), while little endian means that the least significant byte is stored at the lowest address (little endian, low byte at low address).

For example, with 0x12345678, the storage order in two different byte order CPUs is as follows:

Understanding STM32 SPI Communication (Master-Slave Dual Machine SPI Communication)

SPI_DEMO Practice

STM32 Master-Slave Dual Machine SPI Communication Test:

Functionality: Master and slave devices can receive data from each other

Understanding STM32 SPI Communication (Master-Slave Dual Machine SPI Communication)

Wiring:

Understanding STM32 SPI Communication (Master-Slave Dual Machine SPI Communication)

The connections are one-to-one; do not connect MOSI to MISO, and the configuration parameters of both devices such as rate, phase, polarity, CRC, transmission direction, and bit count must be the same. Remember, they must share a common ground.

Understanding STM32 SPI Communication (Master-Slave Dual Machine SPI Communication)

Main code for the master device:

  1. /* Master device stm32f103c8 SPI1 */

  2. int main(void)

  3. {

  4. u16 t;

  5. u8 send_data=’A’;

  6. u8 led_flag = 0;

  7. delay_init(); // Delay function initialization

  8. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // Set NVIC interrupt group 2: 2 bits preemptive priority, 2 bits response priority

  9. uart_init(115200); // UART initialization to 115200

  10. LED_Init(); // LED port initialization

  11. KEY_Init(); // Key PB9 pull-up to detect low level

  12. spi_M_init(); // SPI1

  13. SPI_MCU_CS_LOW(); // Start signal low level selected to communicate with the slave device

  14. while(1)

  15. {

  16. if(KEY0==0)

  17. {

  18. delay_ms(5);

  19. if(KEY0==0){

  20. /* Check if the specified SPI flag is set: transmission buffer empty flag, no data */

  21. while (SPI_I2S_GetFlagStatus(MCU_SPIx, SPI_I2S_FLAG_TXE) == RESET); // Check if the specified SPI flag is set: transmission buffer empty flag

  22. SPI_I2S_SendData(MCU_SPIx, send_data); // Send a data through peripheral SPIx

  23. /* Wait for one byte to be received */

  24. while (SPI_I2S_GetFlagStatus(MCU_SPIx, SPI_I2S_FLAG_RXNE) == RESET);

  25. /* Send the data sent by the slave device, which is the data received by the master device, to the UART transmission buffer */

  26. USART1->DR = SPI_I2S_ReceiveData(MCU_SPIx);

  27. led_flag++;

  28. send_data++;}

  29. while(KEY0==0);

  30. }else{

  31. }

  32. if(led_flag%2)

  33. GPIO_SetBits(GPIOC,GPIO_Pin_13);

  34. else

  35. GPIO_ResetBits(GPIOC,GPIO_Pin_13);

  36. }

  37. }

  38. // SPI master mode configuration

  39. void spi_M_init(void){

  40. SPI_InitTypeDef SPI_InitStructure;

  41. GPIO_InitTypeDef GPIO_InitStructure;

  42. NVIC_InitTypeDef NVIC_InitStructure;

  43. /* Enable SPI clock */

  44. MCU_SPI_APBxClock_FUN ( MCU_SPI_CLK, ENABLE );

  45. /* Enable clock for SPI related pins */

  46. MCU_SPI_CS_APBxClock_FUN ( MCU_SPI_CS_CLK|MCU_SPI_SCK_CLK|MCU_SPI_MISO_PIN|MCU_SPI_MOSI_PIN, ENABLE );

  47. /* Configure the CS pin of SPI, it can be a normal IO */

  48. GPIO_InitStructure.GPIO_Pin = MCU_SPI_CS_PIN;

  49. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  50. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

  51. GPIO_Init(MCU_SPI_CS_PORT, &GPIO_InitStructure);

  52. /* Configure the SCK pin of SPI */

  53. GPIO_InitStructure.GPIO_Pin = MCU_SPI_SCK_PIN;

  54. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

  55. GPIO_Init(MCU_SPI_SCK_PORT, &GPIO_InitStructure);

  56. /* Configure the MISO pin of SPI */

  57. GPIO_InitStructure.GPIO_Pin = MCU_SPI_MISO_PIN;

  58. GPIO_Init(MCU_SPI_MISO_PORT, &GPIO_InitStructure);

  59. /* Configure the MOSI pin of SPI */

  60. GPIO_InitStructure.GPIO_Pin = MCU_SPI_MOSI_PIN;

  61. GPIO_Init(MCU_SPI_MOSI_PORT, &GPIO_InitStructure);

  62. /* Stop signal MCU: CS pin high level */

  63. SPI_MCU_CS_HIGH();

  64. /* SPI mode configuration */

  65. // MCU chip supports SPI mode 0 and mode 3, set CPOL CPHA accordingly

  66. SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

  67. SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

  68. SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;

  69. SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;

  70. SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

  71. SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;// Note this

  72. SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;//

  73. SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;

  74. SPI_InitStructure.SPI_CRCPolynomial = 7;

  75. SPI_Init(MCU_SPIx , &SPI_InitStructure);

  76. /* Enable SPI */

  77. SPI_Cmd(MCU_SPIx , ENABLE);

  78. //SPI_I2S_ITConfig(MCU_SPIx, SPI_I2S_IT_RXNE, ENABLE); // Enable receive interrupt

  79. /* NVIC interrupt controller configuration */

  80. // NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // Interrupt priority group 2

  81. // NVIC_InitStructure.NVIC_IRQChannel = SPI1_IRQn; // SPI2 interrupt

  82. // NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; // Preemptive priority 3

  83. // NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; // Sub-priority 3

  84. // NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // Enable IRQ channel

  85. // NVIC_Init(&NVIC_InitStructure); // Initialize VIC register according to specified parameters

  86. }

Main code for the slave device:

  • To allow the master to initially receive valid data, first store the data to be sent in the transmission buffer SPI_I2S_SendData(MCU_SPIx,ā€˜n’);. One point to note is that at this time, the data has not yet been sent to the master device, as the slave device cannot actively send data but must passively send data, waiting for the master device to send data, which means it must wait for a clock signal cycle. When the slave device receives the clock signal (CLK), it moves the data from the transmission buffer to the shift register and sends it to the master device.

  • Since it is a slave device, the SPI1 chip select pin will be reused, hardware chip select.

  1. //stm32f103c8 Slave device

  2. int main(void)

  3. {

  4. u16 retry;

  5. u8 send_data=’a’;

  6. u8 led_flag=0;

  7. delay_init(); // Delay function initialization

  8. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // Set NVIC interrupt group 2: 2 bits preemptive priority, 2 bits response priority

  9. uart_init(115200); // UART initialization to 115200

  10. LED_Init(); // LED port initialization

  11. KEY_Init();

  12. spi_S_init();

  13. while (SPI_I2S_GetFlagStatus(MCU_SPIx, SPI_I2S_FLAG_TXE) == RESET); // Check if the specified SPI flag is set: receive buffer non-empty flag

  14. SPI_I2S_SendData(MCU_SPIx,’n’);//

  15. while(1)

  16. {

  17. // while (SPI_I2S_GetFlagStatus(MCU_SPIx, SPI_I2S_FLAG_TXE) == RESET); // Check if the specified SPI flag is set: receive buffer non-empty flag

  18. // SPI_I2S_SendData(MCU_SPIx,’n’);

  19. }

  20. }

  21. // SPI slave mode configuration

  22. void spi_S_init(void){

  23. SPI_InitTypeDef SPI_InitStructure;

  24. GPIO_InitTypeDef GPIO_InitStructure;

  25. NVIC_InitTypeDef NVIC_InitStructure;

  26. /* Enable SPI clock */

  27. MCU_SPI_APBxClock_FUN ( MCU_SPI_CLK, ENABLE );

  28. /* Enable clock for SPI related pins */

  29. MCU_SPI_CS_APBxClock_FUN ( MCU_SPI_CS_CLK|MCU_SPI_SCK_CLK|MCU_SPI_MISO_PIN|MCU_SPI_MOSI_PIN, ENABLE );

  30. /* Configure the CS pin of SPI, it can be a normal IO */

  31. GPIO_InitStructure.GPIO_Pin = MCU_SPI_CS_PIN;

  32. // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  33. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

  34. GPIO_Init(MCU_SPI_CS_PORT, &GPIO_InitStructure);

  35. /* Configure the SCK pin of SPI */

  36. GPIO_InitStructure.GPIO_Pin = MCU_SPI_SCK_PIN;

  37. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

  38. GPIO_Init(MCU_SPI_SCK_PORT, &GPIO_InitStructure);

  39. /* Configure the MISO pin of SPI */

  40. GPIO_InitStructure.GPIO_Pin = MCU_SPI_MISO_PIN;

  41. GPIO_Init(MCU_SPI_MISO_PORT, &GPIO_InitStructure);

  42. /* Configure the MOSI pin of SPI */

  43. GPIO_InitStructure.GPIO_Pin = MCU_SPI_MOSI_PIN;

  44. GPIO_Init(MCU_SPI_MOSI_PORT, &GPIO_InitStructure);

  45. /* Stop signal MCU: CS pin high level */

  46. // SPI_MCU_CS_HIGH();

  47. /* SPI mode configuration */

  48. // MCU chip supports SPI mode 0 and mode 3, set CPOL CPHA accordingly

  49. SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

  50. SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;

  51. SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;

  52. SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;

  53. SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

  54. SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;// As a slave, chip select

  55. SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;

  56. SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;

  57. SPI_InitStructure.SPI_CRCPolynomial = 7;

  58. SPI_Init(MCU_SPIx , &SPI_InitStructure);

  59. /* Enable SPI */

  60. SPI_Cmd(MCU_SPIx , ENABLE);

  61. SPI_I2S_ITConfig(MCU_SPIx, SPI_I2S_IT_RXNE, ENABLE); // Enable receive interrupt

  62. NVIC_InitStructure.NVIC_IRQChannel = SPIX_IRQ; // SPI1 interrupt

  63. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1; // Preemptive priority 3

  64. NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; // Sub-priority 3

  65. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // Enable IRQ channel

  66. NVIC_Init(&NVIC_InitStructure); // Initialize VIC register according to specified parameters

  67. }

  68. u8 send_data=’a’;

  69. u8 led_flag=0;

  70. // Interrupt handling function

  71. void handle_spi_fun(void)

  72. {

  73. /* Check if the receive buffer is non-empty */

  74. if (SET == SPI_I2S_GetITStatus(MCU_SPIx, SPI_I2S_IT_RXNE))

  75. {

  76. USART1->DR = MCU_SPIx->DR; /* Read data from the receive buffer */

  77. while (SPI_I2S_GetFlagStatus(MCU_SPIx, SPI_I2S_FLAG_TXE) == RESET);

  78. MCU_SPIx->DR = send_data;

  79. if(led_flag%2)

  80. GPIO_ResetBits(GPIOC,GPIO_Pin_13);

  81. else

  82. GPIO_SetBits(GPIOC,GPIO_Pin_13);

  83. led_flag++;

  84. send_data++;

  85. /* Clear interrupt flag */

  86. SPI_I2S_ClearITPendingBit(MCU_SPIx, SPI_I2S_IT_RXNE);

  87. }

  88. }

Test results:

Understanding STM32 SPI Communication (Master-Slave Dual Machine SPI Communication)

COM8 is the master device receiving data from the slave device, and COM4 is the slave device receiving data from the master device.

It is evident that the master device failed to successfully obtain data from the slave device, while the slave device received data from the master device.

Problem analysis:

1. The problem lies with the master device: the master device did not receive or respond.

2. The problem lies with the slave device: the slave device did not send data.

3. Both of the above problems occurred simultaneously.

Connection issues:

1. First, I connected the master device’s MOSI to its own MISO, and the test result showed that the master device could receive data. This ruled out the first possibility.

2. During communication between the master and slave devices, I used a logic analyzer to detect the MISO pin and did not detect any waveform changes. The problem is likely with the slave device.

So, I replaced the slave device with STM32F429, while the master device remained STM32F103C8, and the program remained the same.

Understanding STM32 SPI Communication (Master-Slave Dual Machine SPI Communication)

Wiring:

Understanding STM32 SPI Communication (Master-Slave Dual Machine SPI Communication)

Understanding STM32 SPI Communication (Master-Slave Dual Machine SPI Communication)

  1. /*stm32F429IG SPI2 Slave device*/

  2. #define SELECT_MASTER 0

  3. int main(void)

  4. {

  5. u8 send_data=’a’;

  6. u8 led_flag=0;

  7. LED_GPIO_Config();//PB0 PB1

  8. Debug_USART_Config();// UART1 115200

  9. SPI_MCU_Init();// SPI2

  10. key_init();// PA0 Key

  11. #if SELECT_MASTER // Set in bsp_spi_mcu.h file

  12. send_data=’A’;

  13. #else

  14. /* Check if the transmission buffer is empty, a point to note

  15. As a slave device, placing data in the transmission buffer does not mean it has been sent to the master device,

  16. It must wait for the master device to send data, which means it needs a clock signal (SCK)

  17. */

  18. while (SPI_I2S_GetFlagStatus(MCU_SPI, SPI_I2S_FLAG_TXE) == RESET);

  19. /* Write data to the data register, writing the data to the transmission buffer */

  20. SPI_I2S_SendData(MCU_SPI, send_data);

  21. #endif

  22. while(1){

  23. // Master device

  24. #if SELECT_MASTER // Set in bsp_spi_mcu.h file

  25. if(KEY==1)

  26. {

  27. delay(0x0F);

  28. if(KEY==1){

  29. /* Check if the transmission buffer is empty, no data */

  30. while (SPI_I2S_GetFlagStatus(MCU_SPI, SPI_I2S_FLAG_TXE) == RESET);

  31. /* Write data to the data register, writing the data to the transmission buffer */

  32. SPI_I2S_SendData(MCU_SPI, send_data);

  33. /* Check if the receive buffer is non-empty, there is data */

  34. while (SPI_I2S_GetFlagStatus(MCU_SPI, SPI_I2S_FLAG_RXNE) == RESET);

  35. /* Send the received data to the UART transmission buffer */

  36. USART1->DR = SPI_I2S_ReceiveData(MCU_SPI);

  37. led_flag++;

  38. send_data++;

  39. while(KEY==1);

  40. }else{}

  41. }

  42. #else

  43. // Slave device

  44. /* Check if the receive buffer is non-empty, there is data */

  45. while(SPI_I2S_GetFlagStatus(MCU_SPI, SPI_I2S_FLAG_RXNE) == RESET);

  46. /* Send the received data to the UART transmission buffer */

  47. USART1->DR = SPI_I2S_ReceiveData(MCU_SPI);

  48. /* Check if the transmission buffer is empty, no data */

  49. while (SPI_I2S_GetFlagStatus(MCU_SPI, SPI_I2S_FLAG_TXE) == RESET);

  50. /* Write data to the data register, writing the data to the transmission buffer */

  51. SPI_I2S_SendData(MCU_SPI, send_data);

  52. led_flag++;

  53. send_data++;

  54. #endif

  55. // Each time the slave device sends data or the master device presses a key, LED1 PB0 toggles

  56. if(led_flag%2)

  57. LED1_OFF

  58. else

  59. LED1_ON

  60. }

  61. }

  62. // SPI2 configuration

  63. void SPI_MCU_Init(void)

  64. {

  65. SPI_InitTypeDef SPI_InitStructure;

  66. GPIO_InitTypeDef GPIO_InitStructure;

  67. /* Enable MCU_SPI and GPIO clock */

  68. /*!< Enable clock for SPI_MCU_SPI_CS_GPIO, SPI_MCU_SPI_MOSI_GPIO,

  69. SPI_MCU_SPI_MISO_GPIO,SPI_MCU_SPI_SCK_GPIO */

  70. RCC_AHB1PeriphClockCmd (MCU_SPI_SCK_GPIO_CLK | MCU_SPI_MISO_GPIO_CLK|MCU_SPI_MOSI_GPIO_CLK|MCU_CS_GPIO_CLK, ENABLE);

  71. /*!< Enable clock for SPI_MCU_SPI */

  72. MCU_SPI_CLK_INIT(MCU_SPI_CLK, ENABLE);

  73. // Set pin multiplexing

  74. GPIO_PinAFConfig(MCU_SPI_SCK_GPIO_PORT,MCU_SPI_SCK_PINSOURCE,MCU_SPI_SCK_AF);

  75. GPIO_PinAFConfig(MCU_SPI_MISO_GPIO_PORT,MCU_SPI_MISO_PINSOURCE,MCU_SPI_MISO_AF);

  76. GPIO_PinAFConfig(MCU_SPI_MOSI_GPIO_PORT,MCU_SPI_MOSI_PINSOURCE,MCU_SPI_MOSI_AF);

  77. /*!< Configure SPI_MCU_SPI pin: SCK */

  78. GPIO_InitStructure.GPIO_Pin = MCU_SPI_SCK_PIN;

  79. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  80. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  81. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  82. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

  83. GPIO_Init(MCU_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);

  84. /*!< Configure SPI_MCU_SPI pin: MISO */

  85. GPIO_InitStructure.GPIO_Pin = MCU_SPI_MISO_PIN;

  86. GPIO_Init(MCU_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);

  87. /*!< Configure SPI_MCU_SPI pin: MOSI */

  88. GPIO_InitStructure.GPIO_Pin = MCU_SPI_MOSI_PIN;

  89. GPIO_Init(MCU_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);

  90. /*!< Configure SPI_MCU_SPI pin: CS */

  91. GPIO_InitStructure.GPIO_Pin = MCU_CS_PIN;

  92. #if SELECT_MASTER

  93. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

  94. #else

  95. /* As a slave device, the hardware chip select pin CS needs to be multiplexed */

  96. GPIO_PinAFConfig(MCU_CS_GPIO_PORT,MCU_SPI_CS_PINSOURCE,MCU_SPI_CS_AF);

  97. #endif

  98. GPIO_Init(MCU_CS_GPIO_PORT, &GPIO_InitStructure);

  99. /* Stop signal MCU: CS pin high level */

  100. // SPI_MCU_CS_HIGH();

  101. /* MCU_SPI mode configuration */

  102. // MCU chip supports SPI mode 0 and mode 3, set CPOL CPHA accordingly

  103. SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

  104. #if SELECT_MASTER

  105. SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

  106. SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

  107. #else

  108. /* Slave mode, set hardware chip select */

  109. SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;

  110. SPI_InitStructure.SPI_NSS = SPI_NSS_Hard;

  111. #endif

  112. SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;

  113. SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;

  114. SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

  115. SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;

  116. SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;

  117. SPI_InitStructure.SPI_CRCPolynomial = 7;

  118. SPI_Init(MCU_SPI, &SPI_InitStructure);

  119. /* Enable MCU_SPI */

  120. SPI_Cmd(MCU_SPI, ENABLE);

  121. }

  122. ![Please add image description](https://img-blog.csdnimg.cn/029afabf1290445b918b83f0a82f7ea1.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzc0NjMyNQ==,size_16,color_FFFFFF,t_70)

Results:

Understanding STM32 SPI Communication (Master-Slave Dual Machine SPI Communication)

COM8 is the master device receiving data from the slave device, and COM1 is the slave device receiving data from the master device.

The output results from the serial port indicate that the test was successful.

To further validate my hypothesis, I swapped the master and slave modes of STM32F1 and STM32F4, and the result was the same: the master device (F4) failed to successfully receive data sent by the slave device (F1), while the slave device could receive data.

Conclusion:

When STM32F103 is used as a slave, it can receive data but cannot send data or experiences data shifting issues.

Additionally: The two microcontrollers have different clock frequencies; F4 has a clock frequency of 180MHz, while F1 has a clock frequency of 72MHz. The APB2 clock frequency for F4 is 90MHz, and the APB1 clock frequency is 45MHz; for F1, the APB2 clock frequency is 72MHz, and the APB1 clock frequency is 36MHz. The SPI1 device is a high-speed device belonging to the APB2 bus, while SPI2 is a low-speed device belonging to the APB1 bus. Therefore, under the same configuration parameters, for example, when SPI1 is the master, the SCLK clock frequency is 72MHz/256=2812.5 KHz, while SPI2 is 36MHz/256=140.625 KHz.

Understanding STM32 SPI Communication (Master-Slave Dual Machine SPI Communication)

Understanding STM32 SPI Communication (Master-Slave Dual Machine SPI Communication)

*Disclaimer: This article is original or forwarded by the author. If it inadvertently infringes on someone’s intellectual property, please inform us for deletion.The above images and text are sourced from the internet. If there is any infringement, please contact us in a timely manner, and we will delete it within 24 hours.The content of the article reflects the author’s personal views, and the Automotive Ethernet Technology Research Laboratory reprints it only to convey a different perspective, which does not represent the Automotive Ethernet Technology Research Laboratory’s endorsement or support of this view. If there are any objections, please contact the Automotive Ethernet Technology Research Laboratory.

Original link:

https://blog.csdn.net/weixin_43746325/article/details/119545607

Leave a Comment