View previous topic :: View next topic |
Author |
Message |
flyboy71
Joined: 14 Mar 2019 Posts: 8
|
Not understanding PWM resolution |
Posted: Thu Dec 12, 2019 9:26 am |
|
|
Im not exactly clear on PWM resolution even after reading other posts. I would like to generate 250kHz PWM on a PIC16F1825 with a 32 MHz Fosc. According to the datasheet Table 24-5 I should have 7 bits of resolution using:
setup_timer_2(T2_DIV_BY_1, 31, 1);
Using set_pwm_duty the duty cycle is 0-100% over a range of 0-31. How do I achieve 7 bits of resolution? Shouldn't I have 128 steps of duty cycle per the table?
My program is basically EX_PWM.C in examples but using an int8 for 'value' rather than the ADC. Its mostly a fundamental understanding of what the datasheet refers to in resolution or Im totally misinterpreting it. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Dec 12, 2019 11:01 am |
|
|
Try this.
Code: | #include <16F1825.h>
#use delay(internal=32M)
//=======================================
void main(void)
{
int16 duty; // Note int16 required for 10-bit pwm
setup_timer_2(T2_DIV_BY_1, 31, 1);
setup_ccp1(CCP_PWM);
duty=64; // Gives 50% duty cycle in 10 bit mode
set_pwm1_duty(duty);
while(TRUE);
}
|
|
|
|
flyboy71
Joined: 14 Mar 2019 Posts: 8
|
|
Posted: Thu Dec 12, 2019 11:13 am |
|
|
Thanks! I'm away on travel so I will try that as soon as I get back to the bench. I think I'm seeing how its handling the resolution being that I was in 8 bit mode; I'm not using those other 2 bits which are zero, giving me effectively only 5 bits of resolution. Does the above give 128 actual steps or does it go in steps of 4? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9269 Location: Greensville,Ontario
|
|
Posted: Thu Dec 12, 2019 12:15 pm |
|
|
It should give all 7 bits....the 'quirky' thing to remember is that the PWM is 10 bits, even though only 7 are 'good' for your setup, it needs to see all 10 bits to be properly configured.
At least that's how I think of it..... |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19587
|
|
Posted: Thu Dec 12, 2019 12:16 pm |
|
|
The key thing is 'duty' being a 16bit variable.
The duty function is 'overloaded'. If it is called with a value defined as
8bit, the value is loaded into the high eight bits of the duty cycle. If
instead it is called using a value defined as 16bit, it is loaded into the
whole duty cycle, including the extra two bits.
So if you use:
set_pwm1_duty(16);
You will only get 5 bits of available resolution.
However, use:
set_pwm1_duty(16L);
You get 1/4 the output pulse and the 7bit resolution.
PCM is carefully using an int16 to get the full 7bits. |
|
|
flyboy71
Joined: 14 Mar 2019 Posts: 8
|
|
Posted: Thu Dec 12, 2019 1:13 pm |
|
|
I'm trying to visually picture how the hardware does this. The datasheet states Quote: | "The 8-bit timer TMRx register is concatenated with the 2-bit internal system clock (Fosc)" | and since the timer is clocked at Fosc/4, does that mean those lower 2 bits are "filling in" the steps that would be present in 8 bit mode? Or in other words, those 2 bits are clocking the timer 4x faster every 4th system clock.
I think were saying the same thing I'm just picturing it differently. |
|
|
dluu13
Joined: 28 Sep 2018 Posts: 395 Location: Toronto, ON
|
|
Posted: Thu Dec 12, 2019 2:45 pm |
|
|
There is an alternative that I use, which is pwm_set_duty_percent() where you can set the duty cycle as a percentage from a scale of 0 to 1000 (so 0.1% increments)
It is slower than pwm_set_duty() but then I don't need to worry about the PWM period. I don't need the speed though, so I just use that, and it cuts down on required brainpower. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19587
|
|
Posted: Fri Dec 13, 2019 3:24 am |
|
|
flyboy71 wrote: | Im trying to visually picture how the hardware does this. The datasheet states Quote: | "The 8-bit timer TMRx register is concatenated with the 2-bit internal system clock (Fosc)" | and since the timer is clocked at Fosc/4, does that mean those lower 2 bits are "filling in" the steps that would be present in 8 bit mode? Or in other words, those 2 bits are clocking the timer 4x faster every 4th system clock.
I think were saying the same thing I'm just picturing it differently. |
The point is that there is an 8bit register holding the upper eight bits
of the PWM duty value, and then two 'extra' bits in another register.
These give the full (10bit if using 255 for PR2) resolution, and use the
faster clock (your 'filling in').
The CCS function does not write to these 'extra' bits, unless you deliver it
with a 16bit value. Doesn't matter whether the number itself is only 0-255,
it's whether it is in a 16bit 'container', that determines whether the extra
bits are actually 'used'. So using 'L' with a constant, or having the number
in a 16bit variable, is what determines whether these are actually accessed.
If you only use the 8bit register, the value is written into the upper 8
bits, so is effectively multiplied by 4. |
|
|
|