本文介绍了使stm32 ADC DMA工作的缺失是什么?不会发生转让竞争的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用stm32f3发现板和来自CubeMX的HAL.我正在尝试在ADC4使用2个ADC通道.我将DMA配置为循环模式.在main中的主循环之前,我调用:

HAL_ADC_Start_DMA(&hadc4, DMA_adc4_buffer, 16);

我实现了功能HAL_ADC_ConvHalfCpltCallbackHAL_ADC_ConvCpltCallback.现在奇怪的部分:HAL_ADC_ConvHalfCpltCallback被定期调用,HAL_ADC_ConvCpltCallback不是.

它告诉我,具有DMA传输的ADC运行正常.但是为什么不调用竞争回叫?如果我用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的时钟为48 MHz,核心时钟仅为12 MHz.函数HAL_DMA_IRQHandler首先检查中断标志的一半传输是否完成,然后按照样式

进行传输完成

if (half transfer complete){
  HAL_ADC_ConvHalfCpltCallback();
} **ELSE** if (transfer complete){
  HAL_ADC_ConvCpltCallback();
}

由于ADC/DMA总是将半传输中断标志设置得如此之快,而处理器却是如此之慢,因此内核永远不会进入秒分支,因此也就永远不会调用ConvCpltCallback().

I am using a stm32f3 discovery board and the HAL from CubeMX. I am trying to use 2 ADC channels at ADC4. I configured DMA in circular mode. Befor the main loop in main, I call:

HAL_ADC_Start_DMA(&hadc4, DMA_adc4_buffer, 16);

I implemented the functions HAL_ADC_ConvHalfCpltCallback and HAL_ADC_ConvCpltCallback. Now the strange part: HAL_ADC_ConvHalfCpltCallback is called regularly, HAL_ADC_ConvCpltCallback is NOT.

It tells me, that the ADC with DMA transfer is running fine. But why is transfer compete callback not called?If I start the ADC with HAL_ADC_Start_IT the interrupt function is called, but that is not what I want.

Putting breakpoints in HAL_DMA_IRQHandlerin the ST HAL also shows, that the callback is never called.

For completeness here parts of the ADC4_Init function:

/**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;

Thank your for ideas.

解决方案

The problem was that the clock of the ADC was 48 MHz, the core clock only 12 MHz. The function HAL_DMA_IRQHandler checks frst for the interrupt flag for half transfer complete, then for transfer complete in the style

if (half transfer complete){
  HAL_ADC_ConvHalfCpltCallback();
} **ELSE** if (transfer complete){
  HAL_ADC_ConvCpltCallback();
}

Since half transfer interrupt flag is always set so fast by the ADC / DMA and the processor is so slow, the core never comes to the seconds ìfbranch and thus never calls the ConvCpltCallback().

这篇关于使stm32 ADC DMA工作的缺失是什么?不会发生转让竞争的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

06-13 14:26