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

STM32 上最强 PWM 捕获功能,1 MHz !

[复制链接]
STMCU-管管 发布时间:2021-8-25 15:15
起因
一直想通过定时器的捕获通道捕获 PWM,这种需求是非常基本的。各种开发板例程也都有,但是精度不怎么样,能捕获的频率也不是很高。对于高频和高精度情况下明显不适用。

有经验的工程师会选择参考手册中介绍的 PWM 输入捕获功能,但是该功能有一个很大的限制:

一个定时器有四个通道,但是只有两个通道才可以使用  PWM 输入捕获,这极大的限制了可用通道,而在有些需求中,定时器可用通道当然是越多越好。

所以鱼鹰一直在苦思冥想一个高精度的通用的 PWM 输入捕获程序。


领悟
一天晚上,鱼鹰一边洗衣,一边思考,终于灵光一闪,既然编码器功能可以借助两组通道完成编码器,为什么 PWM 输入捕获不能使用类似的机制呢?

手册中的 PWM 输入因为使用了 从模式 功能,才有上述限制,只要我不使用从模式,仅仅使用两个通道的捕获功能,就可以解除该限制了吧?

所以借助《如何高效的扩展定时/计数器?》里面介绍的知识,鱼鹰顿悟了……

效果
左边用逻辑分析仪设置的输出参数,右边通过捕获程序捕获的结果。
STM32F103,主频 72 Mhz,定时器时钟频率 72 MHz。
12.png

13.png

14.png

15.png

16.png



我们从上图可以知道,即使输入 PWM 频率高达 1 Mhz,我们的程序还是将其准确测量出来了。

当然在占空比计算方面,因为定时器频率自身的原因,计算的并不精确,和实际的误差比较大,不过在这么高的频率下,只是 10% 的误差,我认为还是可以接受的。


而频率达到 3 MHz 时,频率比较接近(4 % 误差),但是占空比已经出现了很大误差,已经不可用了(可能计算有点问题)。

100 K,占空比 5 % 的情况下,频率测量误差 0%,占空比误差 1%!!!


优缺点
由于时间与篇幅原因(花了很多时间做测试),本篇笔记不会介绍捕获原理(鱼鹰要写的话,一定会尽可能的介绍清楚,所以字数会比较多,目前时间不足),主要是想通过本篇介绍 F103 72Mhz 的情况下所能达到的极致效果,让各位在接任务时有一个概念,看是否能简单通过 103 完成功能。

现在简单介绍一下鱼鹰这个方案的优缺点:

优点:
1、不占用 CPU 资源,使用 DMA 与定时器捕获功能完成。
    而如果使用中断的方式,100KHz 下,10 us 就需要进入一次中断,基本不用干其他事情了。一旦中断被别的代码短暂禁用,错过了捕获,那计算的结果可能就有问题了。
2、可以分时使用定时器的四个通道,不会被所谓的从模式所限制,但能达到和手册介绍 PWM 输入捕获功能一样的精度。
3、可以捕获高频信号(MHz),并且精度高。
4、精度和定时器时钟频率有很大关系(F1  1/72 us),如果 F4 的芯片,定时器频率更高,那么可以达到更高的精度(可以算优点,也可以算缺点)。
5、因为采用 DMA 传输 + 硬件(定时器)方式,计算的结果可以信任,不需要太多的处理(比如滤波)。
6、单个通道可以达到很高的捕获率,甚至可以通过特定的算法进行实时捕获,而对 CPU 本身的影响却很小(即不占用 CPU 资源实时捕获计算)。
7、解除STM32定时器只能捕获上升沿或下降沿,而不能双边沿捕获的限制。

缺点:
1、只能分时测量每个通道的 PWM,不能同时测量(如果频率很高,几十个微秒就能切换 一次测量,问题不大)。
2、占用 DMA 传输通道,导致对应的通道的外设不能使用(比如串口)
3、代码很简单,但是很难理解(下面的代码计算了所有捕获,实际上只要计算几个就行,因为数据可以信任)。

  1. uint32_t cal_duty_cycle(capture_buff_def *buff, uint32_t size)
  2. {
  3.     assert_param(size > CCR_VALUE_BUFF);
  4.    
  5.     for(int i = 0; i < size - 1; i++)
  6.     {
  7.         cycle_temp[(i << 1)]        = buff[i + 1].ccr1 - buff[i].ccr1;
  8.         cycle_temp[(i << 1) + 1]    = buff[i + 1].ccr2 - buff[i].ccr2;
  9.     }
  10.   
  11.     for(int i = 0; i < size - 1; i++)
  12.     {
  13.         duty_cycle_temp[(i << 1)]     = /* cycle_temp[(i << 1)]  - */(buff[i].ccr1 - buff[i].ccr2);
  14.         duty_cycle_temp[(i << 1) + 1] = /* cycle_temp[(i << 1) + 1]  - */(buff[i].ccr1 - buff[i].ccr2);
  15.     }
  16.    
  17.     cycle       = (1000 * 1000 * 72) / cycle_temp[20];
  18.     duty_cycle  = duty_cycle_temp[20] * 100 / cycle_temp[20];
  19.     return 0;
  20. }
复制代码




收藏 评论0 发布时间:2021-8-25 15:15

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版