我写了一份能够计算产生特定频率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;
}
附件中为部分测试结果。
|