0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

测试代码中使用DMA传输,定时器触发ADC

茶话MCU 来源:ST MCU 信息交流 2020-08-10 16:22 次阅读

有人在使用STM32G0芯片ADC模块时,往往因为扫描模式的理解不到位或选择不当导致些问题。这里就该话题做点简单分享介绍,不妨以一个实例展开。

现在共用到ADC1模块的4个ADC通道,即1个片内Vrefint通道和其它三个外部通道CH8,CH10,CH17。下面测试代码中使用DMA传输,定时器触发ADC.

它们的硬件连接情况如下,其中VRefint为内部参考电压,其电压值大概1.2V样子。

对于STM32G0系列,ADC扫描模式可以有两种,分别是不完全配置序列模式和完全配置序列模式。我们先看看不完全配置序列模式。

不完全配置序列模式

在该模式下,ADC_CFGR1寄存器中的CHESELRMOD位必须被清零。

被转换通道的扫描顺序按照ADC通道固有序号的大小顺序依次进行,扫描方向可以软件配置为向前【forward】或后退【backward】。任何ADC通道都可以配置进该序列中,总的序列长度由寄存器ADC_CHSELR中被置位的CHSELx个数决定,最多可配置18个通道。

我们以上面提到的CH8、CH10、CH17和VRefint通道【它对应ADC通道CH13】为例,若将上述4个通道配置为不完全序列模式,只需将ADC_CHSELR寄存器中的CHSELx相应位进行置1即可。如下图所示:

若选择forward扫描模式,则按通道号从小到大的顺序依次实施转换,生成对应于CH8、CH10、CH13、CH17的结果。使用STM32CubeMx的配置如下:

既然扫描按默认通道号大小顺序进行,自然就无须RANK顺序的配置了。

编译运行后可以看到结果,我在内存里放了两组数据以便比较观察。

从结果来看跟实际情况是一致的,转换结果依次来自CH8/CH10/CH13/CH17。其中那个149x数值来自对内部Vrefint的转换结果。

那么,对于同样的ADC通道及硬件连接,若采用完全配置序列模式会怎么样呢?

完全配置序列模式

在该模式下,ADC_CFGR1寄存器中的CHESELRMOD位必须被置1。

全序列可支持的通道数最多8个,扫描顺序不是依照硬件约定的通道号来安排,而是依据ADC_CHSELR寄存器中的从SQ1[3:0]到SQ8[3:0]所选择的通道顺序进行,即按照我们在CubeMX或代码中配置的RANK顺序进行,不再涉及扫描方向forward/backward的配置,并且只有通道0 到 通道14可以被选择!

还有,当SQn[3:0]里的赋值等于0b1111,即0x0f时则该通道选择域以及后续SQn的通道选择无效。比方说,假设SQ3[3:0]的数据为0b1111,则表示从SQ3[3:0]开始直到SQ8[3:0]的通道选择无效。由于SQn[3:0]才4位,所有它也没法选择高于14的有效通道号。【请特别注意这些特性!】

看到这里,我们不禁想到前面预先安排的4个通道中的有个CH17,显然不适合这种模式。如果被错误地强行使用该模式,基于CubeMx配置和现有Cube库所产生的代码运行结果会怎么样呢?

先用CubeMX进行配置:

4个通道的扫描顺序配置如下,相比前面多了RANK顺序配置。

先撇开CH17合法性不谈,不难看出这里跟前面的扫描顺序配置有点不一样,这里的配置为我们提供了更多的自主性及便利性,转换扫描并不固定于通道号的顺序,具体由SQn[3:0]的配置选择决定。我这里让SQ1选择CH8,SQ2选择CH10,SQ3选择CH17,SQ4选择CH13,分别对应配置中的RANK1、RANK2、RANK3、RANK4顺序。

编译运行查看结果:

前面说过,CH17硬件上是接地的,显然此时对应于CH17的转换值【绿色箭头所指】跟实际情况完全不符,其它三个倒是跟实际情况吻合。409x对应CH8接VDD,0对应CH10接GND,149x对应内部vrefint。

我尝试将CH17接到VDD,转换结果还是跟实际情况还是完全不相符。

结合上面的介绍,我们知道对于完全配置序列模式不能选用高于通道14的通道号。我们不妨通过寄存器进一步看看,当我们错误地强行使用CH17时在现有库代码的情况下,对应的SQ3[3:0]真正的值是多少?到底选择了什么通道?还是CH17吗?

在调试环境下,打开通道选择寄存器,可以看到下面结果:

从上面通道选择寄存器不难看出,除了SQ3外,其它三个配置都是正确的,跟我们预设的通道是一致的。但是,SQ3被错误地配置为CH1了,也就是说上面看到的所谓CH17的转换结果都是来自CH1.难怪不论怎么改变CH17的外部连接时,SQ3选择通道所对应的转换结果没有相应变化,跟CH17的管脚电压也没啥关系。

看到这里有人可能会想,如果我们在前面规划ADC通道时把CH1同时规划进来、硬件上恰好也接地,这时就可能发生误判!这种巧合性的误判,有时可能给我们的调试带来极大隐患而一会半会又找不到原因。当然,具体会发生些什么要因具体应用而定。这里只是简单提醒下,就此打住。

总之,这点在STM32G0 ADC应用中是个很容易出错的地方,将本不该用在完全配置序列模式的通道被错误地强行使用,虽有转换结果,而转换结果却来自别的通道,往往为此觉得问题诡异、不可思议而备受折腾。

最后,稍微小结下。对于STM32G0系列的ADC模块来说,其ADC通道在被转换时涉及到转换序列配置问题,这里有两种转换序列配置模式,即不完全配置序列模式和完全配置序列模式。

