GD32F103单片机主从SPI通信异常问题处理

📅 2026/8/14 5:06:23
GD32F103单片机主从SPI通信异常问题处理
项目场景主板上有主从单片机主单片机为STM32F103从单片机为GD32F103RET6它们之间通过SPI进行通信相互发送数据。问题描述调试过程中发现当重新通过仿真器对主单片机进行下载程序并仿真时主从单片机之间的SPI通信就会发生异常无法正常通信。但是对整个主板重新上电主从单片机通信一直是正常的。原因分析怀疑是在主板运行过程中若单片机自身发生复位会导致主从单片机之间SPI的通信出现异常可能性最大的是CLK时钟错位。进一步对从单片机的程序进行仿真发现SPI的SPI_STAT_TRANS标志位一直处于置位状态也就是说处于忙状态导致从单片机无法正常收发数据。解决方案SPI初始化时对SCK引脚增加外部中断检测配置如下所示staticvoidSPI1_GPIO_Configuration(void){rcu_periph_clock_enable(RCU_GPIOB);rcu_periph_clock_enable(RCU_SPI1);rcu_periph_clock_enable(RCU_AF);/* SPI2_SCK(PB13), SPI1_MISO(PB14) and SPI1_MOSI(PB15) GPIO pin configuration */gpio_init(GPIOB,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_10MHZ,GPIO_PIN_13);gpio_init(GPIOB,GPIO_MODE_IPU,GPIO_OSPEED_10MHZ,GPIO_PIN_15);gpio_init(GPIOB,GPIO_MODE_AF_PP,GPIO_OSPEED_10MHZ,GPIO_PIN_14);spi_nss_internal_low(SPI_PORT);/* enable and set key EXTI interrupt priority */nvic_irq_enable(EXTI10_15_IRQn,3,0);/* connect key EXTI line to key GPIO pin */gpio_exti_source_select(GPIO_PORT_SOURCE_GPIOB,GPIO_PIN_SOURCE_13);/* configure key EXTI line */exti_init(EXTI_13,EXTI_INTERRUPT,EXTI_TRIG_RISING);exti_interrupt_flag_clear(EXTI_13);}外部中断处理程序代码如下voidEXTI10_15_IRQHandler(void){if(RESET!exti_interrupt_flag_get(EXTI_13)){exti_interrupt_flag_clear(EXTI_13);if(spi_i2s_flag_get(SPI_PORT,SPI_FLAG_TRANS)RESET)SPI1_Busy_1ms0;SPI1_Clk_1ms0;}}添加监视SPI的busy状态的处理程序若SPI_FLAG_TRANS置位SPI1_Busy_1ms 100但却没有检测到SCK即SPI1_Clk_1ms100则对SPI进行重新配置。如下所示voidSPI1_Monitor(void){if(System1msGetReady()){if(SPI1_Busy_1ms!0xffff)SPI1_Busy_1ms;if(SPI1_Clk_1ms!0xffff)SPI1_Clk_1ms;}if(spi_i2s_flag_get(SPI_PORT,SPI_FLAG_TRANS)RESET){SPI1_Busy_1ms0;SPI1_Clk_1ms0;}if(SPI1_Busy_1ms100SPI1_Clk_1ms100){SPI1_Busy_1ms0;SPI1_Configuration();}}优化 SPI 中断处理程序并增加错误处理逻辑voidSPI1_IRQHandler(void){/* 接收缓冲区非空中断 */if(spi_i2s_interrupt_flag_get(SPI_PORT,SPI_I2S_INT_FLAG_RBNE)SET){struct_Uart_BUF*P_Uart;P_UartUartAll_Get(UART_NO_SPI1);P_Uart-RecBuf[P_Uart-RecBufWritePoint]spi_i2s_data_receive(SPI_PORT);P_Uart-RecBufWritePoint(P_Uart-RecBufWritePoint1)%UART_BUFFER_SIZE;}/* 发送缓冲区空中断 */if(spi_i2s_interrupt_flag_get(SPI_PORT,SPI_I2S_INT_FLAG_TBE)SET){if(SPI1_Int_SendR!SPI1_Int_SendW){spi_i2s_data_transmit(SPI_PORT,SPI1_Int_SendBuffer[SPI1_Int_SendR]);SPI1_Int_SendR(SPI1_Int_SendR1)%SPI_SEND_BUFFER_SIZE;}else{IRQ_REQUEST_HIGH();spi_i2s_interrupt_disable(SPI_PORT,SPI_I2S_INT_TBE);}}/* 接收CRC错误 */if(spi_i2s_interrupt_flag_get(SPI_PORT,SPI_INT_FLAG_CRCERR)SET){spi_crc_error_clear(SPI_PORT);}/* 接收过载错误 */if(spi_i2s_interrupt_flag_get(SPI_PORT,SPI_I2S_INT_FLAG_RXORERR)SET){/* 先读SPI_DATA寄存器 */spi_i2s_data_receive(SPI_PORT);SPI_STAT(SPI_PORT);}}经过上述配置问题可以得到解决。