Después de empacharme de datasheet, buscar info por el foro y tal no he conseguido hacer que el timer1 desborde cuando yo quiero...
A ver si mi deducción es correcta:
Uso el oscilador interno del pic 18f2550 (8 MHz), uso el prescaler por 2, y por tanto se produce un tick del reloj cada 1 us (8 MHz/4/2=1 MHz-> T= 1 us). Quiero que desborde cada 400 us, generando así una interrupción, por lo que deberá hacer 400 ticks (1 us * 400=400 us) antes de desbordar. Por tanto, deberé cargar el timer1 a 65536-400=61536. De esta forma, cada 400 us desbordará el timer1 ¿verdad? Sin embargo, no lo consigo, desborda cada 60 y pico ms..... Os dejo el código por si lo hiciese mal.
El código es un receptor serie, detecta el bit de start con la interrupción del puerto B y después deshabilita dicha interrupción, activa la del timer y recibe el dato. Una vez recibido todo el dato, se desactiva el timer y se reactiva la interrupción del puerto para volver a recibir otro dato.
El timer0 lo utilizo simplemente para comprobar que el pic funciona, haciendo parpadear un led cada cierto tiempo (no lo he calculado
, ya que no es importante).
#include <18F2550.h> //pic a utilizar
int orden=0, aux;
void ejecutaOrden();
#fuses INTRC_IO,NOWDT,NOPROTECT,PUT //ordenes para el programador
#use delay (internal=8M) //Fosc=8 Mhz interno
#use fast_io(b)
#use fast_io(c)
long int contador_led=0;
int contador_reloj=0;
#INT_RB
void bit_start(){ //Tras simularlo con el ISIS, vemos que con un periodo de reloj de 400 us le da tiempo
//al micro a detectar la interrupción. Ésta interrupción salta cuando llega el bit_start
//Después se desactiva, tras activar la interrupción del timer1.
if (input_state(PIN_B7)){ //En el semiciclo positivo del reloj....
contador_reloj=0;
disable_interrupts(INT_RB);
disable_interrupts(GLOBAL);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_2);
set_timer1(61536); //f=8MHz -> f/4/2=1 MHz-> T=1 us. Para que cuente 400 us: 65536-400=61536.
//Contamos 400 us, para detectar los pulsos correctos.
enable_interrupts(INT_TIMER1);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
}
}
#INT_TIMER0
void interrupcion(){
contador_led++;
if (contador_led==488){ //¿?
contador_led=0;
output_toggle(PIN_C0);
}
set_timer0(5); //Recargamos el timer.
}
#INT_TIMER1
void interrupcion1(){
contador_reloj++;
orden=orden<<1;
aux=input_state(PIN_B7);
orden=orden+aux;
if (contador_reloj==8){ //Si terminamos de recibir el dato, nos preparamos para un nuevo bit de start y ejecutamos la orden.
contador_reloj=0;
disable_interrupts(INT_TIMER1);
enable_interrupts(INT_RB);
ejecutaOrden();
}
set_timer1(61536);
}
//PROGRAMA
void main(void)
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2|RTCC_8_BIT); //Dado que la frecuencia del timer viene dada por:
//f(8MHz)/4/2(RTCC_DIV_2)=1MHz cada cuenta. Tiene 255 cuentas,
//por lo que creará una interrupción cada 255 us
set_timer0(5); //cargamoss un 5 para que desborde cada 250 us.
set_tris_c(0x00);
set_tris_b(0b10000001); //portb como toca
output_low(PIN_B1);
output_low(PIN_B2);
output_low(PIN_B3);
output_low(PIN_B4);
output_low(PIN_B5);
output_low(PIN_B6);
output_c(0x00);
enable_interrupts (INT_RB);
enable_interrupts(INT_TIMER0);
enable_interrupts (GLOBAL);
do{ //Si es una orden lenta, se va ejecutando en el bucle infinito.
}while (1); //Bucle infinito
}
void ejecutaOrden(){
if ((orden & 0b10000000)==0){ //Si es una orden ejecutable en el acto, se ejecuta aquí y se resetea la orden
switch (orden){
case 1: output_toggle(PIN_B1);
break;
case 2: output_toggle(PIN_B2);
break;
default: break;
}
orden=0;
}
}
Gracias de antemano por vuestra ayuda, estoy aprendiendo muchísimo con vuestro foro,
LoPiTaL