Sie sind auf Seite 1von 16

PIC18F4550 Timer Capture (CCP) mode

Introduction
Input Capture is widely used in many applications such as:

 Capturing the arrival time of an event


 Measuring pulse width
 Measuring period
An event can be represented by the rising and falling edges of a pulse.
                                         

 
The time of an event occurrence can be recorded by latching the count when an edge is detected (rising or falling). This can be done using input
capture mode in the microcontrollers.
PIC18F4550 has an in-built CCP (Capture / Compare / PWM) module which has input capture mode. The input capture of the signal has applications
like finding frequency, calculating duty cycle of the input signal etc. 
Let us see the capture mode in PIC microcontroller 18F4550.
PIC18F4550 has two CCP modules -  
1. CCP1
2. CCP2
Here, we will be discussing CCP1 module.
In capture mode, input pulse should be connected to CCP1 which is multiplexed with PORTC.2 (RC2) as shown below, and configure it as the input
pin.
 

PIC18F4550 Capture Pins


PIC18F4550 Capture mode Pins
 
CCP1 module is able to use only the following two timers
1. Timer1
2. Timer3
 

Working of Capture Mode


Now, how capture mode works?
 Timer1 or Timer3 are initialized to count the value in the capture operation.
 T3CON register is used for selecting the Timer1 / Timer3 for input capture shown above.
 When the rising or falling edge is detected at CCP1 pin, the interrupt flag CCP1IF bit is set. It is cleared through software.
 When an interrupt occurs, the value of the timer is copied into CCP register CCPR1 (CCPR1H and CCPR1L), and by looking at this value we
are able to find the arrival time of that event.
 

Capture Mode (CCP) Registers


In PIC18F4550, different registers are used for capture mode.
1. CCPR1 Register is a 16-bit event capture register in which the event captured by timer1 or timer3 i.e. TMR1 or TMR3 register is copied. This is
done by the hardware itself. CCPR1L register and CCPR1H register are the two 8-bit registers that are used for lower and higher byte storage,
respectively.

CCPR1 Register
 
2. CCP1CON Register : CCP Control Register
This is an 8-bit register used to select the capture mode. Let’s see the bit configuration of this register.

CCP1CON Register
 
CCP1M3 : CCP1M0 : CCP1 Mode Select bits
         0100 = Capture mode is selected for every falling edge detected.
         0101 = Capture mode is selected for every rising edge detected.
         0110 = Capture mode is selected for every 4th rising edge detected.
         0111 = Capture mode is selected for every 16th rising edge detected.
And the other combinations of these bits are used for Compare and PWM mode.
DCxB1 and DCxB0 are used for PWM mode only.
CCP1IF Interrupt Flag

 After a capture event occurs, the interrupt flag is set.


 This interrupt flag is CCP1IF (CCP interrupt flag) which is located in the PIR1 register. The PIR1 register is shown below.
PIR1 Register : Peripheral Interrupt Register

PIR1 Register
 
CCP1IF :
      1 = TMR1 or TMR3 register capture occurred (at falling or rising edge of pulse)
      0 = No TMR1 or TMR3 capture occurred.
We need to enable this (CCP1IF) flag by enabling the CCP1IE bit (CCP Interrupt enable bit) in the PIE1 register.
PIE1 Register : Peripheral Interrupt Enable

PIE1 Register
 
T3CON Register : Timer3 Control and Status Register
T3CON register is used for selecting a timer for the capture mode. This is shown below

T3CON Register
 
T3CCP2 : T3CCP1 (bit 6 and bit 3)
These two bits in combination are used for Timer and Capture mode selection.
      00 = Timer1 is the capture / compare clock source for both the CCP modules.
      01 = Timer3 is the capture / compare clock source for the CCP2,
              Timer1 is the capture / compare clock source for the CCP1
      1x = Timer3 is the capture / compare clock source for both the CCP modules.
