ST意法半导体
直播中

刘丽菲

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

STM32H750XBH6- ART-Pi使用HAL_SPI_Transmit_DMA()函数初次发送时,不进入SPI中断怎么解决?

主控:STM32H750XBH6- ART-Pi
开发环境:CubeMX+MDK V5.27问题背景: DAC芯片需要使用32bit SPI 目前使用轮询方式工作正常 需要硬件SPI+DMA加快速率1.在仅仅更改:以下三项为8bit byte时,单字节的DMA发送是能够多次发送的,功能正常
hspi2.Init.DataSize = SPI_DATASIZE_32BIT;---------------->8BIThdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;------->BYTEhdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;------>BYTE2.当前代码使用HAL_SPI_Transmit_DMA()函数初次发送时,能够在逻辑分析仪上看到波形出现(能进入DMA中断),但是不进入SPI中断,导致SPI_Busy3.当前代码由于处于Bus状态导致之后所有DMA发送直接返回

SPI配置项:
void MX_SPI2_Init(void){/* USER CODE BEGIN SPI2_Init 0 *//* USER CODE END SPI2_Init 0 *//* USER CODE BEGIN SPI2_Init 1 *//* USER CODE END SPI2_Init 1 */hspi2.Instance = SPI2;hspi2.Init.Mode = SPI_MODE_MASTER;hspi2.Init.Direction = SPI_DIRECTION_2LINES;hspi2.Init.DataSize = SPI_DATASIZE_32BIT;hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;hspi2.Init.NSS = SPI_NSS_SOFT;hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;hspi2.Init.TIMode = SPI_TIMODE_DISABLE;hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;hspi2.Init.CRCPolynomial = 0x0;hspi2.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;hspi2.Init.NSSPolarity = SPI_NSS_POLARITY_LOW;hspi2.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA;hspi2.Init.TxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;hspi2.Init.RxCRCInitializationPattern = SPI_CRC_INITIALIZATION_ALL_ZERO_PATTERN;hspi2.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE;hspi2.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE;hspi2.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE;hspi2.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE;hspi2.Init.IOSwap = SPI_IO_SWAP_DISABLE;if (HAL_SPI_Init(&hspi2) != HAL_OK){Error_Handler();}/* USER CODE BEGIN SPI2_Init 2 *//* USER CODE END SPI2_Init 2 */}DMA配置项:
void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle){  GPIO_InitTypeDef GPIO_InitStruct = {0};  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};  if(spiHandle->Instance==SPI2)  {  /* USER CODE BEGIN SPI2_MspInit 0 */  /* USER CODE END SPI2_MspInit 0 */  /** Initializes the peripherals clock  */    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI2;    PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL;    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)    {      Error_Handler();    }    /* SPI2 clock enable */    __HAL_RCC_SPI2_CLK_ENABLE();    __HAL_RCC_GPIOI_CLK_ENABLE();    /**SPI2 GPIO Configuration    PI1     ------> SPI2_SCK    PI2     ------> SPI2_MISO    PI3     ------> SPI2_MOSI    */    GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;    GPIO_InitStruct.Pull = GPIO_NOPULL;    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;    HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);    /* SPI2 DMA Init */    /* SPI2_TX Init */    hdma_spi2_tx.Instance = DMA1_Stream0;    hdma_spi2_tx.Init.Request = DMA_REQUEST_SPI2_TX;    hdma_spi2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;    hdma_spi2_tx.Init.PeriphInc = DMA_PINC_DISABLE;    hdma_spi2_tx.Init.MemInc = DMA_MINC_ENABLE;    hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;    hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;    hdma_spi2_tx.Init.Mode = DMA_NORMAL;    hdma_spi2_tx.Init.Priority = DMA_PRIORITY_LOW;    hdma_spi2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;    hdma_spi2_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;    hdma_spi2_tx.Init.MemBurst = DMA_MBURST_SINGLE;    hdma_spi2_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;    if (HAL_DMA_Init(&hdma_spi2_tx) != HAL_OK)    {      Error_Handler();    }    __HAL_LINKDMA(spiHandle,hdmatx,hdma_spi2_tx);    /* SPI2 interrupt Init */    HAL_NVIC_SetPriority(SPI2_IRQn, 0, 0);    HAL_NVIC_EnableIRQ(SPI2_IRQn);  /* USER CODE BEGIN SPI2_MspInit 1 */  /* USER CODE END SPI2_MspInit 1 */  }}

回帖(1)

麻酱

2025-3-8 17:24:41

