Using CCP module’s compare mode on PIC18

On this article I talk about the compare mode available on the CCP units of every PIC18.

The compare mode works almost the same way as the capture mode: the counting from the reference timer is constantly compared to a programmed value (on the CCPRxH and CCPRxL registers). When the counting matches that value a compare event is triggered which then can trigger one of the following events:

  1. The output pin (RC2/CCP1 or RC1/CCP2 depending on the module) is set;
  2. The output pin is cleared;
  3. The output pin is toggled (0->1 or 1->0);
  4. The output pin state is not modified;
  5. A special event is triggered (on CCP1 it resets timer 1 and on CCP2 it resets timer 1 or timer 3 and also starts an ADC conversion as long the ADC module is enabled).

In all cases the compare event also sets the module interrupt flag (CCP1IF or CCP2IF).

This feature can be used to generate periodic signals, by modifying the output pin state at a periodic time interval or simply generating periodic interrupts (for any internal timed process).

The following figure shows that as soon as timer 1 counting reaches the value stored on channel 1 compare registers (CCPR1H and CCPR1L), a compare event is triggered, toggling the state of pin CCP1. The ISR code should provide the proper CCPR1H and CCPR1L reloading with the next desired time interval.


Note that for signal generation as shown on the figure it is mandatory reloading register pair CCPR1H and CCPR1L with the next trigger point (by adding half the signal period to the contents of those registers).

The following example demonstrates th use of modules CCP1 and CCP2 generating interrupt-only events. The ISR code detects which module triggered the interrupt and reload the next compare point on the corresponding register pair).

Both modules are configured to use timer 1 as the timebase. The timer 1 is clocked by the system clock (FOSC/4) divided by 8. On the PK2Lab board that results on 4MHz/4/8 = 125kHz, meaning that every timer count is done in 1/125,000=8µs.

By adding 40,000 counts to each CCP1 compare we can have an interrupt getting triggered each 40,000*8µs=320ms. That means that a led connected to RC0 will blink at a rate of 1.56250Hz (a period of 640ms) and a led connected to RC1 will blink at a rate of 3.125Hz (320ms).

%d bloggers like this: