Utilizando o Modo de Comparação do CCP do PIC18

Neste artigo eu falo um pouco sobre o modo de comparação das unidades CCP dos PIC18.

O modo de comparação funciona praticamente como o recíproco do modo de captura, ou seja, a contagem proveniente do temporizador de referência é constantemente comparada com um valor programado nos registradores do CCP (CCPRxH e CCPRxL). Quando a contagem do timer atinge o valor programado um evento de comparação é disparado originando por sua vez um dos seguintes eventos:

  1. O pino de saída (RC2/CCP1 ou RC1/CCP2 conforme o módulo) é setado;
  2. O pino de saída é apagado;
  3. O pino de saída tem o seu estado invertido (0->1 ou 1->0);
  4. O pino de saída não é alterado;
  5. Um evento especial é disparado (no caso do CCP1 este evento provoca o reset do timer 1 e no caso do CCP2 este evento provoca o reset do timer 1 ou timer 3 e também inicia uma conversão do ADC caso o mesmo esteja ativo).

Em todos os casos o evento de comparação também seta o flag de interrupção do módulo (CCP1IF ou CCP2IF).

Esta funcionalidade pode ser utilizada para gerar sinais periódicos, modificando o estado de um pino a cada intervalo de tempo ou gerando interrupções periódicas.

O figura abaixo mostra que, no instante em que a contagem do timer 1 atinge o valor programado nos registradores de comparação do canal 1 (CCPR1H e CCPR1L), um evento de comparação é gerado, fazendo com que o estado do pino CCP1 seja invertido. A ISR do CCP1 deverá providenciar a recarga dos registradores CCPR1H e CCPR1L com o valor desejado para a próxima comparação.

PIC18_CCP

Note que para a geração de sinais como o mostrado na figura é necessário recarregar o par de registradores CCPR1H e CCPR1L com o valor do próximo evento (somando-se o valor correspondente a metade do período ao conteúdo atual dos registradores de comparação).

O exemplo a seguir mostra a utilização dos módulos CCP1 e CCP2 operando no modo de comparação e gerando apenas interrupções. A ISR verifica qual módulo causou a interrupção e em seguida recarrega o respectivo par de registradores com o valor da próxima comparação.

Os dois módulos CCP utilizam o timer 1 como base de tempo para a comparação. O timer 1 é configurado para utilizar o clock do sistema (FOSC/4) dividido por 8. No caso da PK2Lab isto resulta em um clock igual a 4MHz/4/8 = 125kHz. Isto significa que cada unidade de incremento do timer 1 é equivalente a 1/125.000 = 8µs.

Adicionando-se 40.000 unidades a cada comparação do CCP1 fazemos com que ocorra uma comparação a cada 40.000*8µs=320ms. Assim, o período de piscagem do led L0 (conectado ao pino RC0) é igual a 640ms (1,56250Hz) e o período de piscagem do led L1 (conectado ao pino RC1) é igual a 320ms (3,125Hz).

#include <p18f4520.h>
#include <stdio.h>
#include "pic_simb.h"

#pragma config OSC = XT, WDT = OFF, MCLRE = ON
#pragma config DEBUG = OFF, LVP = OFF, PWRT = ON, BOREN = OFF
#pragma config CCP2MX = PORTBE

#define L0	LATCbits.LATC0
#define L1      LATCbits.LATC1

#pragma code isr = 0x000008
#pragma interrupt ISR
void ISR(void)
{
	if (PIR1bits.CCP1IF)
	{	// interrupção do CCP1
		PIR1bits.CCP1IF = 0;	// apaga flag de interrupção
		CCPR1 += 40000;		// soma o período ao CCP1
		L0 = !L0;		// inverte o estado do led L0
	}
	if (PIR2bits.CCP2IF)
	{	// interrupção do CCP2
		PIR2bits.CCP2IF = 0;	// apaga flag de interrupção
		CCPR2 += 20000;		// soma o período ao CCP2
		L1 = !L1;		// inverte o estado do led L1
	}
}
#pragma code

void main(void)
{	
	ADCON1 = 0x0F;			// desliga entradas analógicas
	TRISC = 0;			// RC0 a RC7 como saídas
	T1CON = bTMR1ON | bT1CLK_PRE8;	// Timer 1 ligado com prescaler = 8	
	CCP1CON = bCCP_COMPARE_INT;	// CCP1 no modo de comparação (interrupção)
	CCP2CON = bCCP_COMPARE_INT;	// CCP2 no modo de comparação (interrupção)
	LATC = 0;			// LEDs desligados
	INTCON = bGIE | bPEIE; 		// habilita GIE e PEIE
	PIE1 = bCCP1IE;			// habilita CCP1IE
	PIE2 = bCCP2IE;			// habilita CCP2IE
	while(1);			// loop infinito
}

Leave a Reply