Electronic – How to select what values to load in CCPR1L register (for generating PWM signal with PIC)

picpwmregistersignal

I need to generate PWM signal with PIC18F2550 microcontroller at near 20kHz. I read the datasheet, I found it too complex and confusing, then I started to search for a sample code on the net to finally see this PWM tool.

I used it with parameters \$ F_{OSC} \$=20MHz and \$ F_{PWM} \$=20kHz to generate these two different codes for corresponding two different duty cycle percentages.

// Duty cycle = 0%
PR2 = 0b11111001 ;
T2CON = 0b00000100 ;
CCPR1L = 0b00000000 ;
CCP1CON = 0b00001100 ;

// Duty cycle = 100%
PR2 = 0b11111001 ;
T2CON = 0b00000100 ;
CCPR1L = 0b11111001 ;
CCP1CON = 0b00111100 ;

The datasheet tells me that the 4th and 5th bits of the CCP1CON register are the LSBs of the "PWM duty cycle with" value, and its MSBs are stored in the CCPR1L register, isn't it?

That makes, for 0% duty cycle, the 10-bit PWM duty cycle timing is,

00000000 + 00 = 0x000

And for 100% duty cycle,

11111001 + 11 = 0x3E7

So, according to this tool, I must set the values between 0x000 and 0x3E7 to the relevant PWM registers to have duty cycle ratios between 0% and 100%. At this point I become confused and the following questions arise in my mind:

  • What is this 0x3E7 value? How is it calculated? How would I find it myself if I hadn't had such an online tool?
  • What is the resolution of this PWM signal (i.e.; what is the time difference of length of two duty cycles for two sequential values like 0x3E6 and 0x3E7)?
  • Why can't I load higher values to the CCPR1L register like all ones (0xFF); that would make 0x3FF for the overall PWM duty cycle length value. What happens if I do so?
  • The tool says that, I can use PWM feature only with 9-bit resolution with the working parameters I specified. So, why the number 0x3E7 is a 10-bit number? Is the "9-bit" comes from integer truncated value of \$log_2(0x3E7)\$?

This happened to be a long question, but it would help me greatly if someone kindly explains me the overall steps and logic of PWM signal creation with PIC microcontrollers.

Thanks.

Best Answer

I know it's a bit late, but I've just got this sabe doubt. After looking around, I've come across this Microchip Doc that shows some examples.

First, we calculate \$\text{PR2}\$. From this formula,

$$ F_\text{PWM} = \dfrac{1}{(\text{PR2} + 1) \times 4 \times T_\text{OSC} \times \text{T2CKPS}} $$

we get

$$ \text{PR2} = \dfrac{1}{F_\text{PWM} \times 4 \times T_\text{OSC} \times \text{T2CKPS}} - 1 $$

where \$T_\text{OSC} = 1/F_\text{OSC}\$, and \$\text{T2CKPS}\$ is the Timer2 prescaler value (1, 4 or 16).

Therefore, if we want \$F_\text{PWM} = 20\text{kHz}\$, and choosing \$\text{T2CKPS} = 1\$, we get \$\text{PR2} = 249\$. We should choose higher values for \$\text{T2CKPS}\$ only if \$\text{PR2}\$ exceeds 8 bits (\$\text{PR2} \gt 255\$) for the given prescale.

Now we calculate the max PWM resolution for the given frequency:

$$ \text{max PWM resolution} = \log_2(\;\dfrac{F_\text{OSC}}{F_\text{PWM}}\;) $$

That gives us \$9.9658\$ bits (I know, it sounds weird, but we'll use it like that later).

Now, let's calculate the PWM duty cycle. It is specified by the 10-bit value \$\text{CCPRxL:DCxB1:DCxB0}\$, that is, \$\text{CCPRxL}\$ bits as the most significant part, and \$\text{DCxB1}\$ and \$\text{DCxB0}\$ (bits 5 and 4 of \$\text{CCPxCON}\$) the least significant bits. Let's call this value \$\text{DCxB9:DCxB0}\$, or simply \$\text{DCx}\$. (x is the CCP number)

In our case, since we have a max PWM resolution of \$9.9658\$ bits, the PWM duty cycle (that is, the value of \$\text{DCx}\$) must be a value between \$0\$ and \$2^{9.9658} - 1 = 999\$. So, if we want a duty cycle of 50%, \$\text{DCx} = 0.5 \times 999 = 499.5 \approx 500\$.

The formula given on the datasheet (also on the linked doc),

$$\text{duty cycle} = \text{DCx} \times T_\text{OSC} \times \text{T2CKPS}$$

gives us the pulse duration, in seconds. In our case, it's equal to \$25\text{ns}\$. Since \$T_\text{PWM} = 50\text{ns}\$, it's obvious that we have a 50% duty cycle.

That said, to calculate DCx in terms of duty cycle as \$r \in [0,1]\$, we do:

$$ \text{DCx} = \dfrac{r \times T_\text{PWM}}{T_\text{OSC} \times \text{T2CKPS}} = \dfrac{r \times F_\text{OSC}}{F_\text{PWM} \times \text{T2CKPS}} $$


Answering your other questions:

2) The resolution of your PWM pulse with period \$T_\text{PWM}\$ is

$$ \dfrac{T_\text{PWM}}{2^\text{max PWM res}} $$

3) Because CCPRxL, along with DCxB1 and DCxB0, determine the pulse duration. Setting CCPRxL with a higher value than \$2^\text{max PWM res} - 1\$ means a pulse duration higher than the PWM period, and therefore you'll get a flat \$V_{DD}\$ signal.