STM32 HAL DMA传输完成中断未触发问题排查咨询
Hey there! I've tackled similar DMA interrupt issues on STM32 F7 series before, so let's walk through what you need to check and clarify the callback timing question for you.
一、DMA传输完成中断未触发的排查点
Since your polling mode works fine, the DMA transfer itself is functional—so the problem lies in interrupt-related configurations. Here are the key checks:
- NVIC interrupt configuration validity: Polling mode doesn't rely on NVIC, but interrupt mode requires the DMA channel's interrupt to be enabled. If you used CubeMX, confirm the corresponding DMA channel interrupt is checked in the "NVIC Settings" tab. If configuring manually, ensure you've called
HAL_NVIC_EnableIRQ()(e.g., forDMA2_Stream7_IRQn) and set a reasonable priority viaHAL_NVIC_SetPriority()to avoid preemption by higher-priority interrupts. - Transmit complete interrupt enabled in DMA initialization: Check your
DMA_InitTypeDefstructure—did you setDMA_InitStruct.DMA_IT_TC = ENABLE;? The HAL library requires explicit enabling of DMA interrupt events (like transfer complete, half-transfer, or error). Without enablingDMA_IT_TC, the interrupt won't trigger even if NVIC is configured. - Callback function correctly registered/overridden: If using a custom callback, make sure you've registered it with
HAL_DMA_RegisterCallback(&hdma_x, HAL_DMA_XFER_CPLT_CB_ID, Your_Custom_Callback). If overriding the default callback, ensure the function name matches (e.g.,HAL_DMA_TxCpltCallback(DMA_HandleTypeDef *hdma)) and isn't overshadowed by the weakly defined version in the HAL library. - Peripheral DMA request association: Although polling works, double-check that the peripheral (e.g., UART, SPI) has its DMA request enabled. Usually, functions like
HAL_UART_Transmit_DMA()handle this automatically, but if configuring manually, verify the DMA enable bit in the peripheral's registers. - DMA channel-peripheral mapping correctness: The Nucleo-F746ZG has specific DMA channel/stream mappings for each peripheral. Confirm you're using the correct channel (e.g., USART1 might map to DMA2 Stream7)—a mismatched channel will prevent interrupt triggers.
二、DMA回调函数的设置时机
You only need to complete the callback registration before calling HAL_DMA_Start() (or peripheral-specific DMA start functions like HAL_UART_Transmit_DMA()), there's no requirement to do it before HAL_DMA_Init().
Here's why: HAL_DMA_Init() only initializes DMA hardware registers and basic handle structure configurations. Callback functions are stored as function pointers in the DMA handle. As long as you assign the callback address to the corresponding pointer in the handle before starting the DMA transfer, the HAL library will call it correctly when the transfer completes. In practice, many developers register callbacks after initialization but before starting transfers, and even dynamically re-register callbacks between transfers if needed—both approaches work.
内容的提问来源于stack exchange,提问作者Jack Berkhout

