请选择 进入手机版 | 继续访问电脑版

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

STM32F103 ADC利用DMA进行采样问题求解

[复制链接]
烦恼的维特_TI 提问时间:2024-6-8 15:36 / 已解决

STM32F103配置了ADC1 的4个通道,利用定时器的事件触发进行10Hz 的数据采样,数据通过DMA传输。然后希望每次采样4*50个数据后触发DMA的中断进行数据的处理。

根据教程进行了相关的配置后,遇到了2个问题:

1 定时器配置成10hz,但是每次启动采集后基本马上就能进入DMA的回调函数,里面数据已经刷满了,所以感觉ADC的采样频率似乎不是收定时器触发的。

2DMA的回调函数HAL_ADC_ConvHalfCpltCallback,HAL_ADC_ConvCpltCallback,应该是数据完成一半数量的采集后触发第一个回调,全部采集后再触发第二个回调,但是实际上每次都是在第一个回调中数据就全部刷新了,采样完成的回调中不会有新的数据刷新。

1717831884505.jpg

1717831912242.jpg1717831901247.jpg

希望有人能帮忙指点下,谢谢

收藏 评论10 发布时间:2024-6-8 15:36

举报

10个回答
butterflyspring 最优答案 回答时间:2024-6-12 15:34:06
这边抽空跑了一下,你的现象我也看到了。

实际上运行是没问题的。
1. 这个现象是因为调试暂停时,定时器的计数器并没有暂停(中断服务程序停下来),所以更新事件的触发信号还是  继续给的,ADC 继续转换。当暂停时,把数据又转换了一些。
2. 可以通过两种方式验证。 一是观察定时器计数值,当单步运行时,每一步的计数值远远大于理论事件
    二是讲触发间隔事件拉长到秒级以上,会发现单步走时不断有数据转换进来的。

STM32F1 TIMER3 TRIGGER ADC.PNG

xmshao 回答时间:2024-6-17 13:20:55

烦恼的维特_TI 发表于 2024-6-13 21:40
你好,目前我就是希望每个定时器事件能够触发一次采集,每次扫描采集4个ADC通道。但是给我的感觉是, ...

[md]你的理解没有问题。即每次TIMER触发,ADC就做4次扫描转换。

如果你是非连续模式,按照你的代码,每触发50次,也就是得到200个数据后 进入DMA完成中断。

如果是连续模式,TIMER触发一次后,后面的触发就无效或不必要了。

你要检查代码逻辑方面问题,或者哪里误会了,尤其时间计算上。

xmshao 回答时间:2024-6-11 20:31:02
你现在是觉得ADC的转换不像是TIMER触发的,从你目前的配置来看,也不能说完全不是TIMER触发的。


你的ADC的启动应该是TIMER触发的,不过TIMER的每次触发后,几个ADC通道基于扫描模式,会依照他们
自己的节奏进行转换,这个过程的确跟TIMER就没有什么关系。


如果你希望,TIMER触发一次就转换1个通道,你就得调整ADC的配置,4个通道的扫描模式不动,但要配置为
间断转换模式,每次TIMER触发只转换一个通道,依次进行。这样ADC的转换就按照TIMER的触发节奏来走了。


关于ADC的间断转换,或称分组转换,可以参考下这篇 《STM32 ADC间断转换模式应用示例》。
烦恼的维特_TI 回答时间:2024-6-13 21:40:53

xmshao 发表于 2024-6-11 20:31
你现在是觉得ADC的转换不像是TIMER触发的,从你目前的配置来看,也不能说完全不是TIMER触发的。</p>
<p>

你好,目前我就是希望每个定时器事件能够触发一次采集,每次扫描采集4个ADC通道。但是给我的感觉是,没次定时器的间隔时间理论上是0.1s,然后HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc1_data, 200);应该是采集50次后触发HAL_ADC_ConvHalfCpltCallback回调,再触发50次后触发HAL_ADC_ConvCpltCallback。不知道我的理解对不对。

如果我的理解没问题的话,那么每次开始采集后,至少要过5s左右才能进入回调函数。但是实际上基本1s 不到就进去了。

所以我觉得很奇怪

烦恼的维特_TI 回答时间:2024-6-13 21:46:24

butterflyspring 发表于 2024-6-12 15:34
这边抽空跑了一下,你的现象我也看到了。</p>
<p>实际上运行是没问题的。

谢谢,这个方式我验证下。这几天我在调试时还发现个现象,就是吧回调函数直接放在main.c下面时候,确实每个5s左右会触发一次回调函数,然后每次都能有200个数据刷新出来,然后我将回调函数放到单独的一个c文件后,就会出现HAL_ADC_ConvHalfCpltCallback这个回调函数基本还是5秒左右进入一次(能够刷新200个数据),但是这个函数执行完后后基本马上进入HAL_ADC_ConvCpltCallback(但是不会有数据刷新),而不是要过5s左右。(HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc1_data, 200);我的理解没5s进入一次half回调,刷新200个数据,然后过5s进入另外一个回调,刷新200 数据。)

你的方法我也再尝试下。但是不知道我对ADC的这个配置的理解是否正确

烦恼的维特_TI 回答时间:2024-6-13 22:33:55

butterflyspring 发表于 2024-6-12 15:34
这边抽空跑了一下,你的现象我也看到了。</p>
<p>实际上运行是没问题的。

你好,根据你提供的建议,我将定时器改成1s,发现正如你说说,在HAL_ADC_ConvHalfCpltCallback,中可能先刷新一般的数据,但是这个时候定时器并没有停止工作,还在不停的触发ADC进行转换,所有随着我在这个回调函数中停留的时间越长,adc的buf里面的数据也在不停的刷新,所以当程序离开HAL_ADC_ConvHalfCpltCallback后会马上进入HAL_ADC_ConvCpltCallback,并给人没有刷新数据的错觉。

另外我想请教下

HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc1_data, 200);这个函数中200 ,是不是意味着当采集到100个数据后,会进入HAL_ADC_ConvHalfCpltCallback,当200个数据都采集完成后,会进入HAL_ADC_ConvCpltCallback。

然后还有个问题,如果我把ADC的模式改成连续转换模式,是否也可以由定时器进行触发采集来控制采集的频率?谢谢

butterflyspring 回答时间:2024-6-14 16:28:23
1.这个函数中200 是给DMA 计数器的,所以你后面的结论是正确的。



2. 如果改成连续转换模式,ADC触发后会持续转换,这样就与定时触发冲突了哦。
Glenxu 回答时间:2024-6-14 20:15:34

butterflyspring 发表于 2024-6-14 16:28
1.这个函数中200 是给DMA 计数器的,所以你后面的结论是正确的。</p>
<p>

如果不选连续转换,则速度非常慢!

烦恼的维特_TI 回答时间:2024-6-15 22:08:42

butterflyspring 发表于 2024-6-14 16:28
1.这个函数中200 是给DMA 计数器的,所以你后面的结论是正确的。</p>
<p>

好的,谢谢指导

烦恼的维特_TI 回答时间:2024-6-15 22:11:05

Glenxu 发表于 2024-6-14 20:15
如果不选连续转换,则速度非常慢!

嗯嗯,我就是想要定频率采集。

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