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