Question

I am writing code for an AVR (in C) to continuously change the duty cycle of three PWM channels. To do this, I wrote a function that takes in a value as a percentage and sets certain registers to certain values determined by the percentage and the TOP value of the timer. Pseudo-code for this --

register = (int) (duty / 100 * timer_top);

But, unless duty = 100, this doesn't work (there is no PWM output).

I tried using the round() function in math.h, but that, too, gives similar output, and makes the compiled files unnecessarily large. I tried other methods, like --

register = duty / 100 * timer_top
register = (duty / 100 * timer_top) + 0.5
register = (int) (duty / 100 * timer_top) + 0.5

But none work. Could someone please help me with this? Thank you!

Was it helpful?

Solution

If duty is an integer, then duty / 100 will be the integer quotient, i.e. truncated to an integer, which will be zero for duty < 100. The computationally cheapest way to avoid this is performing the multiplication first, like

register = duty * timer_top / 100;

If you want to do real floating-point division, you can write that as

register = (int) (duty / 100. * timer_top);

where the decimal point in the constant makes it a double value. In this case, you can also use the other alternatives you wrote to affect rounding behaviour. But you can get different rounding behaviour using integer divisions only as well, e.g.

register = (duty*timer_top + 50)/100;

which will round to nearest instead of to zero, just like your + 0.5 would in the double-valued approach.

OTHER TIPS

Try this:

Register = (long long)duty * timer_top / 100;

You can do a rough version of rounding function using integer math only. The following pseudocode assumes that all numbers are positive:

intermediate = 100 * timer_top
register = duty/intermediate;
if (duty%intermediate>intermediate/2) {
    register++;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top