你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【已解决】ADC的DMA中断内为什么要先stop(ADC)?

[复制链接]
Rancho1122 提问时间:2024-8-21 17:44 / 已解决

void DMA1_Channel1_IRQHandler(void) {

HAL_DMA_IRQHandler(&hdma_adc1);

//这里省略其他处理代码(读DMA值, 环路运算等)

HAL_ADC_Stop(&hadc1);

HAL_ADC_Start_DMA(&hadc1, (uint32_t *)u32ADC_Value_DMA, 8); }

如上,STM32G474,HRTIM_A触发ADC采样,ADC配置中使能了DMA(normal模式),然后我在DMA中断内获取采样值。

为什么在DMA中断的最后要加stop(ADC)和start(DMA)呢?如果没有这两句话,就无法正常进入该DMA中断。按理说我已经配置了HRTIM_A(65K)触发ADC,ADC会以65K频率自动触发采样,自动进DMA中断。

有没有大神解释一下~

收藏 评论4 发布时间:2024-8-21 17:44

举报

4个回答
xmshao 回答时间:2024-8-23 13:11:48
看样子,你是找到方法了要觅原因。


我这边模拟你的应用场景,做了验证测试。可以重现你的问题。


首先,你现在的DMA工作在Normal模式,每次传输一轮数据后DMA会自动停下来,所以重启DMA是必须的。


但是,你更大的疑惑点可能在于为什么启动ADC的DMA传输要先停止AD模块。


原因就是,当你启动ADC后,数据传输由DMA传输相应个数数据后就停下来了。但AD并没有停下来,而在你目前


调用的API库函数里恰好就有对AD工作状态的检测。见下面代码:


if (LL_ADC_REG_IsConversionOngoing(hadc->Instance) != 0UL) { tmp_hal_status = HAL_BUSY;return tmp_hal_status; }


如果检查到AD还在工作,则表示此时AD在忙碌,程序没有完成相应初始化而是直接基于busy状态返回退出,所以后续的ADC数据没法完成传输。


强调一下,这是基于库函数的应用逻辑。我们自行组织代码时可能就不一定要这么做。它这么做有好处,


每次开启ADC及DMA传输时尽可能是从头开始,便于数据管理等。
xmshao 回答时间:7 天前

既然DMA配置在Normal模式,DMA每完成一轮数据的传输后会自动停下来。想再使用它的话需重新配置和使能。如果明白了这点,对为什么需要再次[调用启动]()ADC的DMA传输的API函数HAL_ADC_Start_DMA()就可以释怀了。

那另一个疑惑就是,为什么在调用该API函数前还有调用HAL_ADC_Stop()函数关闭ADC呢?

我们可以点进HAL_ADC_Start_DMA()函数里面去看看,可以很快发现在该函数的入口处就有对ADC是否处于运行态的检查。如果检查到当前ADC处于工作态,即busy态就马上退出函数,而不做后续的DMA配置及其它ADC相关处理。

Rancho1122 回答时间:5 天前

xmshao 发表于 2024-8-23 13:11
看样子,你是找到方法了要觅原因。</p>
<p>

明白了,非常感谢!👍

Rancho1122 回答时间:5 天前

xmshao 发表于 2024-8-25 22:20
既然DMA配置在Normal模式,DMA每完成一轮数据的传输后会自动停下来。想再使用它的话需重新配置和使能。 ...

明白了,非常感谢!👍

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版