RD16 :
This bit is used to specify that the Timer3 register is 16-bit (TMR3) or two 8-bit (TMR3H and TMR3L).
      RD16 = 1, Enable one 16-bit register.
      RD16 = 0, Enable two 8-bit registers.
The setting of this bit is required only when we select Timer3 for the capture mode.
Otherwise, RD16 in T1CON register is used for Timer1.
 

Steps for Programming Capture (CCP) Mode


Initialization of PIC18F4550 Capture mode
1. Initialize the CCPCON1 register for capturing the rising or falling edge.
2. Configure CCP1 pin as an input pin.
3. If you are using Timer3, then configure T3CON register to select Timer3 for input capture; otherwise, Timer1 is a default.
4. Also, set the value of T1CON or T3CON register for deciding whether timer register should be two 8-bit (TMRxL and TMRxH) or 16-bit
(TMRx).
5. Set CCPR1 and TMR3 / TMR1 register to 0.
Note: ’x’ is for 1 or 3.
CCP1CON = 0x05; /* Capture mode is selected for detecting rising edge */
CCPR1 = 0x00; /* Clear CCPR1 register for counting*/
T1CON = 0x80; /* Enable 16-bit TMR1 register, no pre-scale,
use internal clock, timer OFF */

 
Capture Operation
1. Make timer ON.
2. Monitor until CCP1IF flag==1, which is set when capture occurs.
3. Copy the value of the CCPR1 register to any data variable and get a time of event occurrence.
 

Application
Let’s design an application using PIC18F4550 in which we will measure Frequency of the input signal and display it on 16x2 LCD. The input signal is
connected to CCP1 (RC2) pin for frequency measurement.
/*
Frequency Measurement using Input Capture Mode in PIC18F4550
http://www.electronicwings.com
*/
#include <stdio.h>
#include <stdlib.h>
#include <p18f4550.h>
#include "osc_config.h"
#include "LCD_8bit_file.h"
#include <string.h>

#define f_timer 2000000

void main()
{
unsigned long signal_period,data1,data2;
unsigned long frequency_Hz[20];
float Frequency;
TRISCbits.TRISC2=1;
OSCCON=0x72; /* set internal clock to 8MHz */
LCD_Init();
memset(frequency_Hz,0,20);
LCD_String_xy(0,1,"Pulse");

PIE1bits.CCP1IE=1;
PIR1bits.CCP1IF=0;
CCP1CON=0x05; /* Capture mode is selected for detecting Rising edge */
CCPR1=0x00; /*CCPR1 is capture count Register which is cleared initially*/
TMR1IF=0;
T1CON=0x80; /* Enable 16-bit TMR1 Register,No pre-scale,use internal clock,Timer OFF */
TMR1=0;
TMR1ON=1; /* Turn-On Timer1 */
while(1)
{
while(!(PIR1bits.CCP1IF)); /*Wait for Interrupt flag which is generated when edge is detected*/
PIR1bits.CCP1IF=0;
data1 = CCPR1; /*Copy count of 1st edge detected*/

while(!(PIR1bits.CCP1IF)); /*Wait for Interrupt flag which is generated when edge is detected*/
PIR1bits.CCP1IF=0;
data2 = CCPR1; /*Copy count of 2nd edge detected*/

if(data1 < data2)


{

/*Calculation for Frequency Measurement*/


signal_period = data2 - data1;
Frequency = ((float)f_timer / (float)signal_period); /*Count for 1 cycle*0.5us gives period */
sprintf(frequency_Hz,"%.3f ",Frequency);

LCD_String_xy(2,0,frequency_Hz);

}
TMR1=0;
memset(frequency_Hz,0,20);
}
}
PIC18F4550 Timer Compare Mode
Introduction 
 PIC18F4550 has inbuilt CCP module which has Capture, Compare and PWM mode for various applications.
 CCP in Compare mode is used to generate waveform of various duty cycle like PWM and also used to trigger an event when pre-determined
