PLEASE WRAP your outgoing lines. Mike Hord wrote: >> Antonis Iliopoulos wrote: >>I know that PWM is not a very popular subject (especially through the CCP channel.) I know, I know, interrupts use less CPU memory, etc. But for my project I must do it initially using a CCP channel and then I can prove that interrupts are better. >>So, since PWM period =[(PR2)+1] x 4 x TOSC x (TMR2 Prescale), if I need a 20 ms period at 4MHz: 20ms = [(PR2)+1] x 4 x 250 ns x 16 (16 pre for muximum performance...) >> >>Therefore I will need a PR2 = 1250 to do it. >> >>Is my math that bad? Am I missing something? Seems good to me. 4Mhz/4=1us=Tcy x 16 prescale= 16us. 20ms/16us=1250 >>Is the only solution to use a lower clock frequency? If you refuse to use interrupts then only a lower clock frequency will work directly. If you set up interrupts correctly, it's easy to achieve what you want with minimal overhead. Set the duty cycle register to 0 so no pulses are generated. Set PR2 to 156-1 for 7 interrupts of TMR2 and 158-1 for one interrupt to get exact 20ms period (1250/8=156.25). This same eighth interrupt set the duty cycle to what you want. The pulse will be generated on the next TMR2 interrupt, at which time you set CCPR1L back to 0, and PR2 back to 155. You do nothing for 7 of 8 TMR2 interrupts so the overhead is nearly nil. (Don't forget to clear TMR1IF EVERY time). > What you're missing is that Tosc is actually 1 us. No, Tcy is 1us. Tosc=1/Fosc=250ns. Hence the factor 4 x Tosc in the equation. > Of course, that > means PR2 should be set to 312.5, so you're still out of luck. No. PR2 needs to be 1250, but that doesn't fit into 8 bits so he has to create a software prescaler. Using a timer interrupt is the cleanest way to do that. > You're also missing the fact that using the CCP module, if it doesn't > overly interfere with other functions, is better than setting/clearing > bits in interrupts, or wait looping. It offers "fire-and-forget", > that is, you start it up and ignore it. A change in duty cycle is > easy to effect by rewriting the appropriate register. Exactly. A duty cycle of zero generates NO pulse on reload, but does generate an interrupt that you can count. You can use this to generate a pulse that is longer that PR2 would otherwise allow, by setting CCPR1L higher than PR2 to prevent the pulse from being cleared until you load the residue of the pulse width you want into CCPR1L. e.g. if you want a 70% duty cycle you need 875/1250. 875/156=5.608974359 =5 full ints (156) + 95 in CCPR1 for 6th. Then clear D/C until int 1. Because the D/C register (CCPR1L) is double buffered you can set up the residue D/C a full 2.5mS (156) before it is needed. PR2 is NOT buffered so you can only mess with it when you know TMR2 has been reset, as right after interrupt. You don't have to use 156 for TMR2, but it makes the math obvious. You could just as easily have chopped the timing up into 4 msec chunks (250) if you wanted a lower interrupt rate. Did I miss anything? Robert -- http://www.piclist.com PIC/SX FAQ & list archive View/change your membership options at http://mailman.mit.edu/mailman/listinfo/piclist