让 stm32 ADC DMA 工作缺少什么?转会竞争不会发生
What is missing to make stm32 ADC DMA work? Transfer Compete does not occur
我正在使用 stm32f3 发现板和来自 CubeMX 的 HAL。我正在尝试在 ADC4 上使用 2 个 ADC 通道。我在循环模式下配置了 DMA。在 main 的主循环之前,我调用:
HAL_ADC_Start_DMA(&hadc4, DMA_adc4_buffer, 16);
我实现了函数 HAL_ADC_ConvHalfCpltCallback
和 HAL_ADC_ConvCpltCallback
。现在奇怪的部分是:HAL_ADC_ConvHalfCpltCallback
被定期调用,HAL_ADC_ConvCpltCallback
不是。
它告诉我,带 DMA 传输的 ADC 运行 没问题。但是为什么不调用transfer compete callback呢?
如果我用 HAL_ADC_Start_IT
启动 ADC,则会调用中断函数,但这不是我想要的。
在 ST HAL 中的 HAL_DMA_IRQHandler
中放置断点也表明,永远不会调用回调。
为了完整起见,ADC4_Init 函数的部分内容:
/**Common config
*/
hadc4.Instance = ADC4;
hadc4.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc4.Init.Resolution = ADC_RESOLUTION_12B;
hadc4.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc4.Init.ContinuousConvMode = ENABLE;
hadc4.Init.DiscontinuousConvMode = DISABLE;
hadc4.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc4.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc4.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc4.Init.NbrOfConversion = 2;
hadc4.Init.DMAContinuousRequests = ENABLE;
hadc4.Init.EOCSelection = ADC_EOC_SEQ_CONV;
hadc4.Init.LowPowerAutoWait = DISABLE;
hadc4.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
感谢您的想法。
问题是ADC的时钟是48MHz,核心时钟只有12MHz。函数HAL_DMA_IRQHandler首先检查半传输完成的中断标志,然后以
的方式检查传输完成
if (half transfer complete){
HAL_ADC_ConvHalfCpltCallback();
} **ELSE** if (transfer complete){
HAL_ADC_ConvCpltCallback();
}
由于 ADC / DMA 总是将半传输中断标志设置得如此之快,而处理器又如此之慢,因此内核永远不会到达秒 ìf
分支,因此永远不会调用 ConvCpltCallback()。
我正在使用 stm32f3 发现板和来自 CubeMX 的 HAL。我正在尝试在 ADC4 上使用 2 个 ADC 通道。我在循环模式下配置了 DMA。在 main 的主循环之前,我调用:
HAL_ADC_Start_DMA(&hadc4, DMA_adc4_buffer, 16);
我实现了函数 HAL_ADC_ConvHalfCpltCallback
和 HAL_ADC_ConvCpltCallback
。现在奇怪的部分是:HAL_ADC_ConvHalfCpltCallback
被定期调用,HAL_ADC_ConvCpltCallback
不是。
它告诉我,带 DMA 传输的 ADC 运行 没问题。但是为什么不调用transfer compete callback呢?
如果我用 HAL_ADC_Start_IT
启动 ADC,则会调用中断函数,但这不是我想要的。
在 ST HAL 中的 HAL_DMA_IRQHandler
中放置断点也表明,永远不会调用回调。
为了完整起见,ADC4_Init 函数的部分内容:
/**Common config
*/
hadc4.Instance = ADC4;
hadc4.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc4.Init.Resolution = ADC_RESOLUTION_12B;
hadc4.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc4.Init.ContinuousConvMode = ENABLE;
hadc4.Init.DiscontinuousConvMode = DISABLE;
hadc4.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc4.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc4.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc4.Init.NbrOfConversion = 2;
hadc4.Init.DMAContinuousRequests = ENABLE;
hadc4.Init.EOCSelection = ADC_EOC_SEQ_CONV;
hadc4.Init.LowPowerAutoWait = DISABLE;
hadc4.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
感谢您的想法。
问题是ADC的时钟是48MHz,核心时钟只有12MHz。函数HAL_DMA_IRQHandler首先检查半传输完成的中断标志,然后以
的方式检查传输完成if (half transfer complete){
HAL_ADC_ConvHalfCpltCallback();
} **ELSE** if (transfer complete){
HAL_ADC_ConvCpltCallback();
}
由于 ADC / DMA 总是将半传输中断标志设置得如此之快,而处理器又如此之慢,因此内核永远不会到达秒 ìf
分支,因此永远不会调用 ConvCpltCallback()。