time expires.
 Also it is used to generate specific time delay.
 PIC18F4550 has 2 in-built CCP module i.e. CCP1 and CCP2.
 Output (e.g. Waveform generation) of CCP2 and CCP1 in compare mode is generated on two pins i.e. RC1 and RC2 respectively.

CCP module Pins


                      

PIC18F4550 Compare mode Pins


 
CCPR1 Register
CCP module has 16-bit register CCPR1 [CCPR1H (8-bit):CCPR1L (8-bit)] given below in which count is loaded to compare.
   
CCPR1 Register
 
The compare mode of CCP module is selected using bits in CCP1CON Register.
Only Timer1 and Timer3 can be used for Compare mode in PIC18F4550.
 

Operation of Compare mode


                 

Operation of Compare mode


 
In compare mode, the 16-bit CCPR1 register value is constantly compared against either the TMR1 or the TMR3 register pair value shown in figure
given below.
 When match occurs between CCPR1 Register value and Timer value, CCP1IF interrupt flag is generated and one of the following actions may occur
on the associated RC2 pin:
1. Toggle output on RC2 pin.
2. RC2 pin drives to High level.
3. RC2 pin drives to low level.
4. Generate software interrupt
5. Generate special trigger event.
Now what output logic will generate when compare match occurs depend on CCP1CON register.
CCP1CON Register: CCP1 Control Register

CCP1CON Register
 
DC1B1:DC1B0:
Used for PWM mode.
CCP1M3:CCP1M0: CCP1 module mode select bit
These bit decides which action takes on compare match.
              0010 = Toggle output on match
              1000 = Initialize CCP1 pin low, on compare match this pin is set     
               to high.
              1001 = Initialize CCP1 pin high, on compare match this pin is set    
                 to low.
              1010 = On compare match generates software interrupt.
              1011 = On compare match trigger special event, reset timer, start
               ADC conversion.
So Configure compare mode as per application using CCP1CON Register.  
Other combinations are used for Capture and PWM mode.
Interrupt on Match
Also remember that after every compare match between CCPR1 and Timer1/Timer3 CCP1IF interrupt flag is set.
This flag is located at PIR1<bit2> Register.
Also note that T3CON register is used to select Timer1 or Timer3 for compare mode.
T3CON Register: Timer3 Control Register

T3CON Register
 
T3CCP2:T3CCP1: Used to select Timer for Compare mode operation.
             00 = Timer1 for both CCP module
             01 = Timer1 for CCP1 module
                      Timer3 for CCP2 module
              1x = Timer3 for both CCP module
Calculation
Now How to calculate Count for CCPR1?
Following figure illustrates steps to calculate count for desired delay which to be load into CCPR1 Register.
     

Calculation steps for CCPR1 Count


 

Steps for Programming


1. Set CCP1 pin as an output.
2. Configure T3CON Register for Timer1 or Timer 3
 If Timer1 is used then configure T1CON Register also.
3. Configure CCP1CON Register for compare mode.
4. Load desired count in CCPR1 (CCPR1H: CCPR1L) Register.
5. Also initialize TMR1 or TMR3 Register value.
6. Start Timer
7. Wait for CCP1IF (PIR1<2>) interrupt flag to set.
8. Then Clear Timer Register (TMR1 or TMR3).
9. Jump to step 3.
 

Application 1
Here let’s generate a square wave of 1 KHz having 50% duty cycle.
For 50% Duty Cycle
Assume Oscillator frequency = 8MHz
Period of waveform = 1ms (1 KHz given)
So Instruction Cycle = 1/ (FOSC/4) = 1/ (8MHz/4) = 0.5 us
That means Timer will increment its count continuously after each 0.5us delay.
Here I used Timer3 register.
Now calculate CCPR1 count.
For 50% Duty Cycle – ON time=OFF time=0.5ms
           0.5ms/0.5us = 1000 i.e. 0x03E8
           CCPR1 = 0x03E8
/*
* Generate waveform of 1KHz having 50% duty cycle
* https://www.electronicwings.com
*/

#include "osc.h"
#include <p18f4550.h>

