1.3.3 CCP

Table 1-7. CCP Code Calculations
Modules Limit High Resolution
CCP1 16.38 ms 250 ns
Timer3

The Capture/Compare/PWM (CCP) module provides an accurate hardware and software method to measure the width of a pulse. The presented method requires the waveform to be periodic since a period measurement is taken.

OVERVIEW

The CCP can be set up to capture both a rising and falling edge of a waveform. A timer count value is captured when the CCP receives an event condition. An event is defined as one of the following:

  1. Every falling edge
  2. Every rising edge
  3. Every 4th rising edge
  4. Every 16th rising edge

An event on every 4th or 16th rising edge is typically used to calculate the period of a signal, as seen in Figure   1.

Figure 1-12. Calculating the Period over 16 Iterations of the Waveform

Timer1 is used on the PIC16 devices with Timer3 being another option on the PIC18 devices. When a capture is made, the timer value will be latched to the CCPRxL:H registers. As seen in Figure   1, a pulse width is defined as the time between a rising and falling edge. Since a pulse measurement requires both a rising and falling edge, the CCP module needs software intervention to capture both events.

Note: Clocking Timer1 from the system clock (FOSC) should not be used in Capture mode. In order for Capture mode to recognize the trigger event on the CCPx pin, Timer1 must be clocked from the instruction clock (FOSC/4).

Ideally, the pulse being measured is many times wider than the setup time required by the CCP module to switch between capturing the rising and falling edges. Often times, the pulse is much less than the required instruction clocks it takes to make the switch. Due to this limitation, a wiser method is to also take a period measurement. If the pulse measurement is greater than the period measurement, then subtract the period measurement from the pulse measurement until the result is less than the period.

The pulse measurement requires a period measurement as well, as seen in Figure   2.

Figure 1-13. Extracting the Pulse from Period Plus Pulse Capture

The period can be measured by setting the CCP to capture on every 16th rising edge provided that 16 periods are less than 65536 Timer1 clock periods. If that is the case then select one event or four events as the Capture mode. Make two captures and calculate the difference by subtracting the first value from the second value. Divide the result by 16 (four right shifts without extending the sign) to determine the period. It does not matter if the second capture value is less than the first when calculating the difference.

Code Snippet for Calculating A single Pulse Width in ‘Extracting the Pulse from Period Plus Pulse Capture’ figure above

// The pulse width may have been measured over the length
// of more than one period, so subtract the period
// out until the pulse width is less than the period.
while(MeasuredPulse > Period) MeasuredPulse -= Period;

SETUP

Steps to measure the period:

  1. Configure CCPXCON<3:0> to capture every 16th rising edge
  2. Configure Timer1 prescaler for the lowest setting without overflowing on the 16th rising edge
  3. Enable the CCP module and timer
  4. Wait until the 16th rising edge
  5. Disable CCP module and save CCPRX in a temporary variable (value1)
  6. Enable the CCP module
  7. Wait for 16 edges
  8. Disable CCP module and timer
  9. The period is now
    Period_16 = CCPR1 - value1
    Period = Period_16 >> 4

CCP Period Operation Code

Operation Code
    CCP1CON<3:0> = 0b0111;    // or '0b0110' for every 4th rising edge (Step 1)
    // Configure Timer1 prescaler - (Step 2)
    CCP1CONbits.EN = 1;           // (Step 3)
    T1CONbits.TMR1ON = 1;         // (Step 3) 
    while(!PIR2bits.CCP1IF);      // (Step 4) 
    CCP1CONbits.EN = 0;           // (Step 5)
    value1 = CCP1_CaptureRead();  // same as "(CCPR1H << 8) + CCPR1L)" (Step 5)
    PIR2bits.CCP1IF = 0;          // Clear Flag, (Step 5)
    CCP1CONbits.EN = 1;           // (Step 6)
    while(!PIR2bits.CCP1IF);      // (Step 7)
    CCP1CONbits.EN = 0;           // (Step 8)
    T1CONbits.TMR1ON = 0;         // (Step 8) 

Steps to measure the pulse:

  1. Configure CCPXCON<3:0> to capture every rising edge
  2. Configure Timer1 prescaler for the lowest setting without overflowing before period
  3. Enable the CCP module and timer
  4. Wait for a rising edge
  5. Disable CCP module and save CCPRX in a temporary variable (value2)
  6. Configure CCPXCON<3:0> to capture every falling edge
  7. Enable CCP module
  8. Wait for a falling edge
  9. Disable CCP module and timer
  10. The pulse width is now:
    
    MeasuredPulse = CCPRX - value2
    while(MeasuredPulse > Period) MeasuredPulse -= Period;

CCP Pulse Operation Code

CCP1CON<3:0> = 0b0101;        // (Step 1)
// Configure Timer1 Prescaler - (Step 2)
CCP1CONbits.EN = 1;           // (Step 3)
T1CONbits.TMR1ON = 1;         // (Step 3) 
while(!PIR2bits.CCP1IF);      // (Step 4) 
CCP1CONbits.EN = 0;           // (Step 5)
value2 = CCP1_CaptureRead();  // same as "(CCPR1H << 8) + CCPR1L)" (Step 5)
PIR2bits.CCP1IF = 0;          // Clear Flag, (Step 5)
CCP1CON<3:0> = 0b0100;        // (Step 6)                              
CCP1CONbits.EN = 1;           // (Step 7)
while(!PIR2bits.CCP1IF);      // (Step 7)
CCP1CONbits.EN = 0;           // (Step 8)
T1CONbits.TMR1ON = 0;         // (Step 8) 

LIMITATIONS

The resolution of this measurement is a function of the PIC MCU instruction clock. The period of the waveform of interest must be at least two times the width of the instruction clock period. This is because the CCP module detection is synchronized to the clock and must register each rising and falling edge.