stm32F1 dma о количестве передаваемых данных в круговом режиме

В настоящее время я изучаю STM32F1xx, используя DMA и SPI с круговым режимом. Моя цель - позволить STM32F1 повторно отправлять одни и те же данные.

Я использую код, сгенерированный cubeMX, настраиваю SPI-DMA в круговом режиме и использую HAL_SPI_Transmit_DMA() для активации передачи DMA.

У меня есть буфер данных, как здесь:

char dataBuf[10] = {'a','b','c','d','e','f','g','h','i','j'};

Когда я использую HAL_SPI_Transmit_DMA (& hspi1, dataBuf, 10); это работает отлично. STM32F1 отправляет символы повторно через SPI, и я могу использовать HAL_SPI_DMAStop(&hspi1); чтобы остановить это.

Но если я хочу просто отправить 5 байт dataBuf несколько раз, используя HAL_SPI_Transmit_DMA (& hspi1, dataBuf, 5), STM32 не может среагировать на это. Он просто где-то висел и ничего не делал.

Мне интересно, почему это происходит. Должен ли объем данных быть таким же, как объявленный размер буферного массива (на самом деле, для меня это не имеет смысла)? Как я могу использовать круговой режим для отправки желаемого объема данных?

Update1

Я должен приложить свои настройки SPI и DMA, вот они.

Настройка SPI:

/* SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
  _Error_Handler(__FILE__, __LINE__);
}

Настройка DMA:

hdma_spi1_tx.Instance = DMA1_Channel3;
hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi1_tx.Init.Mode = DMA_CIRCULAR;
hdma_spi1_tx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
{
  _Error_Handler(__FILE__, __LINE__);
}

Update2

Это моя тестовая установка с кодом:

char spiDataBuf[10] = {'a','b','c','d','e','f','g','h','i','j'};
uint8_t runSPI = 0;

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
  //HAL_Delay(500);
  if(HAL_GetTick()-lastTick > 1)
  {
      //calColor2Data(&statusColor, 1);
      //updateWs2812();
      if(runSPI)
      {
          HAL_SPI_Transmit_DMA(&hspi1,spiDataBuf,5); 
          // or HAL_SPI_Transmit_DMA(&hspi1,spiDataBuf,10);
          runSPI = 0;
      }
      else
      {
          runSPI = 1;
          HAL_SPI_DMAStop(&hspi1);
      }

      lastTick = HAL_GetTick();
  }



/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

}

И логический вывод: когда я установил 10 байтов для отправки, он работает нормально, STM32 отправляет abc.. несколько раз и делает паузу, как предполагалось. Захват логики, пожалуйста, смотрите следующие изображения.

Отправить 10 байт - Обзор

Отправить 10 байт - результат

Но когда я посылаю 5 байт, кажется, что это не может быть остановлено.. Логический захват, пожалуйста, смотрите следующие изображения.

Отправить 5 байтов - обзор, не может быть остановлен

Отправить 5 байт - результат, но он отправил 5 байт повторно

Мой вопрос остается, почему DMA не может быть остановлен, когда я установил 5 байтов для отправки?

Я проверил другое количество байтов. 10, 9, 8 байт работают. Но 7, 6, 5, 4, 3,2,1 байт не работают. SPI DMA - это те случаи, которые нельзя остановить.

Если необходимо предоставить дополнительную информацию, пожалуйста, дайте мне знать.

Благодарю.

С наилучшими пожеланиями.

1 ответ

Проверьте ваши размеры данных. DMA и SPI работают в 8-битном /16-битном или 32-битном режиме. Я предполагаю, что ваш SPI ожидает 16 бит для каждой передачи (или установлен в 16-битном режиме). Затем 5-й байт, который отправляет ваш DMA, не заполняет буфер TX SPI. Это означает, что SPI не будет передавать 16 бит (так как он ожидает другого байта), что означает TXE флаг не будет установлен, что означает, что он не будет запрашивать следующий байт от прямого доступа к памяти.

Исправление: установите SPI в 8-битный режим.

У меня такая же проблема. Отладка показывает, что пропускает HAL_SPI_TxCpltCallback, но все равно поднимается HAL_SPI_TxHalfCpltCallback. Понижение скорости SPI у меня сработало. hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;

Другие вопросы по тегам