STM32用户开发产品,使用模数转换器模块,通过定时器更新事件触发模数转换,转换结果通过直接内存存取方式传输到指定的内存区域。直接内存存取工作在正常模式(即非循环模式)。传输一批数据后,在传输完成中断中设置传输结束标志,该标志由应用程序代码监控。
当检查有效标志时,获取预定的转换数据。处理完数据后,软件会生成一个TIMER更新事件,以确保计数器从0开始计数[注意:此处选择的向上计数模式]。然后,更新事件标志和模数转换器转换完成标志位EOC被清除,DMA在DMA关闭后被重新配置,并且DMA在第二次传输时再次使能。
在调试期间,发现对于第二次DMA传输,一旦DMA被启用,就立即传输一个数据。理论上,在传输第一个数据之前,应该延迟一个定时器更新周期。由于用于触发模数转换器的定时器在软件设置UG后从0开始计数,因此只有在计数溢出后才会触发模数转换。他不明白的是TIM已经复位并从0开始计数,并且清除标志位已经被清除。在定时器触发之前,还有什么原因导致DMA携带数据?
该问题源于STM32论坛,但用户没有发布任何代码。这里我们模拟他的应用场景做一个测试和验证,并试图找出相关的原因。
我还在这里设计了两轮DMA传输,并且仍然使用定时器更新事件来触发ADC转换。第一轮DMA传输将3个AD转换结果传输到某个存储器地址,第二轮将5个转换结果传输到另一个存储器位置。
首先,使用Stm32CubeMx基于STM32F411Discovery板执行基本初始化配置。配置非常简单。
模数转换器配置,这里只选择一个常规通道进行测试,选择TIM2的触发输出开始模数转换,模数转换器的直接内存存取转换功能开启,直接内存存取工作在正常模式。[一号直接将VDD连接到硬件上的模数转换器输入通道]
定时器配置,此处选择TIM2,其更新事件用作启动模数转换器的触发输出。
配置完成后,生成初始化代码,然后添加用户代码。
这里准备了几个内存变量。
在第一次直接存储器存取传输完成后,我立即关闭了定时器,并且在开始第二次直接存储器存取传输之前,不允许定时器有机会触发模数转换器再次产生平机会事件。让我们看看是否还发生了什么。
我将用户代码分为两部分,分别用红色和绿色的方框表示。
第一部分包括基本初始化功能、开启模数转换器外设及其直接内存存取功能、为第一次直接内存存取传输配置并启用直接内存存取,以及等待三次模数转换器转换结束。
代码第二部分的功能主要是关闭定时器和DMA,第二次配置DMA,打开DMA功能,启动定时器。[:我在箭头所指的点,也就是计数器将要启动的代码处,碰到了断点]
基于上述代码测试,一旦第二次DMA传输被启用,就不存在首先传输一个数据的现象。此时,计时器尚未启动,直接内存存取处于就绪待机状态。[结果如下]
顾客的反馈到底是什么?
因为他没有看到用户的具体代码,他说在第一次DMA传输后,他还重置了计时器。然后,我们不妨在第一次DMA传输后给定时器添加一个复位操作,看看会发生什么。
我稍微修改了第二部分中的代码,如下所示[见下图中a处的代码] :
基于调整后的代码,测试还发现当第二次DMA传输被启用时,首先传输一个数据的现象。然而,此时计时器仍未启动,那么DMA是如何开始传输数据的呢?[结果如下图所示]
当然,纯粹从DMA传输功能来看,它不一定与定时器是否启动有关。对于已启用的直接内存存取,只要有适当的直接内存存取要求,它就会运作。特别是这里,直接内存存取传输应该只发生在平机会事件发生的时候。平机会事件从何而来?
我们不妨先推理一下:
第一次直接内存存取传输完成后,不能再处理任何平机会事件。在第一次码分多址传输期间,每次码分多址读取模数转换器数据时,平机会被清零,并且在码分多址传输完成后,定时器立即关闭。在这种情况下,没有什么会影响计时器的快速关闭。从理论上讲,不会有定时器更新事件来触发二次码分多址传输之间的模数转换,更不用说在启用第二次码分多址之前的平机会清零。
这看起来确实有点奇怪,用客户的话来说,你觉得有一个DMA请求,像是它潜伏在哪里?
与初始代码相比,当前代码有一个额外的定时器复位操作。该复位操作是否会导致模数转换器转换产生平机会事件?说到这,它真的有这种能力。
因为软件重置定时器也可以生成更新事件,它可以只启动AD转换[AD转换功能还没有关闭]来生成EOC事件。如果EOC标志未及时清除,即使计数器尚未启动,也可以在下一次DMA传输启用后立即触发DMA传输。
通过这里的分析,我觉得我已经找到了问题的原因。然而,似乎有些不对劲。因为即使定时器复位动作产生一个更新事件并触发模数转换器转换,从而产生一个平机会事件,我们在定时器复位动作后特别清除了平机会标志。[下图中第二个红色圆圈中的代码]
这个平机会旗帜清除行动有问题吗?
首先确认代码编写本身,没问题。再看看逻辑和时间问题。
通过进一步调试,在下图所示的代码中放置了三个断点,以便一步运行。事实上,我们发现定时器复位事件触发了模数转换器转换,并设置了平机会。在随后的代码中,也发现了清除的EOC。有趣的是,当运行下图所示的3个断点时,奇怪的现象消失了,潜在的DMA请求似乎隐藏了起来。
如果您取消上面的第一个和第二个断点并运行代码,这种现象将立即重新出现,而潜在的断点将再次被激活。
这里反复验证,基本上明白是怎么回事了。
毫无疑问,定时器的复位操作会导致模数转换和平机会事件。虽然代码中有明确的EOC操作,但对模数转换器来说为时过早。也就是说,当删除平机会时,模数转换器可能仍在忙于转换,这离平机会事件发生还有很长时间。这可以准确地解释为什么在重置操作代码后设置断点,然后删除EOC是有效的。
在这种情况下,我会在清除平机会操作码前添加平机会标志进行查询和等待,以确保后续清除操作的可靠性和有效性。我又调整了代码。请看下面方框中的代码。
在验证修改后的代码后,这种现象完全消失了。接下来的第二轮DMA传输也很有序。
这个应用案例的共享到此结束。最后,做一个简短的总结和一些提醒:
1.STM32定时器的软件复位操作可以产生一个更新事件,其效果相当于定时器溢出引起的更新事件。
2.在编写代码,特别是嵌入式代码时,除了要保证代码的基本正常逻辑外,还要注意每个硬件本身的操作时序和响应时间参数。
3.结合这种情况,在第一次DMA传输完成后准备第二次DMA时,建议先关闭计数器,否则会给我们的应用带来一些隐患。本案中讨论的问题是其中一个隐患。受空间和主题的限制,我们不会在这里谈论它,如果有合适的情况,我们会在以后交换它。
防控疫情的需求激发之下,代替人类送药、送餐送菜、消毒巡逻的无人车成了疫情期间的特殊尖兵。疫情过后,无人车配送是否...
2020-03-23 17:12市场分调研机构Omdia的最新数据分析显示,全球智能城市人工智能(AI)软件市场将从6 738亿美元(2019年),在2025年将增长到4...
2020-04-07 17:55现代电测技术日趋成熟,由于具有精度高、便于微机相连实现自动实时处理等优点,已经广泛应用在电气量和非电气量的测量中。
2020-04-07 17:56微软经常在游戏领域开辟路径,扮演开拓者的角色,这一点体现在很多方面,包括微软的尖端技术(DX12终极版 DX光追),硬件(X...
2020-04-07 17:57去年 12 月,波音为美国宇航局发射了未载人的 Starliner 航天器。然而由于技术问题,任务并没有按计划进行。作为 NASA ...
2020-04-07 17:58