I would like to create a variable duty cycle PWM on a PIC18F4550 microcontroller to control the gate of a MOSFET in a project I am doing.

I am new to microcontrollers but already have code that can generate a PWM signal. I would like help figuring out how to do two things.

  1. How can I change the duty cycle step by step (i.e. 10%,20%,30%....100%), increasing the duty cycle each period of the PWM.
  2. How can I change the duty cycle of the PWM based upon the press of an external switch.

I am programming in the C language and would appreciate some example code.

  • 1
    \$\begingroup\$ Please make it a habit to provide a link to the datasheet if you're asking about a particular part. It's a courtesy to others who want to help you; we often want to take a look at it. It also may prevent confusion if we know unambiguously what part we're talking about. \$\endgroup\$
    – stevenvh
    Jun 26, 2012 at 15:28

2 Answers 2


To step through through various duty cycles, such as incrementing 10% each period, you need to set up an interrupt on the Timer Overflow. In that interrupt services routine, you modify the PWM duty cycle register to it's new value.

To update the duty cycle based on a switch, you do the same thing. Set up an interrupt on the input pin connected to the switch and again update the duty cycle registers during that interrupt service routine.

Here is a Microchip Tutorial on Timer interrupts including some C code. And here is the Microchip Application Note on the Capture/Compare/PWM peripheral. The examples are in Assembly. But you say you've already set up the PWMs so you should already be familiar with which registers you need to modify to change the duty cycle.


The 18F4550 has built-in PWM generators, so this is easy. Once you set up the hardware, it continues to generate the PWM waveform on its own. The hardware to do this is called a "CCP" module, which stands for Compare, Capture, and Pulsewidth modulation. In your case you want to use it in PWM mode.

You set up timer 2 to provide the PWM period, then the duty cycle is written to CCPRxL. Actually the duty cycle has 2 extra fraction bits below the timer 2 period. These fraction bits are written to the CCPxCON register in the right place. It's a little squirrely, but it all works.

If you want to change the PWM duty cycle every period, then you probably want to interrupt on timer 2. Note that with its postscaler, you can interrupt every N periods, where N is 1 to 16. In the interrupt, you change CCPRxL and CCPxCON (if you want to use the extra fraction bits) to the new duty cycle. The duty cycle in these registers is in units of timer 2 counts, which is the absolute on time per pulse, not the fraction of on time per pulse. The fraction of on time is the absolute on time divided by the period.

Once you know how change the PWM duty cycle, it can be triggered from any decision in the code. To change it based on a external switch press means detecting that press then performing the change.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.