STM32
直播中

蒲泛粟

8年用户 1011经验值
私信 关注
[问答]

stm32f4下spi+dma读取数据不对是什么原因导致的?

STM32F4用的HAL库,SPI3+DMA方式读取25FL512S片子数据,读出来的数据错误,之前没用DMA的时候读出来的数据是对的,为了提高速度换成DMA出现问题了,请大神们帮忙分析下?下面是代码:/* SPI3 init function */
void MX_SPI3_Init(void)
{
  hspi3.Instance = SPI3;
  hspi3.Init.Mode = SPI_MODE_MASTER;
  hspi3.Init.Direction = SPI_DIRECTION_2LINES;
  hspi3.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi3.Init.CLKPolarity = SPI_POLARITY_HIGH;
  hspi3.Init.CLKPhase = SPI_PHASE_2EDGE;
  hspi3.Init.NSS = SPI_NSS_SOFT;
  hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
  hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi3.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi3.Init.CRCPolynomial = 10;
  HAL_SPI_Init( hspi3);
}

void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
  GPIO_InitTypeDef GPIO_InitStruct;

  if(hspi->Instance==SPI3)
  {
  /* USER CODE BEGIN SPI3_MspInit 0 */

  /* USER CODE END SPI3_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_SPI3_CLK_ENABLE();
  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

    /**SPI3 GPIO Configuration   
    PA15     ------> SPI3_NSS1
    PD2      ------> SPI3_NSS2
    PD0      ------> SPI3_WP
    PD1      ------> SPI3_HOLD
    PD4      ------> SPI3_RST
    PC10     ------> SPI3_SCK
    PC11     ------> SPI3_MISO
    PC12     ------> SPI3_MOSI
    */
    GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF6_SPI3;
    HAL_GPIO_Init(GPIOC,  GPIO_InitStruct);

    /* SPI3 DMA Init */
    /* SPI3_RX Init */
    hdma_spi3_rx.Instance = DMA1_Stream0;
    hdma_spi3_rx.Init.Channel = DMA_CHANNEL_0;
    hdma_spi3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_spi3_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi3_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_spi3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_spi3_rx.Init.Mode = DMA_NORMAL;
    hdma_spi3_rx.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_spi3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    hdma_spi3_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
    hdma_spi3_rx.Init.MemBurst = DMA_MBURST_INC4;
    hdma_spi3_rx.Init.PeriphBurst = DMA_PBURST_INC4;

    HAL_DMA_Init( hdma_spi3_rx);
    __HAL_LINKDMA(hspi,hdmarx,hdma_spi3_rx);        

    /* SPI3_TX Init */
    hdma_spi3_tx.Instance = DMA1_Stream5;
    hdma_spi3_tx.Init.Channel = DMA_CHANNEL_0;
    hdma_spi3_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_spi3_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi3_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi3_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_spi3_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_spi3_tx.Init.Mode = DMA_NORMAL;
    hdma_spi3_tx.Init.Priority = DMA_PRIORITY_MEDIUM;
    hdma_spi3_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    hdma_spi3_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
    hdma_spi3_tx.Init.MemBurst = DMA_MBURST_INC4;
    hdma_spi3_tx.Init.PeriphBurst = DMA_PBURST_INC4;
    HAL_DMA_Init( hdma_spi3_tx);
    __HAL_LINKDMA(hspi,hdmatx,hdma_spi3_tx);

    /* DMA interrupt init */
  /* DMA1_Stream0_IRQn interrupt configuration */
  //HAL_NVIC_SetPriority(SPI3_IRQn, 6, 0);
  //HAL_NVIC_EnableIRQ(SPI3_IRQn);

    /* DMA interrupt init */
  /* DMA1_Stream0_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 6, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);

    /* DMA1_Stream5_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 6, 1);
  HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn);        

  /* USER CODE BEGIN SPI3_MspInit 1 */
  /* USER CODE END SPI3_MspInit 1 */
  }
}

void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi)
{
  if(hspi->Instance==SPI3)
  {
  /* USER CODE BEGIN SPI3_MspDeInit 0 */

  /* USER CODE END SPI3_MspDeInit 0 */
    /* Peripheral clock disable */
    __HAL_RCC_SPI3_CLK_DISABLE();
  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_DISABLE();

    /**SPI3 GPIO Configuration   
    PC10     ------> SPI3_SCK
    PC11     ------> SPI3_MISO
    PC12     ------> SPI3_MOSI
    */
    HAL_GPIO_DeInit(GPIOC, GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12);

    /* SPI3 DMA DeInit */
    HAL_DMA_DeInit(hspi->hdmarx);
   /HAL_DMA_DeInit(hspi->hdmatx);
        
  HAL_NVIC_DisableIRQ(DMA1_Stream0_IRQn);
  HAL_NVIC_DisableIRQ(DMA1_Stream5_IRQn);
  //HAL_NVIC_DisableIRQ(SPI3_IRQn);

  /* USER CODE BEGIN SPI3_MspDeInit 1 */
  /* USER CODE END SPI3_MspDeInit 1 */
  }
}

