I'm using a HC908QT4 8-pin microcontroller to generate a 20kHz PWM signal on one of the timer output channels. The uC is running on the internal clock at 3.2MHz. I am running in unbuffered PWM mode, meaning there is some software overhead in determining how to change the Duty cycle register without glitching occuring. As far as I'm aware I am doing this correctly. I have no problem generating the PWM waveform for most duty cycles. I can generate 100% duty cycle by setting the CHxMAX bit. I just can't get 0% (or close to it - 10% minimum) duty cycle. There is always a needle thin pulse generated.
To ensure that I am handling the change in duty cycle correctly, I have handlers in the overflow ISR and the compare ISR to set a new duty cycle. Although the ISR's execute regularly, the handlers only execute when there is a change in duty cycle. Thereafter, the new duty cycle stablises.
Is there a reason why I can't achieve the 0% duty cycle? Thoughts or comments would be greatly appreciated....
Assuming you are doing the updating of the timer channel register from within the output compare ISR, you could possibly check for zero PWM value, and if so, clear the TOVx bit to prevent toggling on the next overflow. The OC interrupt should still occur, but there should be no pulse at the timer output.
I am not sure what the pulse width would be if you were to place a value in the timer channel register equal to the modulus value. I understand from the data sheet that overflow should take precedence over OC, suggesting a very short pulse width.
I am uncertain of your modulus setting. A PWM frequency of 20kHz would seem to imply a value of 160 decimal. However, for 8-bit resolution using a value of 255, I calculate the frequency to be 12.5kHz.
I think I have addressed your "needle thin pulse", but this would not seem to relate to a 10% minimum duty cycle. I am also unclear on what is happening within your overflow ISR, with respect to PWM operation.
Thanks for the reply. I have not been able to verify your suggestions in hardware yet. However I did manage to read a section in the QT4 datasheet, with your comments in mind, and discovered that the only way to achieve 0% duty cycle is to clear the TOVx bit. Exactly as per you recommendation
I took for granted that setting the output compare register value to zero would ensure a 0% duty cycle. However, it makes sense that in all liklihood the logic gates will toggle on overflow (set the ouptut port), and clear when they hit the compare state (almost instantly, but not instantly enough when one considers that it is gate logic driving the PWM output).
I will test the theory in hardware as soon as time allows and provide feedback.
As for the 20kHz. You are exactly right in assuming my modulus register is set to 160 decimal. I would have liked more duty cycle resolution - But then I would have like a higher PWM frequency too. You can just never keep embedded developers happy However, I have ended up with a happy compromise. As for the minimum duty cycle of 10%, I will investigate more closely once I have the 0% duty cycle working. I am driving into some load capacitance which may skew readings slightly. But I still see very little variation in my 0% setting and my 10% setting - Probably just my own frustration causing me to make assumptions about the actual pulse width.
One way or another it seems we're on the right track! Thanks for the suggestion. I am most grateful!
Posted: Mon Oct 24, 2005 4:21 am
Some additional thoughts occurred to me.
If the timebase for the PWM is to be exactly 160 cycles, you would need to set the modulo register for 159 decimal.
Accepting that the 0% and 100% values will be special cases, as previously discussed, for all other values I suspect that the value in the timer channel register will need to be one less than the pulse width required. This is because the PWM pulse goes active when the modulo count is reached, rather than when the counter becomes zero - giving an extra cycle. So the allowable range of values within the timer channel register would likely be 0 to 158 decimal.