View previous topic :: View next topic |
Author |
Message |
aruna1
Joined: 14 Oct 2008 Posts: 103
|
PWM formula question |
Posted: Wed Dec 21, 2011 11:14 am |
|
|
Hi
I have being studying pwm module of a PIC. (12F683) and came up with following problem.
According to the datasheet and AN539 we can use maximum of 10bit pwm up to certain frequency depending on the oscillator frequency.
then there is this figure in the datasheet,
according to this figure, timer period is decided by the value stored in PR2 register which is a 8 bit value. then it shows on time (duty) of the signal is from TMR2 = 0 to TMR2 = CCPR1L:CCP1CON<5:4>, which is a 10bit value.
that is period is a 8bit value (0-255) while duty is a 10bit value (0-1023). Shouldn't duty is always less than or equal to period which is 8bit? that is duty cycle should always be a fraction of PR2 value, making that maximum resolution we can use is 8bit.
I saw one post where pcm programmer mention this, which is duty should be a fraction of PR2 value, which brings to my question of how to get 10bit resolution
If we are to get 10bit resolution shouldn't PR2 value become 10bit too?
For a pic running on 8MHz internal clock, we can generate 1kHz PWM with 10bit resolution (which i don't know how with 8bit PR2 value), where we cant generate 10bit resolution for higher frequencies like 40 kHz (which i can understand as period is now small enough to fit into 8bit).
I read AN594,AN539 and AN564. Also posts about 10bit and 8bit mode of pwm, but couldn't figure out the answer to my problem.
can someone please help me?
thank you |
|
![](templates/subSilver/images/spacer.gif) |
John P
Joined: 17 Sep 2003 Posts: 331
|
|
Posted: Wed Dec 21, 2011 12:18 pm |
|
|
The extra 2 bits that exist for the PWM period but not the clock frequency correspond to the lowest-order 2 bits of the pre-counter that creates the TMR2 frequency. If you aren't using a precount (TMR2 runs at the instruction rate) then the extra 2 bits are taken from the divide-by-4 logic that creates the instruction clock from the crystal rate, or the internal clock if you aren't using a crystal. So it actually does work with 10 bits of resolution.
I'm not familiar with the processor you're using, but if you look up the data sheets for the PIC16F690, and go to section 11, where the PWM system is described, you'll find this note below figure 11-3:
"The 8-bit timer TMR2 register is concatenated
with the 2-bit internal system clock (FOSC), or
2 bits of the prescaler, to create the 10-bit time
base." |
|
![](templates/subSilver/images/spacer.gif) |
aruna1
Joined: 14 Oct 2008 Posts: 103
|
|
Posted: Wed Dec 21, 2011 12:23 pm |
|
|
John P wrote: | The extra 2 bits that exist for the PWM period but not the clock frequency are actually the lowest-order 2 bits of the pre-counter that creates the TMR2 frequency. If you aren't using a precount (TMR2 runs at the instruction rate) then the extra 2 bits are taken from the divide-by-4 logic that creates the instruction clock from the crystal rate, or the internal clock if you aren't using a crystal. So it actually does work with 10 bits of resolution. |
hi
sorry but I didnt understand what you said, can you explain it bit clearly |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Dec 21, 2011 12:35 pm |
|
|
The resolution of the PWM period is the instruction clock (Fosc / 4),
because Timer2 is clocked at that rate. But the resolution of the duty
cycle is Fosc. The duty cycle circuit is designed to use Fosc. This is
somewhat unusual in PICs (because most things run on Fosc/4), so it
can cause initial confusion when learning about the PWM module. |
|
![](templates/subSilver/images/spacer.gif) |
aruna1
Joined: 14 Oct 2008 Posts: 103
|
|
Posted: Wed Dec 21, 2011 1:03 pm |
|
|
PCM programmer wrote: | The resolution of the PWM period is the instruction clock (Fosc / 4),
because Timer2 is clocked at that rate. But the resolution of the duty
cycle is Fosc. The duty cycle circuit is designed to use Fosc. This is
somewhat unusual in PICs (because most things run on Fosc/4), so it
can cause initial confusion when learning about the PWM module. |
well i dont know it is confusing,
so tell me if we are doing the calculations manually without using the wizard, how do we get the correct value for set_pwm_duty() function. I mean if i want to set 1kHz 50% pwm on 8MHz oscillator frequency (setup_timer_2(T2_DIV_BY_4,124,1);) how do i know
whether to put value 512 or 62 (50% = 62/124) ?
if i use 512 it is 10 bit but if i use 62 it will be 7 bit right? |
|
![](templates/subSilver/images/spacer.gif) |
John P
Joined: 17 Sep 2003 Posts: 331
|
|
Posted: Wed Dec 21, 2011 1:21 pm |
|
|
You're asking a good question there. I don't think that the CCS compiler deals with 10-bit PWM at all; you're limited to 8 bits. Is that right?
If you use an oscillator reload figure of 124, then 62 would certainly give you a 50% duty cycle. But what's hidden in the background is that instead of 62/124 it's actually 248/896.
Concerning the extra 2 bits that get counted, you don't really need to know what gets counted where. Just accept that somewhere, the processor has those bits and you can set up a 10-bit PWM operation. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Dec 21, 2011 1:35 pm |
|
|
The set_pwm1_duty() function can be confusing, because unlike most
other CCS functions, it uses Function Overloading. The behavior of the
function is different depending on the data type of the parameter.
If you use an 8-bit parameter, it will use 8-bit mode for the PWM duty
cycle. If you use a 16-bit parameter, it will use 10-bit mode.
This thread has several links that further explain 8/10-bit mode for PWM:
http://www.ccsinfo.com/forum/viewtopic.php?t=45968 |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Wed Dec 21, 2011 4:05 pm |
|
|
It is also just worth commenting as a separate thing about the phraseology used in the data sheet.
The PWM period definition, is given as:
CCPR1L:CCP1CON<5:4>
Now this is a standard nomenclature. If a register name is used, then you have the whole register, so:
CCPR1L -> The whole 8 bits of CCPR1L
Similarly, where 16bit registers are involved, use of the register name without an 'L' or 'H', refers to the whole 16bit register.
TMR1 -> the 16bit timer1 value
TMR1L -> the low eight bits of timer1
Then if a 'bit number' is given, this refers to just this bit. So:
CCP1CON<5> -> bit 5 in CCP1CON
Multiple bit numbers can be catenated with ':'
So the definition:
CCPR1L:CCP1CON<5:4>
Says that the PWM pulse width is defined by the eight bits of CCPR1L, then bit 5 of CCP1CON, then bit 4 of CCP1CON. Ten bits.
It is worth understanding the notation, since it is widely used in the data sheets.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
aruna1
Joined: 14 Oct 2008 Posts: 103
|
|
Posted: Wed Dec 21, 2011 8:55 pm |
|
|
@Ttelmah
I understand that
@jhop p & pcm programmer,
even if I forgot internal working, I'm still stuck with previous question, how one can decide when to put 10bit value or 8 bit value for the duty?
oook now I have 3 different options for setting pwm.
lets say I want to set 1kHz 50% pwm on 8MHz oscillator frequency (setup_timer_2(T2_DIV_BY_4,124,1);)
option 1
from resolution calculation formula it gives that @ 1kHz we can use 8.96 bits.
2^8.96 = 500
so i can use setup_pwm_duty(250) to make 50% duty, if i think of 8.96 bit resolution\on.
Option 2
but wizard generates setup_pwm_duty(512) code. I measured pwm duty with 512 value and it shows 50% which is very confusing.
according to calculation it should be over 100%
Option 3
But I also can use fraction of PR2 value, which is 62 (62/124 = 50%)
setup_pwm_duty(62)
with all above methods i can get 50% duty.
But,
with second method I can change pwm duty with 10 bit resolution, which is very good
with third method i guess i get 7 bit resolution (because 124<128=2^7).
and with both first and second method value inserted in to setup_pwm_duty() method is larger than 8bit value @ 50%. so compiler should think it as 10 bit value.(?)
with all above methods i can get 50% duty.
but as John P mentioned if it is 248/896 I have 10 bit value but variation is from 0 - 896 which does not give full 10bit range.
I read some posts and what i understood is
setup_timer_2(T2_DIV_BY_4,124,1);
with above function if i use duty value 0-123 I get 8 bit PWM
int duty; // duty from 0 to 123
setup_pwm_duty(duty);
but if I multiply it by 4 and use it (as a long value) it will give me 10bit resolution (which is fake resolution because it just multiplied by 4)
int16 duty; // duty from 0 to 895
setup_pwm_duty(duty);
when i use 8bit pwm, it sets 2 LSBs of 10bit value to 00 and only consider 8bit value from CCPR1L.
and AN839 says there is 2 8bit modes, 8bit high and 8bit low. in 8 bit low mode these 2 LSBs are used and 2 MSBs of CCPR1L is set to 00.
then if I put 62L how compiler knows whether to use 10bit mode or 8bit low mode?
because 62L is 1111 in CCPR1L and 10 in CCP1CON<5:4>, |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Thu Dec 22, 2011 2:47 am |
|
|
Did you look at the thread that PCM_programmer pointed you to.
The 'point' is that the pwm function has two distinct modes of operation, triggered by the nature of the number you feed it. Feed it an 8bit number, and it only updates the top eight bits of the ten bit value - this is fast, and gives much smaller code. Feed it a larger number, and it adds the code to switch to 10bit operation. So:
Code: |
int8 intduty;
int16 longduty;
intduty=longduty=250;
setup_pwm_duty(intduty); //Will effectively send 1000 to the PWM
setup_pwm_duty(longduty); //sends 250 to the PWM
setup_pwm_duty(250); //Again effectively 1000
setup_pwm_duty((int16)250); //sends 250
setup_pwm_duty(250L); //Note the 'L' - sends 250
setup_pwm_duty(500); //sends 500 - because value>256 automatically
//switches to 16bit operation
|
This is explained in the thread that PCM_programmer listed.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
aruna1
Joined: 14 Oct 2008 Posts: 103
|
|
Posted: Thu Dec 22, 2011 3:04 am |
|
|
@Ttelmah
Ya i check the thread pcm pointed, but it did not cleared my doubts
from your above post what i get is PWM system is not linear and totally messed up.
setup_pwm_duty(1); //Will effectively send 4 to the PWM (1*4)
setup_pwm_duty(2); //Will effectively send 8 to the PWM (2*4)
setup_pwm_duty(3); //Will effectively send 12 to the PWM (3*4)
setup_pwm_duty(255); //Will effectively send 1020 to the PWM (255*4)
then linearity changes
setup_pwm_duty(256); //Will effectively send 256 to the PWM
setup_pwm_duty(257); //Will effectively send 257 to the PWM
setup_pwm_duty(258); //Will effectively send 258 to the PWM
so see that
setup_pwm_duty(255); //Will effectively send 1020 to the PWM
setup_pwm_duty(256); //Will effectively send 256 to the PWM
isn't it messed up or I'm missing something?
unless we always use 'L' postfix system is totally messed up right? |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Thu Dec 22, 2011 3:19 am |
|
|
Of course it will...
Read what is posted. Look at these two lines:
Code: |
setup_pwm_duty((int16)250); //sends 250
setup_pwm_duty(250L); //Note the 'L' - sends 250
|
_You_ have to tell the compiler to treat the number as a 16bit value, though it is not implicitly one.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
aruna1
Joined: 14 Oct 2008 Posts: 103
|
|
Posted: Thu Dec 22, 2011 3:39 am |
|
|
one more thing
if we use post fix L can we use 10bit resolution at any pwm frequency?
so that at any high or low frequrncy we can use
setup_pwm_duty(0L); to setup_pwm_duty(1023L); and pwm will change linearly |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Thu Dec 22, 2011 4:14 am |
|
|
No.
10bit is the maximum resolution.
It is always the value fed as the period for ((timer2 + 1) * 4)-1.
The value for the period on timer2, can be up to 255, so with 255 selected, you get:
(255+1)*4 = 1024
and -1 gives 1023, as the full scale value.
If you select a lower count value for timer1, the frequency goes up, and the available resolution goes down. So with 127 selected, you get 511 as the maximum value (0 to 511 = 512 values - 9bit resolution), but double the frequency.
This is explained in the data sheet, with example resolutions for a number of timer values.
With the 'L', or the number cast to an int16, you get the full resolution _available_, but this is limited by the hardware.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
aruna1
Joined: 14 Oct 2008 Posts: 103
|
|
Posted: Thu Dec 22, 2011 4:35 am |
|
|
Quote: |
If you select a lower count value for timer1, the frequency goes up, and the available resolution goes down. So with 127 selected, you get 511 as the maximum value (0 to 511 = 512 values - 9bit resolution), but double the frequency. |
just to clarify
so now function should be
setup_pwm_duty(0L); to setup_pwm_duty(511L);
right? |
|
![](templates/subSilver/images/spacer.gif) |
|