[技术讨论] 定时器产生特定频率PWM信号的算法及疑点

[复制链接]
 楼主| hjlqwq 发表于 2023-3-13 19:39 | 显示全部楼层 |阅读模式
我写了一份能够计算产生特定频率PWM信号所需autoreload和prescaler算法。经过验证,可以高精度实现pwm的生成。但是我并不知道这套算法为什么能够实现,希望大家能够解释一下其中的数学依据。
  1. #include "stdio.h"
  2. #include "string.h"

  3. struct {
  4.         unsigned long int prescale;
  5.         unsigned long int autoreload;
  6.         unsigned long int err;
  7. }pwm, pwm_calc;

  8. void pwm_generate(unsigned long int freq)
  9. {
  10.         memset(&pwm, 0x00, sizeof(pwm));
  11.         memset(&pwm_calc, 0x00, sizeof(pwm_calc));
  12.         pwm.err = pwm.err - 1;
  13.         for (pwm_calc.prescale = 1; pwm_calc.prescale < 65535UL; pwm_calc.prescale++) {
  14.                 pwm_calc.autoreload = (170000000UL / ((pwm_calc.prescale + 1) * freq)) - 1;
  15.                 if (pwm_calc.autoreload > 65535UL || pwm_calc.autoreload < 100)
  16.                         continue;
  17.                 if (pwm_calc.autoreload * pwm_calc.prescale > freq)
  18.                         pwm_calc.err = pwm_calc.autoreload * pwm_calc.prescale - freq;
  19.                 else
  20.                         pwm_calc.err = freq - pwm_calc.autoreload * pwm_calc.prescale;
  21.                 if (pwm_calc.err < pwm.err)
  22.                         memcpy(&pwm, &pwm_calc, sizeof(pwm));
  23.                 if (pwm_calc.err == 0)
  24.                         break;
  25.         }
  26.         return;
  27. }

  28. int main(void)
  29. {
  30.         unsigned long int freq;
  31.         while (1) {
  32.                 printf("enter freq:");
  33.                 scanf("%ul", &freq);
  34.                 pwm_generate(freq);
  35.                 printf("prescale:%lu autoreload:%lu calcfreq:%lu calcerr:%lu\n", pwm.prescale, pwm.autoreload, 170000000UL / ((pwm.autoreload + 1) * (pwm.prescale + 1)), pwm.err);
  36.         }
  37.         return 0;
  38. }
附件中为部分测试结果。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

1

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部