代码之家  ›  专栏  ›  技术社区  ›  Alexis

stm32 spi在使用中断时丢弃数据

  •  2
  • Alexis  · 技术社区  · 6 年前

    我正在尝试使用中断通过spi发送一个可变大小的字节数组。系统由两块核STM32L432板组成。发送板工作正常,但我与接收板有问题。特别是,我注意到经常会丢失一些字节。除了cubemx提供的默认初始化之外,在init函数中还有以下设置:

    // Trigger RXNE when the FIFO is 1/4 full
    LL_SPI_SetRxFIFOThreshold(sw.spi_sw2pc,LL_SPI_RX_FIFO_TH_QUARTER);
    
    // Enable RXNE interrupt
    LL_SPI_EnableIT_RXNE(sw.spi_sw2pc);
    
    // Enable SPI
    if((SPI3->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
    {
        // If disabled, I enable it
        SET_BIT(sw.spi_sw2pc->CR1, SPI_CR1_SPE);
    }
    

    SPI设置为以10 Mbit/s的速度工作。是否是通信速度太快?

    以下是irq处理程序和回调。

    中断处理程序

    void SPI3_IRQHandler(void)
    {
      /* USER CODE BEGIN SPI3_IRQn 0 */
      /* Check RXNE flag value in ISR register */
        if(LL_SPI_IsActiveFlag_RXNE(SPI3))
        {
            /* Call function Slave Reception Callback */
            SW_rx_callback();
        }
    
      /* USER CODE END SPI3_IRQn 0 */
      /* USER CODE BEGIN SPI3_IRQn 1 */
    
      /* USER CODE END SPI3_IRQn 1 */
    }
    

    回调

    void SW_rx_callback(void)
    {
        // RXNE flag is cleared by reading data in DR register
    
        while(LL_SPI_IsActiveFlag_RXNE(SPI3))
            recv_buffer[recv_buffer_index++] = LL_SPI_ReceiveData8(SPI3);
    
        if(LL_SPI_GetRxFIFOLevel(SPI3) == LL_SPI_RX_FIFO_EMPTY)
        {
            // If there are no more data
            new_data_arrived = true;
            memset(recv_buffer,'\0',recv_buffer_index);
            recv_buffer_index = 0;
        }
    
    }
    

    提前谢谢你的帮助。

    1 回复  |  直到 6 年前
        1
  •  3
  •   vlk    6 年前

    10mbits的spi意味着每秒有125万个中断(在8bit传输的情况下),这足以通过中断来处理,特别是与hal结合使用时。

    stm32l4xx相当快(80mhz),但在这种情况下,它意味着每个中断调用不能超过64个周期。但是调用中断需要12个周期,退出中断10个周期(它处于理想状态,总线上没有等待状态),所以如果中断代码需要42个或更多周期,那么您可以确保丢失了一些字节。

    以下是我的建议:

    • 首先尝试启用一些编译器优化,以加快代码速度。
    • 更改中断程序并从中断处理程序中删除所有不必要的内容(使用sw fifo并在主循环中处理接收到的数据)
    • 但最好的解决方案是使用dma传输。