STM32 SPI отбрасывает данные при использовании прерывания - PullRequest
0 голосов
/ 07 июня 2018

Я пытаюсь отправить массив байтов переменного размера через SPI, используя прерывания.Система состоит из двух ядерных плат STM32L432.Плата отправителя работает нормально, но у меня проблема с платой получателя.В частности, я заметил, что очень часто некоторые байты сбрасываются.Помимо инициализации по умолчанию, предоставляемой CubeMX, в моей функции инициализации также есть следующие настройки:

// 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 Мбит / с.Может ли быть так, что скорость связи слишком высокая?

Ниже приведены обработчик IRQ и обратный вызов.

обработчик 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 Ответ

0 голосов
/ 07 июня 2018

SPI на 10 Мбит / с означает, что у вас будет 1,25 миллиона прерываний в секунду (в случае 8-битной передачи), и этого вполне достаточно для обработки прерываниями, особенно в сочетании с HAL.

STM32L4xx довольно быстро (80 МГц) но в данном случае это означает, что каждый вызов прерывания не может занимать более 64 циклов.но вызов прерывания занимает 12 циклов, выходное прерывание 10 циклов (оно находится в идеальном состоянии без состояний ожидания на шине), поэтому, если ваш код прерывания займет 42 или более циклов, вы можете быть уверены, что пропустили несколько байтов.

Вот мои предложения:

  • Сначала попробуйте включить некоторые оптимизации компилятора, чтобы ускорить код.
  • Измените подпрограмму прерывания и удалите все ненужное из обработчика прерываний (используйте SWFIFO и обрабатывает полученные данные в основном цикле)
  • Но лучшим решением в вашем случае может быть использование передачи DMA.
...