PWM 参数计算
pwm模块可以设置的参数有prescaler, period, duty.
period参数的大小决定了这个pwm的分辨率。比如period有12位,即它的一个周期最多可以分为4096个等级。
cpu提供clk给pwm模块, pwm需要对这个clk做分频动作,分频系数由prescaler决定。
period参数的大小决定了这个pwm的分辨率。比如period有12位,即它的一个周期最多可以分为4096个等级。
cpu提供clk给pwm模块, pwm需要对这个clk做分频动作,分频系数由prescaler决定。
linux 中pwm接口位于<linux/pwm.h>,其中有
int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns);
其参数定义, period_ns为pwm最终输出脉冲的周期,duty_ns为pwm最终输出脉冲周期中占空比时间(高电平时间)。
在这个函数中要要据两个输出参数计算出pwm各参数的配置值。
计算步骤:
1. 供给pwm的clk,频率为fclk, 周期 t0 = 1/fclk
2. clk经过perscaler的分频之后,每周期时间 t1 = t0 / (perscaler+1) = (perscaler+1) / fclk
3. pwm分辨率为4096, 最大限度使用这个分辨率,则4096中的每一级占一个分频后的clock,所以最终输出脉冲的周期为:
period_ns = t1 * 4096 = (1/fclk) * (perscaler + 1) * 4096
而在pwm_config()函数中,给定period_ns和原始clk,在函数中计算出perscaler等参数。
c = pwm_source_clk; //origin clk c = c * period_ns; do_div(c, 1000000000); period_cycles = c; if (period_cycles < 1) period_cycles = 1; prescale = (period_cycles - 1) / 4096; pv = period_cycles / (prescale + 1) - 1; if (pv > 4095) pv = 4095; if (prescale > 1023) return -EINVAL; c = (unsigned long long)pv * duty_ns; do_div(c, period_ns); dc = c;
最后得到 prescale, pv, dc 分别是设置入寄存器prescaler, period, duty域中。