stm32F1 dma关于spi在循环模式下传输数据量

时间:2018-06-16 10:34:17

标签: spi dma stm32f1

我目前正在使用DMA和SPI以循环模式学习STM32F1xx。 我的目标是让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重复发送a.b.c ...并按预期暂停。逻辑捕获请参见以下图像。

Send 10 bytes - Overview

Send 10 bytes - result

但是当我发送5个字节时,它似乎无法停止。逻辑捕获请看下面的图像。

Send 5 bytes - Overview, can not be stopped

Send 5 bytes - result, but it did send 5 byte repeatedly

我的问题仍然存在,为什么在设置5个字节要发送时无法停止DMA?

我测试了其他字节数。 10,9,8字节工作。但是7,6,5,4,3,2,1个字节不起作用。 SPI DMA是那些无法停止的情况。

如果需要提供更多信息,请告知我们。

感谢。

最好的问候。

2 个答案:

答案 0 :(得分:0)

检查您的数据大小。 DMA和SPI工作在8位/ 16位或32位模式。我的猜测是你的SPI预计每次传输16位(或设置为16位模式)。然后,DMA发送的第5个字节不会填充SPI的TX缓冲区。这意味着SPI不会发送16位(因为它正在等待另一个字节),这意味着TXE标志不会被置位,这意味着它不会从DMA请求下一个字节。 / p>

修复:将SPI设置为8位模式。

答案 1 :(得分:0)

遇到同样的问题。调试显示,它跳过了HAL_SPI_TxCpltCallback,但仍上升了HAL_SPI_TxHalfCpltCallback。 降低SPI的速度对我有用。 hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;