在使用STM32H750XBH6的ART-Pi开发板时,如果你遇到HAL_SPI_Transmit_DMA()函数初次发送时无法进入SPI中断的问题,可能是由于以下几个原因导致的。以下是一些可能的解决方案和调试步骤:


1. 检查SPI和DMA配置



  • SPI配置:确保SPI的配置正确,尤其是数据大小(DataSize)设置为32位时,其他相关配置也要匹配。

  • DMA配置:检查DMA的配置,确保PeriphDataAlignmentMemDataAlignment与SPI的数据大小匹配。如果SPI数据大小是32位,那么DMA的PeriphDataAlignmentMemDataAlignment应该设置为DMA_PDATAALIGN_WORDDMA_MDATAALIGN_WORD


2. 检查SPI中断优先级



  • 确保SPI中断的优先级设置正确,并且没有被其他高优先级中断阻塞。你可以尝试提高SPI中断的优先级,看看是否能解决问题。


3. 检查DMA中断



  • 如果你使用的是DMA传输,确保DMA中断配置正确,并且DMA中断已经启用。你可以检查HAL_SPI_Transmit_DMA()函数是否正确地启用了DMA传输。


4. 检查SPI和DMA的初始化顺序



  • 确保SPI和DMA的初始化顺序正确。通常,DMA应该在SPI之前初始化,或者在SPI初始化之后重新配置DMA。


5. 检查SPI时钟



  • 确保SPI的时钟配置正确,并且SPI时钟已经启用。如果SPI时钟没有正确配置或启用,SPI传输将无法启动。


6. 检查SPI状态寄存器



  • 在调试时,可以检查SPI的状态寄存器(如SR寄存器),看看是否有任何错误标志被置位。例如,检查OVR(溢出错误)、MODF(模式错误)等标志。


7. 检查DMA传输完成回调函数



  • 确保你已经实现了DMA传输完成回调函数(如HAL_SPI_TxCpltCallback()),并且该函数被正确调用。如果回调函数没有实现或没有正确调用,可能会导致你无法观察到传输完成的中断。


8. 检查SPI和DMA的硬件连接



  • 确保SPI和DMA的硬件连接正确,尤其是SPI的MOSI、MISO、SCK和NSS引脚是否正确连接到目标设备。


9. 使用调试工具



  • 使用调试工具(如ST-Link)来单步调试代码,观察SPI和DMA的寄存器状态,看看是否有任何异常。


10. 检查CubeMX配置



  • 重新检查CubeMX的配置,确保所有相关的外设和引脚配置正确。有时候,CubeMX的配置可能会遗漏某些关键设置。


示例代码


以下是一个简单的示例代码,展示了如何使用HAL_SPI_Transmit_DMA()函数进行32位数据的SPI传输:


// SPI和DMA初始化
void SPI2_Init(void)
{
    hspi2.Instance = SPI2;
    hspi2.Init.Mode = SPI_MODE_MASTER;
    hspi2.Init.Direction = SPI_DIRECTION_2LINES;
    hspi2.Init.DataSize = SPI_DATASIZE_32BIT;
    hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
    hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
    hspi2.Init.NSS = SPI_NSS_SOFT;
    hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
    hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
    hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
    hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    hspi2.Init.CRCPolynomial = 10;
    if (HAL_SPI_Init(&hspi2) != HAL_OK)
    {
        // 初始化错误处理
    }

    // DMA配置
    hdma_spi2_tx.Instance = DMA1_Stream0;
    hdma_spi2_tx.Init.Channel = DMA_CHANNEL_0;
    hdma_spi2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_spi2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi2_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_spi2_tx.Init.Mode = DMA_NORMAL;
    hdma_spi2_tx.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_spi2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_spi2_tx) != HAL_OK)
    {
        // 初始化错误处理
    }

    __HAL_LINKDMA(&hspi2, hdmatx, hdma_spi2_tx);
}

// SPI传输完成回调函数
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
    if (hspi->Instance == SPI2)
    {
        // 传输完成处理
    }
}

// 主函数
int main(void)
{
    HAL_Init();
    SystemClock_Config();
    SPI2_Init();

    uint32_t data = 0x12345678;
    HAL_SPI_Transmit_DMA(&hspi2, (uint8_t*)&data, 1);

    while (1)
    {
        // 主循环
    }
}

总结


通过以上步骤,你应该能够找到并解决HAL_SPI_Transmit_DMA()函数初次发送时无法进入SPI中断的问题。如果问题仍然存在,建议逐步调试代码,检查每一步的状态和寄存器值,以确定问题的根本原因。

举报

更多回帖

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