在介绍之前,先介绍一下STM32F103 TIM的一些相关特性:
无法使用外部引脚中断触发DMA(某些型号可以) 无法使用TIM 同时捕获上升沿和下降沿。您在库中看到的宏实际上在使用上受到限制。高级定时器1、8,通用定时器2、3、4、5不可用,一般103只有这几个定时器。
3、当输入高频信号时,进入中断非常频繁。如果频率为100K,则需要每5us输入一次(高低电平各输入一次,或者占空比为50%时,其他占空比条件更苛刻),如果使用中断处理,则必须在中断中完成很多操作(清除标志、计算、翻转极性等),并且需要保证这两个中断不能被全局中断禁止或者被高优先级中断打断。否则,您得到的可能不是脉冲的高电平,因此您的占空比和频率将被错误计算。
由于存在上述问题,并且捕获PWM脉冲是一个比较常见的功能,因此需要一个高效的捕获程序来完成这项工作。我认为今天Osprey介绍的实现原理是最高效的。
100K频率误差0%,占空比误差1%!
在嵌入式系统中,100K的频率已经是比较高的了。当然,在关注占空比时,如果只关注频率,可测量的频率会更高。
有人可能会争论说,为什么不使用FPGA呢? Osprey当然知道有比单片机更有效的捕获设备,因为我自己买的逻辑分析仪(如果你想买这个,可以用Osprey预订,可以给你一定的折扣。预订数量需要超过10)可以捕获非常高的频率。准确性,但问题是成本,有必要吗?这个逻辑分析仪要几百大洋。
废话不多说,Osprey首先介绍一下这种捕获方式的基本原理。
很简单,就是利用二进制溢出特性来实现的。 (问题2038 - GIF)
Osprey在笔记中也多次介绍过该功能的应用,比如无锁队列、扩展定时器、编码器、延时等。今天我们再补充一个应用,PWM捕获(本笔记不介绍这个原理)功能。您可以查看历史注释)。
可以说了解了这个特性,在各种整数数据处理上更是如虎添翼。我不再担心数据溢出的问题。相反,我必须利用这个功能来完成一些很酷的操作,比如今天的PWM 捕获。
另一个技巧是使用DMA,这就是它高效且可靠的原因。
首先我们看一下定时器的框图:
上面标记的部分就是为什么PWM 输入模式只能使用通道1 或通道2。
这里以TI1 作为PWM 输入,两个捕获通道同时捕获TI1 为例。
基本配置如下:
捕捉通道1触发DMA,同时设置捕捉上升沿。这样,只要上升沿触发,就可以自动完成捕获并DMA传输到用户缓冲区。通道2下降沿捕获,不触发DMA。配置DMA,将外设地址不是传输到某个寄存器,而是传输到DMAR,并设置传输次数,必须是2的倍数,因为需要一次传输两次,32位宽度。由于CCRx需要发送两次,因此需要正确设置DCR寄存器。以上配置是整个功能中最关键的部分。如果你了解了下面介绍的捕获原理,自然就知道为什么需要这样设置了。
我们先看一下PWM捕捉的基本工作流程:
另外,还需要了解TIM的一个非常重要的DMA传输特性:通过配置寄存器,可以一次触发多个DMA连续传输,这个函数中也用到了这个特性。
如何利用这个功能?一般我们配置DMA传输时,比如串口,一般外设地址就是DR寄存器。如果我们想传输捕获的TIM值,我们可以将其设置为CCR1寄存器的地址。
这个也可以正常传输,但是触发时只能传输一个寄存器的值。如果需要传输两个捕获的值,则需要配置两个DMA通道才能完成,但这里又涉及到两个DMA通道的同步问题。因为你肯定希望每次采集的两个数据属于同一个脉冲。
所以TIM就是利用这两个寄存器来解决这个问题的。通过**DMAR传输**,可以完成一次触发,连续传输两个CCR的值。
想必看到这里你应该大概知道捕获的原理是什么了。
这里就根据上图来介绍一下Osprey。
初始化(定时器、DMA、GPIO)完成后,定时器就可以工作了。一旦有脉冲输入,上升沿触发。此时,由于设置了DMA触发,并且设置了连续传输的两个寄存器,因此会将当前的CCR1和最后捕获的CCR2(下降沿触发)传输到用户缓存中。这是两次DMA 传输,因此DMA 计数器将递减两次。并且CCR1的值比CCR2的值大(不考虑溢出,并且在差异的情况下,大小没有意义)。这样,对于上面的三个触发器,我们就可以得到三组捕获的数据。
通过(uint16_t)(CCR1 CCR2)可以得到低电平,通过两个CCR1或CCR2的差值可以得到周期。这样计算频率和占空比并不困难。特别需要注意的是,定时器在三个上升沿捕获周期内不能溢出。这可以通过定时器分频来实现。分频系数越小,分辨率越高,但也越容易溢出。
这里需要注意的是,如果频率比较高,建议多测量几组数据,然后取接下来的几组数据进行简单的平均或中值计算(具体根据捕获的值来确定),这样精度就更高了,因为一开始可能是因为初始化导致误抓,这是有可能的(一开始也不确定,可以先测试64组)。
另外,如果输入的PWM频率或占空比会不断变化,还需要根据情况进行几组测量(或定时测量),并进行简单的处理,这样就不容易捕捉到变化的脉冲保证脉冲计算的可靠性。
总之,如何让你的程序更加可靠,就看各位道友了。 Osprey只是提供了一个解决方案。另外,Osprey不准备向道友提供源码,请放心使用。如果确实有需要,在本文更新之前,如果道友已经表示赞赏或者留言支持,也可以主动联系Osprey,Osprey可以提供参考方案,仅供参考。如果您以前没有,请不要寻找Osprey。