# Problema con el modulo CCP para generar una señal periódica con el P16F628A



## Mclaw (Nov 11, 2008)

Necesito realizar un código en C con el MPLAB para el compilador PICC de HI-TECH que genere una señal cuadrada de 38 KHz.

 Para ello me he planteado utilizar el módulo CCP del pic que estoy utilizando (el P16F628A) . La idea es cargar en el registro CCP1H:CCP1L el valor correspondiente a la mitad del ciclo y configurar el CCP en modo comparación para que cuando el Timer1 llegue a ese valor se resetee el valor de TMR1 y se genere una interrupción que me permita cambiar la salida de 0 a 1 o de 1 a 0 según corresponda. 

El oscilador debería de funcionar a 4 MHz y la frecuencia de instrucción una cuarta parte, 1MHz o un 1us. Como la mitad del periodo es aproximadamente 13us pues ese es el valor que cargo en el CCP1. 

El problema es que mi código no genera nada y no se donde me equivoco! Alguien podría decirme donde me estoy equivocando? 

#include <stdio.h>
#include <htc.h>

#define SALIDA RB5


unsigned short valor = 13;


/* service routine for ccp interrupt */
void 
interrupt CCP_isr(void) {
	TMR1ON = 0;						// detenemos el TIMER1
	TMR1IF = 0;						// limpiamos la bandera
	SALIDA = !SALIDA;				        // cambia el valor de la salida
	TMR1ON = 1;						//volvemos a ponerlo a contar
}

void 
main(void) {
									// initialize timer 1 and CCP module; 
	OSCF = 1;						// oscilador interno a 4 MHz
	CCP1CON = 0b00001011;			// módulo CCP en modo comaparación y reseteando el Timer1
	T1CON = 0;						// preescalado 1:1 modo oscilador OFF, TMR1CS = O internal clock..
	TRISB5 = 0;
	OSCF = 1;						// oscilator to 4 MHz (not to 38 KHz)
	CCP1IE = 1;						// activamos interrupciones para el módulo CCP1
	CCPR1L = (char)(valor & 0xFF);
	CCPR1H = (char)(valor >> 8);

	GIE = 1;						       // habilitamos las interrupciones globales
	TMR1IF = 0;
	TMR1ON = 1;						//comienza a contar

	for(;
		continue;					        // let interrupt do its job
}


----------



## Ardogan (Nov 11, 2008)

Lo primero que veo es que sería más fácil usar el modo PWM (me fijo, y te digo como )que el modo de comparación.
Lo segundo es que estás usando el TMR1 cuando para el módulo se usa el TMR2.
Asi que lo 1ro que tenes para hacer es configurar el TMR2 en vez del TMR1, y si no te anda acá estamos.

Saludos

------------------

Edición:

error! el TMR2 se usa para el módulo PWM, pero el TMR1 para comparación y captura.
Aunque creo que la cuestión también viene por el lado de los tiempos de interrupción como te dije acá.

Probá con PWM y te olvidás de las interrupciones!.

PWM period =(PR2+1)*4*Tosc * PRE_TMR2

para una señal de 38 KHz el periodo es = 26,3 us -> 26 us

en tal caso deberá ser

PRE_TMR2=1 y PR2 = 25

Para el ciclo de trabajo (0.5 para que sea cuadrada -> 13):

Ciclo trabajo = (CCPR1L:CCP1CON<5:4>) x Tosc x PRE_TMR2 (tiempo en nivel alto en realidad)

Un detalle interesante, fijate que el ciclo de trabajo (o mejor dicho el tiempo en nivel alto, puse ciclo de trabajo por traducción literal de la hoja de datos) podés manejar múltiplos de Tosc, y no de 4 Tosc.
Es decir, tenés resolución de 1/4 MHz = 250 ns ; el cuádruple que utilizando un timer.

Entcones para 13 us sería CCPR1L:CCP1CON<5:4> = 52.

Fuentes: hoja de datos y  Compare/Capture/PWM (CCP) - PICmicro Mid-Range MCU Family
---------------------
Contanos como te fué, saludos


----------



## Mclaw (Nov 11, 2008)

mmm es el Timer1 el que hay que usar para comaración, lo he comprobado en el datasheet pero sigo sin saber donde me equivoco


----------



## Mclaw (Nov 11, 2008)

Muchísimas gracias!
aún no puedo probarlo porque no tengo osciloscopio para probarlo, pero mañana os cuento! Ojalá que funcione!


----------

