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:
- O pino de saída (RC2/CCP1 ou RC1/CCP2 conforme o módulo) é setado;
- O pino de saída é apagado;
- O pino de saída tem o seu estado invertido (0->1 ou 1->0);
- O pino de saída não é alterado;
- 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.
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 }