void main()
{
OSCCON=0x72; /* Configure internal clock at 8MHz */
TRISCbits.TRISC2=0; /* Configure RC2 pin as output */
CCP1CON=0x02; /* Module is configured for compare mode and is set up so that upon a compare match of CCPR1 and
TMR3, RC2 is driven low*/
PIR1bits.CCP1IF=0; /* Clear interrupt flag*/
TMR3=0; /* Clear Timer3 Register*/
T3CON=0xC0; /* Timer3 used for compare mode with TMR3 register in 16-bit format*/
CCPR1=1000; /* Load a count for generating 1khz*/
T3CONbits.TMR3ON=1; /* Turn On Timer3*/
while (1)
{
/* Wait for CCP Interrupt flag to set, it is set on compare match between CCPR1 and TMR3*/
while(PIR1bits.CCP1IF==0);
PIR1bits.CCP1IF=0;/* Clear interrupt flag */
TMR3=0;
}
}

 
Output

 
 

Application 2
Now generate another 1KHz waveform with 40% duty Cycle.
For 40% Duty Cycle,
 ON time=0.4ms, OFF time=0.6ms
0.4ms/0.5us = 800 i.e. 0x0320
0.6ms/0.5us = 1200 i.e. 0x04B0
Load these values into CCPR1 Register
/*
* Generate waveform of 1KHz having 40% duty cycle
* https://www.electronicwings.com
*/

#include "osc.h"
#include <p18f4550.h>

void main()
{
OSCCON=0x72; /* Configure internal clock at 8MHz */
TRISCbits.TRISC2=0; /* Configure RC2 pin as output. */
CCP1CON=9; /* Module is configured for compare mode and is set up so that upon a compare match of CCPR1 and
TMR3, RC2 is driven high*/
PIR1bits.CCP1IF=0;
TMR3=0;
T3CON=0xC0; /* Timer3 used for capture mode with TMR3 register in 16-bit format*/
CCPR1=0x320; /* Load a count for generating 0.4ms*/
T3CONbits.TMR3ON=1; /* Turn On Timer3*/
while(1)
{
/* Wait for CCP Interrupt flag to set, it is set on compare match between CCPR1 and TMR3*/
while(PIR1bits.CCP1IF==0);
PIR1bits.CCP1IF=0; /* Clear interrupt flag*/
TMR3=0; /* Clear Timer3 Register*/
CCP1CON=8; /* CCP1 module is configured for compare mode and is set up so that upon a compare match
of CCPR1 and TMR3, RC2 is driven low*/
CCPR1=0x04B0; /* Load count for generating 0.6ms */
while(PIR1bits.CCP1IF==0);
PIR1bits.CCP1IF=0;
TMR3=0; /* Clear Timer3 Register*/
CCP1CON=9;
CCPR1=0x0320; /* Load count for generating 0.4ms */

}
}

 
Output
PIC18F4550 PWM
Introduction
Pulse Width Modulation (PWM) is a technique by which width of a pulse is varied while keeping the frequency of the wave constant.

PWM Generation
A period of a pulse consists of an ON cycle (5V) and an OFF cycle (0V). The fraction for which the signal is ON over a period is known as a duty
cycle.
 

 
E.g. A pulse with a period of 10ms will remain ON (high) for 2ms.Therefore, duty cycle will be
D = 2ms / 10ms = 20%
Through PWM technique, we can control the power delivered to the load by using ON-OFF signal. The PWM signals can be used to control the speed
of DC motors and to change the intensity of the LED. Moreover, it can also be used to generate sine signals.
Pulse Width Modulated signals with different duty cycle are shown below

PWM Duty Cycle


 
PIC18F4550 controller has in-built 10-bit PWM module known as CCP module. The pin CCP1 (RC2) is used for generating PWM signals. It needs to
be configured as output.
 

PIC18F4550 PWM Pins

PIC18F4550 PWM Pins


