Introduction
The CCP (Capture/Compare/PWM) module is an important peripheral available in many PIC microcontrollers, especially the PIC18 series. It is designed to perform three major functions:
- Capture,
- Compare, and
- Pulse Width Modulation (PWM).
This module provides hardware support for timing and waveform generation applications, which reduces the processing burden on the CPU and improves the efficiency of embedded systems. The CCP module is commonly used in applications such as motor speed control, frequency measurement, signal generation, servo motor interfacing, and timing operations.
Capture Mode
In Capture mode, the CCP module records the value of a timer whenever a specific event occurs on the CCP input pin. These events may include rising edges, falling edges, or every fourth/sixteenth rising edge of a signal. The captured timer value is stored in the CCP register, allowing the microcontroller to measure the time interval between events accurately. Capture mode is widely used for frequency measurement, pulse width measurement, and event timing applications.
Compare Mode
In Compare mode, the CCP module continuously compares the value of a timer with a predefined value stored in the CCP register. When the timer value matches the compare value, the module can trigger an action such as generating an interrupt, toggling an output pin, or resetting the timer. Compare mode is useful in applications requiring precise timing control, such as waveform generation, event scheduling, and delay generation.
Pulse Width Modulation (PWM) Mode
In PWM mode, the CCP module generates a Pulse Width Modulated signal with a programmable frequency and duty cycle. PWM signals are digital pulses whose ON and OFF times can be adjusted to control the average power delivered to a load. This mode is commonly used for DC motor speed control, LED brightness adjustment, servo motor control, and power electronics applications. The PWM signal generation is typically performed using Timer2 in PIC18 microcontrollers, where the period register and duty cycle registers determine the output waveform characteristics.
How to Generate PWM Signal using CCP Module ?
In order to generate a PWM signal from the CCP module, first we need to understand the registers that are used for selecting the PWM mode of CCP module. They are
- CCPxCON
- CCPxRL
- CCPxRH
where x can be 1 or 2.
CCP1CON Register
CCP1 control/configuration register is an 8-bit register that is used for configuring it in capture,compare or PWM mode.
CCP1CON
| — | — | DC1B1 | DC1B2 | CCP1M3 | CCP1M2 | CCP1M1 | CCP1M0 |
When we want to configure CCP module in PWM mode then the values of CCP1M3:CCP1M0 should be 11xx.
The DC1B1 and DC1B2 are the two bits that we use for adjusting the duty cycle.
| DC1B1 | DC1B2 | Duty Cycle Adjustment |
| 0 | 0 | 0 |
| 0 | 1 | 0.25% |
| 1 | 0 | 0.50% |
| 1 | 1 | 0.75% |
I will describe in coming example how to use these bits for adjusting the duty cycle.
CCPxRL
CCP1RL and CCP1RH bit, both are 8-bit registers and can be combined to be used as 16-bit registers for capture and compare mode. While CCP1RL along these two bit (DC1B1 and DC1B2) making 10-bit register is used for seting the time period and duty cycle of the required waveform.
PWM Signal
Another feature of CCP is pulse width modulation (PWM). The PWM feature allows us to create pulses with variable widths. Although we can program timers to create PWM, the CCP module makes the programming of PWM much easier and less tedious. PWM is widely used in industrial controls such as DC motor controls. Indeed the PWM is so widely used that Microchip has enhanced the PWM capabilities of the newer generation of the PIC18 family members and has designated them as ECCP (enhanced CCP).
The main difference between ECCP and standard CCP is the PWM capability. In creating pulses with variable widths for the PWM, two factors are important: The period of the pulse and its duty cycle. The duty cycle (DC) is the portion of the pulse that stays HIGH relative to the entire period. Very often the DC is stated in the form of percentages. For example, a pulse with a 4 ms period that stays HIGH for 1 ms has DC of 25% (1 ms / 4 ms= 25%), as shown in Figure below.
Steps of Programming CCP Module for PWM Signal Generation
Timer2 is used for generating a PWM signal by using a CCP Module. The associated registers with Timer2 are PR2 (period Register) and TMR2 register. In order to understand the timers2 programming, read here.
Period of PWM
The CCP module uses Timer2 and its associated register, PR2, for the PWM time-base, which means that the frequency of the PWM is a fraction of the Fosc, the crystal frequency. It uses the PR2 register to set the PWM period as follows:
$$
T_{PWM} = \left[(PR2)+1\right] \times 4 \times N \times T_{OSC}
$$
where Tosc is the inverse of 1/Fosc, the crystal frequency; Tpwm is the desired PWM period; and N is the prescaler of 1, 4, or 16 set by the Timer2 control register (T2CON). Therefore, we can get the value for the PR2 register as follows:
$$
PR2 = \left[\frac{F_{OSC}}{F_{PWM} \times 4 \times N}\right] – 1
$$
From above equation, we can conclude that the maximum value for Tpwm can be achieved when N
=16 and PR2 = 255.
Therefore, we have:
$$
T_{PWM} = \left[(255)+1\right] \times 4 \times 16 \times T_{OSC} = 16384\,T_{OSC}
$$
which means that the minimum allowed $$
F_{PWM} = \frac{F_{OSC}}{16384}
$$
Example 1
Find the PR2 value and the prescaler needed to get the following PWM frequencies. Assume XTAL – 20 MHz.
(a) 1.22 kHz, (b) 4.88 kHz, (c) 78.125 kHz
Solution:
(a)
$$
PR2 \text{ value} = \left[\frac{20\,MHz}{4 \times 1.22\,kHz}\right] – 1 = 4097
$$
which is larger than 255, the maximum value allowed for the PR2.
Now choosing the prescaler of 16 we get
$$
PR2 \text{ value} = \left[\frac{20\,MHz}{4 \times 1.22\,kHz \times 16}\right] – 1 = 255
$$
(b)
$$
PR2 \text{ value} = \left[\frac{20\,MHz}{4 \times 4.88\,kHz}\right] – 1 = 1023
$$
which is larger than 255, the maximum value allowed for the PR2.
Now choosing the prescaler of 4 we get
$$
PR2 \text{ value} = \left[\frac{20\,MHz}{4 \times 4.88\,kHz \times 4}\right] – 1 = 255
$$
(c)
$$
PR2 \text{ value} = \left[\frac{20\,MHz}{4 \times 78.125\,kHz}\right] – 1 = 63
$$
Example 2
Find the minimum and maximum \(F_{PWM}\) frequency allowed for XTAL \(= 10\ MHz\). State the PR2 and prescaler values for the minimum and maximum \(F_{PWM}\).
Solution:
We get the minimum \(F_{PWM}\) by making \(PR2 = 255\) and prescaler \(= 16\), which gives us
$$
\frac{10\,MHz}{4 \times 16 \times 256} = 610\,Hz
$$
We get the maximum \(F_{PWM}\) by making \(PR2 = 1\) and prescaler \(= 1\), which gives us
$$
\frac{10\,MHz}{4 \times 1 \times 1} = 2.5\,MHz
$$
As stated earlier, the duty cycle of PWM is the portion of the pulse that stays HIGH relative to the entire period. To set the duty cycle, the CCP module uses the 10-bit register of DC1B9:DC1B0. The 10-bit register of DC1B9:DC1B0 is formed from 8 bits of CCPRIL and 2 bits from the CCPICON register, where CCPRIL is the upper 8 bits and DC1B2:DC1B1 of the CCPICON are the lower 2 bits of the 10-bit register. In reality, CCPRL1 is the main register for the duty-cycle and the lower 2 bits of DC1B2:DC1B1 are for the decimal point portion of the duty cycle.
It must be noted that the value for the duty cycle register of the CCPRIL is always some percentage of the PR2 register. For example, if PR2 = 50 and we need a 20% duty cycle, then CCPRL1 10 because 20% x 50 = 10. In this case, DC1DB2:DC1B1 = 00. Now assume that we want a 25% duty cycle for the same PR2. Because 50 × 25% = 12.5, we make CCPRL1 = 12 and DC1B2:DC1B1 = 10 to take care of the 0.5 part.
Example 3
Design and implement an embedded system interface using the CCP1 (RC2) pin of a microcontroller to generate a 3 kHz PWM signal with a 75% duty cycle. Assume a crystal frequency of 10 MHz. Use this PWM output to control the speed of a DC motor (or brightness of an LED), and explain the required hardware interfacing connections.
Solution
To generate a PWM signal using the CCP1 module, the PWM frequency is determined by:
$$
F_{PWM} = \frac{F_{OSC}}{4 \times (PR2+1) \times N}
$$
where:
Rearranging the formula to calculate the PR2 value:
$$
PR2 = \left[\frac{F_{OSC}}{F_{PWM} \times 4 \times N}\right] – 1
$$
Choosing the Timer2 prescaler
$$
PR2 = \left[\frac{10 \times 10^6}{3000 \times 4 \times 4}\right] – 1
$$
$$
PR2 = 207.33 \approx 207
$$
Therefore:
- Prescaler=4
Duty Cycle Calculation
The duty cycle is given as
The PWM duty cycle value is calculated using:
$$
Duty\ Cycle\ Value = \frac{Duty\ Cycle \times 4 \times (PR2+1)}{100}
$$
Substituting the values:
$$
Duty\ Cycle\ Value = \frac{75 \times 4 \times (207+1)}{100}
$$
$$
Duty\ Cycle\ Value = 624
$$
The 10-bit value=
is loaded into the CCP duty cycle registers.
PWM Initialization Steps
- Set the CCP1 pin (RC2) as output.
$$
TRISC2 = 0
$$
2. Load the PR2 register.
$$
PR2 = 207
$$
3. Configure CCP1 module in PWM mode.
$$
CCP1CON = 0x0C
$$
4. Load the duty cycle value.
$$
CCPR1L = 156
$$
Lower 2 bits are loaded into DC1B bits of CCP1CON.
- Configure Timer2 prescaler as 4 and turn ON Timer2.
$$
T2CON = 0x05
$$
Hardware Interfacing
The PWM output is available on the CCP1 pin (RC2). Since a microcontroller cannot directly drive a DC motor due to current limitations, a transistor or MOSFET driver circuit is required.
DC Motor Control Interface
- Connect RC2 (CCP1 pin) to the base/gate of a transistor or MOSFET through a resistor.
- Connect the DC motor between the supply voltage and transistor collector/drain.
- Use a flyback diode across the motor terminals to protect against back EMF.
- Connect all grounds together.
The PWM signal controls the average voltage applied to the motor, thereby controlling motor speed.
LED Brightness Control
For LED dimming:
- Connect RC2 to the LED through a current limiting resistor.
- The PWM signal changes the average power delivered to the LED.
- Increasing duty cycle increases LED brightness.
At
duty cycle, the LED remains ON for most of the PWM period, producing high brightness.
COMPLETE PIC18 ASSEMBLY CODE
;=========================================================
; PWM Generation using CCP1 (RC2)
; Fosc = 10 MHz
; PWM = 3 kHz, Duty = 75%
;=========================================================
LIST P=18F4520 ; Change device if needed
#include <P18F4520.INC>
;—————- CONFIG BITS —————————–
CONFIG OSC = HS
CONFIG WDT = OFF
CONFIG LVP = OFF
;—————- VARIABLES ——————————-
CBLOCK 0x20
ENDC
;—————- RESET VECTOR —————————-
ORG 0x00
GOTO MAIN
;=========================================================
; MAIN PROGRAM
;=========================================================
MAIN:
;—– Configure RC2 (CCP1) as output —–
BSF TRISC, 2 ; First set as input (safe init)
BCF TRISC, 2 ; Then set RC2 as output
;—– Set PWM period using Timer2 —–
MOVLW D’208′ ; PR2 = 208 for ~3 kHz
MOVWF PR2
;—– Set Duty Cycle = 75% —–
MOVLW D’156′ ; CCPR1L = upper 8 bits of 627
MOVWF CCPR1L
; Set lower 2 bits (DC1B1:DC1B0 = 3)
MOVLW B’00001100′ ; DC1B1:DC1B0 = 11 (binary 3)
MOVWF CCP1CON
;—– Configure CCP1 in PWM mode —–
MOVLW B’00001100′ ; CCP1M3:CCP1M0 = 1100 (PWM mode)
MOVWF CCP1CON
;—– Configure Timer2 —–
MOVLW B’00000101′
; T2CKPS1:T2CKPS0 = 01 → Prescaler 1:4
; TMR2ON = 1 → Timer2 ON
MOVWF T2CON
;—– Wait for PWM stabilization —–
WAIT:
GOTO WAIT
END

Conclusion
Using the CCP1 module with Timer2, a PWM signal of approximately
and
duty cycle is generated successfully. This PWM signal can efficiently control DC motor speed or LED brightness while reducing processor overhead because waveform generation is handled by hardware.


