打印
[技术讨论]

定时器产生特定频率PWM信号的算法及疑点

[复制链接]
131|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hjlqwq|  楼主 | 2023-3-13 19:39 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
我写了一份能够计算产生特定频率PWM信号所需autoreload和prescaler算法。经过验证,可以高精度实现pwm的生成。但是我并不知道这套算法为什么能够实现,希望大家能够解释一下其中的数学依据。
#include "stdio.h"
#include "string.h"

struct {
        unsigned long int prescale;
        unsigned long int autoreload;
        unsigned long int err;
}pwm, pwm_calc;

void pwm_generate(unsigned long int freq)
{
        memset(&pwm, 0x00, sizeof(pwm));
        memset(&pwm_calc, 0x00, sizeof(pwm_calc));
        pwm.err = pwm.err - 1;
        for (pwm_calc.prescale = 1; pwm_calc.prescale < 65535UL; pwm_calc.prescale++) {
                pwm_calc.autoreload = (170000000UL / ((pwm_calc.prescale + 1) * freq)) - 1;
                if (pwm_calc.autoreload > 65535UL || pwm_calc.autoreload < 100)
                        continue;
                if (pwm_calc.autoreload * pwm_calc.prescale > freq)
                        pwm_calc.err = pwm_calc.autoreload * pwm_calc.prescale - freq;
                else
                        pwm_calc.err = freq - pwm_calc.autoreload * pwm_calc.prescale;
                if (pwm_calc.err < pwm.err)
                        memcpy(&pwm, &pwm_calc, sizeof(pwm));
                if (pwm_calc.err == 0)
                        break;
        }
        return;
}

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

Snipaste_2023-03-13_18-32-07.png (38.56 KB )

测试结果

测试结果

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

1

帖子

0

粉丝