In PIC18F4550, only Timer2 can be used for PWM generation. TMR2 is a 16-bit Timer2 register which is used to hold the count.
In PIC18F4550 following registers are used for PWM generation.
Note: Here, we are using a CCP1 module. If we want to use CCP2 module then we need to modify register name as CCPR1L to CCPR2L, CCP1CON
to CCP2CON.
Also, make RC1 pin as output for PWM generation.
CCPR1H and CCPR1L register
In CCP module, there is a 16-bit register which is split as two 8-bit registers - CCPR1H and CCPR1L.

CCPR1 Register
 

 Only CCPR1L is used to decide the duty cycle of the PWM. CCPR1H is not user accessible for the PWM mode.
 As the PIC18F4550 generates a 10-bit PWM pulse, to set the duty cycle it uses 10-bit register. The higher 8 bits (MSBs) DC1B9: DC1B2 of
this register are in CCPR1L register (8-bit) and lower 2 bits(LSBs) DC1B1: DC1B0, which are used for a decimal portion in duty cycle, are in
CCP1CON register at bit 5 and 4 respectively.
 So the 10-bit value for duty cycle is represented by CCPR1L: CCP1CON<5: 4>
PR2 register

 It is an 8-bit register which is used to load a count for a period of the pulse (TPWM).
 

Working of PWM in CCP module

PIC18F4550 PWM Generation Working


1. Load the period value in a PR2 register and the duty cycle value in CCPR1L: CCP1CON<5: 4> registers and initialize CCP1 pin as an output.
2. Configure T2CON register and set the TMR2 register to 0. Also, start the Timer2.
3. Now when a match occurs between registers PR2 and TMR2, pin CCP1 is pulled high and TMR2 is cleared.
4. The value of CCPR1L along with the CCP1CON<5: 4> which is a count for duty cycle is moved to the CCPR1H.
5. Finally, TMR2 is compared with the CCPR1H along with two lower bits of a duty cycle. When matched, the pin CCP1goes low.
 
This is how PWM is generated in PIC18F4550.
 
CCP1CON register: CCP1 Control Register for PWM

CCP1CON Register
 
DC1B1: DC1B0
These two bits are LSBs which are used for defining the decimal value of a duty cycle.
CCP1M3: CCP1M0: CCP1 module mode select bits
11xx = PWM mode
Other combinations are used for capture and compare modes.
Calculations
Now how to set value for the PR2 register which defines the period value of a pulse.

 
where,
Fpwm – Frequency of PWM signal
 
Now, let us see how to set a value for the CCPR1L which decides the duty cycle of a pulse. We know that a duty cycle is some % of PR2 (period)
register. For example, if PR2 is 199 then 20% duty cycle of the 199 is given by,

e.g.
(CCPR1L: CCP1CON<5: 4>) = (199 + 1) x (20/100)
(CCPR1L: CCP1CON<5: 4>) = 40 = 0b0010100000
 
So, load MSB 8-bits of above result to the CCPR1L and 2 LSB bits in CCP1CON <5:4>.
i.e. CCPR1L = 0b00101000 = 0x28
      CCP1CON <5:4> = 0b00
Note: CCPR1L (duty cycle) value should be always less than or equal to the PR2 (period) value. If the CCPR1L value is greater than the PR2 value,
the pin CCP1 will not be cleared. This allows a duty cycle of 100% and gives output.
Note: But, if a PR2 value is exceeding 8-bit value i.e. 255 then we have to increase Timer2 pre-scale value.
Max PWM Resolution
   bits
The PWM duty cycle must be a value between 0 and (2 ^ PWM Resolution) - 1.
 

Steps for Programming


1. Load the PR2 value which will decide the period of the pulse.
2. Set the duty cycle by loading a value in the CCPR1L: CCP1CON<5: 4>
3. Configure the CCP1CON register for setting a PWM mode.
4. Initialize the pin CCP1as an output pin which will give PWM output.
5. Configure the T2CON register and enable TMR2 using T2CON
 