所谓不完全配置序列模式,在进行多个通道AD转换时,转换顺序由各通道自身的硬件序列号和扫描方向决定,其中硬件序列号即CHn在数据手册里已经明确定义,扫描方向通过寄存器配置。整个转换序列可支持的通道数多达18个,没有被排除在外的通道。

而完全配置序列模式呢,在进行多个通道AD转换时,转换顺序由通道选择寄存器中通道选择域SQn[3:0]来决定,即按照SQ1,SQ2.。。。。SQ7,SQ8的顺序,而且SQn[3:0]只能选择CH0到CH14的通道,整个序列最多支持8个通道。显然,CH15~CH18不能使用该模式。

说到这里,或许有人会问,如果只使用1个ADC通道,还有这个转换序列模式的选择问题吗?你把1个通道看成一个特殊的转换序列来理解就知道有没有这个模式选择问题了。

芯片设计人员在此提供了两种转换序列模式,本意旨在让我们能在实际应用中可以根据实际需求灵活选择,然而,往往由于开发人员的惯性思维和无视手册导致在这个地方遇上点麻烦或困惑。在此分享之,祝君好运!

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • adc
    adc
    +关注

    关注

    95

    文章

    5646

    浏览量

    539411
  • 定时器
    +关注

    关注

    23

    文章

    3146

    浏览量

    112030
  • dma
    dma
    +关注

    关注

    3

    文章

    535

    浏览量

    99012

原文标题:STM32G0系列ADC扫描序列模式解读

文章出处:【微信号:stmcu832,微信公众号:茶话MCU】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    调试STM32的adc单通道DMA传输时,DMA传输后就出现值变了的原因?

    这次在调试STM32的adc单通道DMA传输时出现了一个很大的问题。 直接去读取ADC的DR是没问题的,但是过来DMA
    发表于 04-22 06:03

    使用dma的方式来传输定时器输入捕获的数据,是不是每隔100ms会触发dma传输完成中断?

    目前使用dma的方式来传输定时器输入捕获的数据,内存数据大小为2,使用normal模式,100ms打开dma模式,请问,这种情况下,是不是每隔100ms会触发
    发表于 04-18 07:47

    STM32通过DMA方式传输TIM3定时器计数值,数值重复是为什么?

    AD值防止数据错乱,故DMA配置必须放在ADC之前。) 因此为了排除相同原因导致的数据重复,所以将DMA配置放在TIM3定时器初始化之前。 结果反馈,TIM3计数
    发表于 04-10 06:50

    信号通过ADC DMA DAC进行转换,非空状态下触发定时器中断进行延时,中断结束还会继续DMA转换吗?

    信号通过ADC DMA DAC进行转换,其中需要延时 我的想法是 把ADC数据存入FIFO,然后根据DMA_GetFIFOStatus()函数判断FIFO状态,非空状态下
    发表于 04-03 08:06

    STM8L151如何配置定时器2触发ADCDMA传输

    (REMAP_DMA1Channel_ADC1ToChannel0); DMA_Init(DMA1_Channel0, BUFFER_ADDRESS,//缓冲区地址 ADC1_D
    发表于 04-02 06:23

    请问如何使用定时器的更新事件触发DMA读取6字节SPI数据?

    想用定时器的更新事件触发DMA读取SPI数据,现在有个问题是一次更新事件只能触发一次DMA传输
    发表于 03-29 06:16

    HAL_ADC_Start_DMA函数为什么无法进行第二次触发

    我使用定时器触发adc采集 使用dma传输dma传输
    发表于 03-26 07:31

    STM32L0使用定时器上升沿触发ADC采样时,采样频率如何确定?

    我想问一下,在使用定时器上升沿触发ADC采样时,采样频率如何确定,是定时器频率就等于ADC采样频率吗?用的是STM32L0
    发表于 03-20 06:37

    定时器触发ADC+DMA采集数据将信号发生给的正玄波通过串口打印出来,有的波形为0为什么?

    目前是想先利用定时器触发ADC+DMA采集数据将信号发生给的正玄波通过串口打印出来,但是波形有一部分为0,是为啥呢,代码如下: MX_GP
    发表于 03-19 06:50

    STM32U575定时器PWM触发DMA搬运内存时,为什么程序在DMA中断里出不来?

    STM32U575 定时器PWM触发DMA搬运内存,为什么程序在DMA中断里出不来?
    发表于 03-12 08:33

    STM32H7做的项目,使用HAL_DMA_Start_IT,但是DMA是以最快的速度传输,并不受定时器周期控制?

    使用STM32H7做的项目,想要用定时器的溢出事件,触发DMA将GPIO的状态传输到内存上。 使用HAL_DMA_Start_IT,但是
    发表于 03-11 07:23

    如何使用定时器触发器进行SPI DMA传输

    我正在做一个项目,在这个项目中,我必须在 DMA 模式下通过 SPI 定期传输数据。 为了避免 CPU 干预,我想使用计时触发器触发 SP
    发表于 01-30 08:08

    定时器触发3路ADC同时采样指定次数

    定时器触发3路ADC同时采样指定次数控制3路ADC相等时间间隔,采样N次。
    发表于 10-19 08:30

    利用定时器触发ADC+DMA采集数据将信号发生给的正玄波通过串口打印出来,波形有一部分为0的原因?

    目前是想先利用定时器触发ADC+DMA采集数据将信号发生给的正玄波通过串口打印出来,但是波形有一部分为0,是为啥呢,代码如下: MX_GP
    发表于 08-07 14:16

    求助,为LPC55S69寻找带DMA定时器驱动ADC示例

    我正在寻找一个示例来演示使用 DMA 设置定时器驱动的 ADC 转换以存储样本的正确方法。 所有提供的示例仅使用软件触发器。我不确定 DMA
    发表于 05-16 07:18