Pulse Width Modulation (PWM) using PIC CCP module

, Posted by ADMIN at 11:15 AM


Pulse width modulation (PWM) is a technique of controlling the amount of power delivered to an electronic load using an on-off digital signal. The fraction of the period for which the signal is on is known as the duty cycle. The average DC value of the signal can be varied by varying the duty cycle. The duty cycle can be anywhere between 0 (signal is always off) to 1 (signal is constantly on). Suppose, if the signal has +5 V while it is on and 0 V during off condition, then by changing the duty cycle of the signal, any voltage between 0-5 V can be simulated. This method is commonly used for controlling speeds of DC motors and brightness of lamps. This lab session will talk about how to generate a PWM signal using the PIC16F628A microcontroller and control the brightness of an LED with it. PIC16F628A has a built-in hardware, called Capture/Compare/PWM (CCP) module, to generate a PWM signal.


The Capture/Compare/PWM (CCP) module in the PIC16F628A microcontroller is very versatile. The Capture and Compare features integrate closely with the 16-bit TMR1 and the PWM feature uses the third timer, the 8-bit TMR2. The CCP module has two 8-bit registers, called CCPR1L and CCPR1H. Together they form a 16-bit register that can be used for capture, compare or to form the duty cycle of a PWM stream. The CCP module is controlled by the CCP1CON register.

In Capture mode, the CCPR1L and CCPR1H registers record the 16-bit value of the TMR1 register when an event occurs on pin RB3/CCP1. An event can take place on:

  • Every falling edge
  • Every rising edge
  • Every 4th rising edge
  • Every 16th rising edge

The RB3/CCP1 pin must be configured as an input and Timer1 must be in Timer mode or synchronized Counter mode for this to work. A Capture event can also trigger an interrupt.

In Compare mode, the value of the TMR1 register is continuously compared to the value of the 16-bit register made up of CCPR1H and CCPR1L. When a match occurs, the RB3/CCP1 pin is driven high, low or remains unchanged, depending upon the setting of the CCP1CON register. The RB3/CCP1 pin must be configured as an output by clearing the corresponding TRISB bit. The Capture and Compare modes will be discussed later in more detail.

In PWM mode, the RB3/CCP1 pin can output a 10-bit resolution periodic digital waveform with programmable period and duty cycle. To operate in PWM mode, the CCP1 pin must be configured for output. The duty cycle of the waveform to be generated is a 10-bit value of which the upper eight bits are stored in the CCPR1L register, whereas the lowest two bits are stored in bit 5 and bit 4 of the CCP1CON register.


The setup for this experiment is very simple. Two tact switches are connected to pins RB0 and RB1 to provide inputs. An LED is driven by the PWM output from the RB3/CCP1 pin through a current limit resistor of 330R. The duty cycle of the output PWM signal is increased or decreased with the two tact switch inputs, and that will vary the brightness of the LED.

Circuit setup on breadboard


The MikroC Pro for PIC compiler provides four library routines for controlling the PWM operation using the CCP module. They are PWM1_Init(const long frequency), PWM1_Set_Duty(unsigned short duty_ratio), PWM1_Start(void), and PWM_Stop(void). Read the MikroC manual for further details. The following program gives 10 different brightness levels of LED by varying the duty cycle from 0 to 250 in the step of 25. The duty cycle will be varied by pressing the UP and DOWN tact switches.

Lab 9: Pulse Width Modulation
Copyright @ Rajendra Bhatt, 2010.
Description: CCP module generating a PWM signal
Oscillator: XT, 4.0 MHz, MCLR Enabled
sbit UP at RB0_bit;
sbit DOWN at RB1_bit;
unsigned short new_DC, current_DC;

void debounce(){

void main() {
CMCON = 0x07; // Disable comparators
PORTB = 0x00;
TRISB = 0b00000011; // RB0, RB1 input, RB3 (PWM1) output
PWM1_Init(5000); // PWM module initialization (5KHz)
new_DC = 0; // Initial value of variable Duty Cycle
current_DC = 0;
PWM1_Start(); // Start PWM1 module with Zero DC
do {
if (!UP){ // If the button connected to RB0 is pressed
if (new_DC < 250) // Don't go above 250
new_DC = new_DC + 25 ; // increment Duty Cycle by 25
if (!DOWN) { // If the button connected to RB1 is pressed
if (new_DC !=0) // Don't go below 0
new_DC= new_DC - 25 ; // Decrement Duty Cycle by 25

if (current_DC != new_DC) {
current_DC = new_DC ;
PWM1_Set_Duty(current_DC); // Change the current DC to new value
} while(1);
} // END main()


As the circuit is powered, the LED starts with zero brightness, i.e., zero duty cycle. Pressing the UP button increases the duty cycle and the LED will glow. The LED will brighten more and more on every press of the UP button, until the duty cycle reaches close to 1.

0% Duty Cycle

25 % Duty Cycle

50% Duty Cycle

~ 100% Duty Cycle

With Regards,

sms communication,
Tanjore -1.

mobile :9944 186 173