# Problema de temporización con pic 16f628a



## Mclaw (Nov 10, 2008)

Hola! 
A ver si alguien puede echarme una mano. Estoy realizando un programa en c con el compilador picc de hi-tech. El problema es que quiero obtener un cambio de nivel en una de las salidas cuando pase cierto tiempo y para ello he utilizado el timer0. Quiero que genere una señal cuadrada de unos 38 KHz por lo que la mitad del periodo será cada 13us aproximadamente. Tengo el siguiente código:

#include	<htc.h>

/*
 *	Example code for using timer0 on a 16F628A
 *	Just sets up a 13 us second interrupt and change the output RB5
 */


#define	PERIOD	1000000		// period in uS - one second here
#define	XTAL	4000000		// crystal frequency - 4MHz
#define IPERIOD	(4 * 1000000 / XTAL)	// Period of instruction clock in uSeconds
#define	RELOADS	242     // 255-13

/* service routine for timer 0 interrupt */
void interrupt
timer0_isr(void)
{
	// effect a change on PORTB whenever our desired period is reached.
	// Note this timing will contain a margin of error.
	TMR0 = RELOADS;
	RB5 = !RB5;				// effect a change on RB5
	T0IF = 0;
}

main()
{
	// initialize timer 0; 

	OPTION = 0b1000;	// prescale by 1:1
	T0CS = 0;			// select internal clock
	T0IE = 1;			// enable timer interrupt
	GIE = 1;			// enable global interrupts
	TRISB = 0;			// output port
	RB5 = 0;
	OSCF = 1;
	for(;
		continue;		// let interrupt do its job
}

El problema es que me genera una señal de 1.97 KHz en lugar de una de aproximadamente 38 KHz y no se porque.  No se si cargo el valor correcto así que he probado con RELOADS valiendo 13 y 242 pero da igual porque da la señal de 1.97 KHz.
Alguien me puede decir que estoy haciendo mal? Se lo agradecería en el alma ya que no consigo encontrar la solución.

Gracias por adelantado.


----------



## Ardogan (Nov 11, 2008)

Vi tu mensaje ayer y revisé hasta donde se (no uso el picc pero tengo idea de como configurar los módulos), y realmente no veo el problema en el código.

Ahora estás tratando de hacer con el módulo CCP (https://www.forosdeelectronica.com/posts/149174/), y tampoco sale.

Lo único que se me ocurre es que tu reloj no sea de 4 Mhz. Esto lo estás probando ya en el circuito armado o con un simulador?. Estás seguro de que es de 4 MHz?.
Si estás 100% seguro de que el reloj está bien, seguí leyendo.

Algo a tener en cuenta al escribir TMR0:



> Any write to the TMR0 register will cause a 2 instruction cycle (2TCY) inhibit. That is, after the
> TMR0 register has been written with the new value, TMR0 will not be incremented until the third
> instruction cycle later (Figure 11-2)


(Referencia: Timer0 - PICmicro Mid-Range MCU Family

Esos 2 Tcy son 2us para tu caso, así que tendrías que restarle 2 al valor del timer0.

Otra cosa que se me ocurre al trabajar con interrupciones tan frecuentes es que no le des tiempo de ejecutarse a la rutina de interrupción.
Pensa que haciendo interrupciones cada 13 us eso te marca el tiempo máximo que podés dedicarle a la rutina de interrupción, a 1 us por instrucción serían 13 instrucciones máximo (13 instrucciones de assembler no de C, las instrucciones call valen doble y las de retorno de rutina también, la instrucción GOTO también).

Para hacerlo con el timer0 tendrías que hacer la rutina de interrupción directamente en assembler, para estar seguro de los tiempos.

Por ahí si tenés que hacer solamente eso te convendría poner la rutina directamente en el bucle del main, pero estarías limitado a que se puede hacer eso solamente. Igual con una interrupción tan frecuente, tampoco vas a poder hacer muchas cosas más.

Me parece mejor solución usar el módulo CCP como planteaste en tu otro post, porque usas directamente el hard del PIC y no tenés que dedicar el casi 100% de tiempo a generar el tren de pulsos. Ahora me fijo en aquel otro post.

Saludos


----------



## Mclaw (Nov 11, 2008)

Muchas gracias por responder ya que cualquier ayuda es buena y realmente agradezco mucho que haya gente que se preocupe por ayudar a otros. 

Yo también he pensado que puede ser algo del reloj ya que tiene dos modalidades, para su reloj interno, una de 4MHz y otra de unos 48 KHz. Pensé que podría ser que el reloj fuera de 48 KHz pero hay una bandera en el registro PCON llamada OSCF que si la pongo a 1 elijo el oscilador a 4 MHz. Lo probé pero no se si tengo que hacer algo más para indicar que el reloj es de 4 MHz. 

Utilicé en otro proyecto el MikroC y la frecuencia se le indicaba directamente pero en MPLAB es diferente, no se si habrá que hacer algo más ...


----------



## biker2k3 (Jul 1, 2010)

Creo ke es medio viejo este post pero les cuento que pude hacer un timer ke incremente una variable cada 100us exactos en PBP :O me costooooo un dia entero pero logre dar con el resultado y lo probe en el PIC Simulator IDE en modo step de a una instruccion y anotando el tiempo en ke cambia la variable, use un crystal de 20mhz prescaler de 1/16 y el tmr0 en 226, con esto me daba 99us y para completar el us que faltaba repeti una linea de codigo 5 veces.


----------

