STM32F4 HAL SPI_Receive dma 只接收一次

Posted

技术标签:

【中文标题】STM32F4 HAL SPI_Receive dma 只接收一次【英文标题】:STM32F4 HAL SPI_Receive dma just receive one time 【发布时间】:2021-06-16 23:14:35 【问题描述】:

我尝试了很多方法和读取参考,但我无法从 SPI_Receive_DMA 模式正确读取数据。

在 spi 1 中,我想在一个线程中以 dma 模式通过 spi 连续读取 Ad7606 数据。 但是,我总是在 SPI1 dma 模式下收到相同的数据。好像我没有收到任何新数据。我知道如果我只想在 spi dma 模式下接收数据,我还必须打开 TX 和 RX DMA 通道。 我不知道我错过了哪一步或错了。有谁知道如何解决这个问题?非常感谢。

static void MX_SPI1_Init(void)

  /* 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_2;
  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();
  

 
static void MX_DMA_Init(void)

 
  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();
  __HAL_RCC_DMA2_CLK_ENABLE();
 
  /* DMA interrupt init */
  /* DMA1_Stream4_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Stream4_IRQn, 5, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn);
  /* DMA2_Stream0_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 5, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
  /* DMA2_Stream3_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 5, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
 

** Note 
DMA2_Stream0 - > SPI1 Receive
DMA2_Stream3 - > SPI1 Transmit
DMA1_Stream4 - > SPI2 Transmit

void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)

  GPIO_InitTypeDef GPIO_InitStruct = 0;
  if(hspi->Instance==SPI1)
  
  /* USER CODE BEGIN SPI1_MspInit 0 */
 
  /* USER CODE END SPI1_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_SPI1_CLK_ENABLE();
 
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**SPI1 GPIO Configuration
    PA5     ------> SPI1_SCK
    PA6     ------> SPI1_MISO
    PB5     ------> SPI1_MOSI
    */
    GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
    GPIO_InitStruct.Pin = GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
    /* SPI1 DMA Init */
    /* SPI1_RX Init */
    hdma_spi1_rx.Instance = DMA2_Stream0;
    hdma_spi1_rx.Init.Channel = DMA_CHANNEL_3;
    hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_spi1_rx.Init.Mode = DMA_NORMAL;
    hdma_spi1_rx.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_spi1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
    
      Error_Handler();
    
 
    __HAL_LINKDMA(hspi,hdmarx,hdma_spi1_rx);
 
    /* SPI1_TX Init */
    hdma_spi1_tx.Instance = DMA2_Stream3;
    hdma_spi1_tx.Init.Channel = DMA_CHANNEL_3;
    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_NORMAL;
    hdma_spi1_tx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_spi1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
    
      Error_Handler();
    
 
    __HAL_LINKDMA(hspi,hdmatx,hdma_spi1_tx);
 
    /* SPI1 interrupt Init */
    HAL_NVIC_SetPriority(SPI1_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(SPI1_IRQn);
  /* USER CODE BEGIN SPI1_MspInit 1 */
 
  /* USER CODE END SPI1_MspInit 1 */
  


int main(void)

  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_SPI1_Init();
  MX_SPI2_Init();
  MX_TIM7_Init();
  MX_USART2_UART_Init();
  uint8_t receive_buffer[256] ;
  /* Init scheduler */
  osKernelInitialize();
 
 /*handle */
  SendTaskHandle = osThreadNew(SendTaskFun, NULL, &SendTask_attributes);
  ReceiveTaskHandle = osThreadNew(ReceiveTaskFun, NULL, &ReceiveTask_attributes);
 
  osKernelStart();
  while (1) 
  

 
 
 
void ReceiveTaskFun(void *argument)

  for (;;) 
     //-- SPI1 callback 
    HAL_SPI_RxCpltCallback(&hspi1); 
    HAL_GPIO_WritePin(GPIO_A, GPIO_PIN_7, 1); //-- cs=1    deactive 

 
 
 
void DMA2_Stream0_IRQHandler(void)

  HAL_DMA_IRQHandler(&hdma_spi1_rx);

 
void DMA2_Stream3_IRQHandler(void)

  HAL_DMA_IRQHandler(&hdma_spi1_tx);

 
 
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)

   if (hspi->Instance == SPI1)
         //-- Enable CS
         HAL_GPIO_WritePin(GPIO_A, GPIO_PIN_7, 0); //-- cs=0   active low  

         //- -  SPI2_DMA_receive
         ...... (Here is for receive data from AD7606 )
     HAL_SPI_Receive_DMA(&hspi1, receive_buffer, 8);
   





 

【问题讨论】:

【参考方案1】:

假设您的所有功能都正确映射,当前流程似乎是:

    ReceiveTaskFun 调用 HAL_SPI_RxCpltCallback() 断言您的芯片选择,启动 DMA 传输并返回 ReceiveTaskFun() 将您的 CS 引脚置为无效并进入下一个循环。 HAL_SPI_RxCpltCallback()(从 ReceiveTaskFun 调用)再次断言您的 CS 引脚并尝试设置 DMA 传输,但很可能会失败。检查返回值看HAL_BUSY,因为它还没有完成传输 同时,您的 DMA 传输可能会发生,也可能不会发生(外设将传输,无论您的从设备是否输出数据),因为您正在切换 CS 引脚 当 8 个字节的传输完成时,会调用 HAL_SPI_RxCpltCallback(),它会重新置位 CS 引脚并开始 DMA 传输。这可能会成功,但由于您一直在切换 CS 引脚,所以您得到的只是垃圾

解决方案可能是:

    在 ReceiveTaskFun() 中使用延迟。您知道传输 + 捕获持续时间,以此为基础 使用来自 SPI 中断的 RTOS 信号 - 让您的 ReceiveTaskFun 等待来自 ISR 回调的信号,然后设置新的传输。

【讨论】:

以上是关于STM32F4 HAL SPI_Receive dma 只接收一次的主要内容,如果未能解决你的问题,请参考以下文章

STM32F4 HAL库开发 -- 再识

STM32F4 UART HAL 驱动程序

STM32F4 HAL库开发 -- 工程模板解读

STM32F4 HAL库开发 -- 工程模板解读

STM32F4 HAL库开发 -- 工程模板解读

STM32F4 HAL库开发 -- DMA