#include "stm32f4xx_it.c"文件下
/**
* @brief This function handles DMA1 stream0 global interrupt.
*/
void DMA1_Stream0_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Stream0_IRQn 0 */

  /* USER CODE END DMA1_Stream0_IRQn 0 */
  HAL_DMA_IRQHandler( hdma_spi3_rx);
  /* USER CODE BEGIN DMA1_Stream0_IRQn 1 */

  /* USER CODE END DMA1_Stream0_IRQn 1 */
}

/**
* @brief This function handles DMA1 stream5 global interrupt.
*/
void DMA1_Stream5_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Stream5_IRQn 0 */

  /* USER CODE END DMA1_Stream5_IRQn 0 */
  HAL_DMA_IRQHandler( hdma_spi3_tx);
  /* USER CODE BEGIN DMA1_Stream5_IRQn 1 */

  /* USER CODE END DMA1_Stream5_IRQn 1 */
}

main函数下定时读取数据调用的函数
void SPI_FLASH_BufferRead(UINT8 chipNum,UINT8* pBuffer, UINT32 ReadAddr, UINT16 NumByteToRead)
{
        if(ReadAddr+RX_DATA_LEN <= S25F_FLASH_SIZE)
        {
                /* 选择芯片 */
                SPI_FLASH_Select(chipNum);
                /*使能片选*/
                SPI_FLASH_CS_ENABLE();
                /*发送读数据指令*/
                SPI_FLASH_SendByte(S25F_ReadData);
                /*发送32位数据地址*/
                SPI_FLASH_Send4Bytes(ReadAddr);
                if(NumByteToRead> RX_DATA_LEN )
                {
                        NumByteToRead = RX_DATA_LEN ;  
                }
                HAL_SPI_Receive_DMA( SpiHandle,pBuffer,NumByteToRead);
                //取消片选信号
                SPI_FLASH_CS_DISABLE();
        }
}
HAL_SPI_Receive_DMA这边读出来的数据一直不对,另外我的HAL_SPI_RxCpltCallback函数除了库文件Stm32f4xx_hal_spi.c下,没在别的文件里重新编写。
请各位帮忙分析下什么原因?



回帖(3)

笑尽往事

2024-4-19 15:45:51
STM32F4下的SPI+DMA读取数据不对可能由多种原因导致。以下是一些可能的原因:

  • 硬件连接错误:如接触不良、接线过长或噪声过大等,这些都可能导致数据乱码或移位。
  • 主从机数据长度不一致:如果主机发送的数据长度与从机接收的数据长度不匹配,例如主机发送16位数据,而从机只接收8位数据,这就会导致数据读取错误。
  • DMA优先级问题:如果从机项目使用了多个中断,并且DMA的优先级不是最高的,那么DMA可能无法完整获取数据包,导致数据读取错误。
  • 数据包大小问题:如果数据包大小设置不正确,或在DMA传输完成中断中再次开启DMA时设置的数据包大小异常,都可能导致数据读取错误。
  • SPI配置问题:SPI的配置错误,例如时钟相位、时钟极性等设置不正确,也可能导致数据读取错误。
  • 中断处理不当:随机的中断CLK或类似干扰可能导致CLK增多或减少,从而影响到SPI接收或发送的移位寄存器无法获得完整的8位数据。此外,如果在DMA接收到一帧数据的一半时发生中断,DMA的计数器可能处于接收部分数据的状态,但并未达到中断个数,这也可能导致数据读取错误。
为了解决这个问题,你可以采取以下措施:

  • 检查硬件连接,确保所有连接都正确无误。
  • 确认主从机的数据长度一致,并调整相应的配置。
  • 确保DMA的优先级设置得当,以便在多个中断发生时能够优先处理DMA中断。
  • 检查并调整数据包大小设置,确保在DMA传输过程中数据包大小保持一致。
  • 仔细检查SPI的配置,确保所有参数都设置正确。
  • 优化中断处理逻辑,确保在DMA接收数据时不会发生意外的中断。
通过逐一排查上述可能的原因,你应该能够找到导致STM32F4下SPI+DMA读取数据不对的具体原因,并进行相应的修复。
举报

jf_40730847

2025-1-15 23:26:53
我之前也遇到过这类问题,体现为通讯速率到几百K以上就不能正常接收数据了,后来把SPI模式换成全双工,调用HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData, uint16_t Size)函数去读取数据就好了
举报

jf_40730847

2025-1-15 23:27:23
我之前也遇到过这类问题,体现为通讯速率到几百K以上就不能正常接收数据了,后来把SPI模式换成全双工,调用HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData, uint16_t Size)函数去读取数据就好了
举报

更多回帖

发帖
×
20
完善资料,
赚取积分