Application 1
Let us generate 10KHz PWM with 20% duty cycle.
/*
Generating 10KHz PWM with 20% duty cycle
www.electronicwings.com

*/

#include "osc_config.h"
#include <pic18f4550.h>

void main()
{

OSCCON = 0x72; /* Set internal clock to 8MHz */


TRISC2 = 0; /* Set CCP1 pin as output for PWM out */
PR2 = 199; /* Load period value */
CCPR1L = 40; /* load duty cycle value */
T2CON = 0; /* No pre-scalar, timer2 is off */
CCP1CON = 0x0C; /* Set PWM mode and no decimal for PWM */
TMR2 = 0; /* Clear Timer2 initially */
TMR2ON = 1; /* Timer ON for start counting*/

while(1);

Application 2
Now, let us control the intensity of LED by generating PWM with different duty cycle using PIC18F4550.

/*
* Control intensity of LED using PIC18F4550
* www.electronicwings.com
*/

#include "osc_config.h"
#include <p18f4550.h>

void MSdelay(unsigned int);

void main()
{
unsigned int duty_cycle;
OSCCON=0x72; /* set internal clock to 8MHz */
TRISCbits.TRISC2=0; /* Set CCP1 pin as output for PWM out */
PR2=199; /* load period value in PR2 register */
CCPR1L=1; /* load duty cycle */
T2CON=0; /* no pre-scalar,timer2 is off */
CCP1CON=0x0C; /* set PWM mode and no decimal value for PWM */
TMR2=0;
T2CONbits.TMR2ON=1; /* Turn ON Timer2 */
while(1)
{

for(duty_cycle=1;duty_cycle<199;duty_cycle++)
{
CCPR1L = duty_cycle; /* load duty cycle */
MSdelay(20);
}
MSdelay(500);

for(duty_cycle=199;duty_cycle>1;duty_cycle--)
{
CCPR1L = duty_cycle; /* load duty cycle */
MSdelay(20);
}
MSdelay(500);
}

void MSdelay(unsigned int val)


{
unsigned int i,j;
for(i=0;i<=val;i++)
for(j=0;j<165;j++); /*This count Provide delay of 1 ms for 8MHz Frequency */
}

Generate Two different PWM simultaneously


 We can generate two different PWM on PIC18F4550 on two different channels i.e. CCP1 and CCP2.
 But these generated PWMs will be of the same frequency. This is because to generate PWM, only Timer 2 is used which is common for
both the CCP1 and CCP2.
 So, the period count which is loaded in the PR2 register to compare it with Timer 2 (TMR2) register is shared/common. Thus, we can
generate two PWM with different duty cycle but with the same frequency.

Now, we will generate Two different PWM on CCP1(RC2) & CCP2(RC1) having the same frequency.

Here, CCP1 will generate PWM of 25% Duty Cycle whereas CCP2 will generate PWM of 50% Duty Cycle.
/*
* Generate Two PWM with different duty cycle on PIC18F4550
* www.electronicwings.com
*/
#include <xc.h>
#include "configuration_bit_header.h"

void main()
{
OSCCON = 0x76; /* Set internal clock to 8MHz */
TRISC1 = 0; /* Set CCP2 pin as output for PWM out */
TRISC2 = 0; /* Set CCP1 pin as output for PWM out */
PR2 = 199; /* Load period value */

/**** generate PWM on CCP1 ****/


CCP1CON = 0x0C; /* Set PWM mode and no decimal for PWM */
CCPR1L = 50; /* load 25% duty cycle value */

/**** generate PWM on CCP2 ****/


CCP2CON = 0x0C; /* Set PWM mode and no decimal for PWM */
CCPR2L = 100; /* load 50% duty cycle value */

/*configure Timer 2 for PWM*/


T2CON = 0; /* No pre-scalar, timer2 is off */
TMR2 = 0; /* Clear Timer2 initially */
TMR2ON = 1; /* Timer ON for start counting*/
while(1);
}

Das könnte Ihnen auch gefallen