Autor Tema: Encender un led por interrupcion  (Leído 4685 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado badtzdizzy

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 234
Encender un led por interrupcion
« en: 11 de Agosto de 2004, 12:38:00 »
Hola, estoy tratando de encender un led por interrupcion, es decir que cada 2 ms se encienda el led pero no se que estoy haciendo mal, me podrian echar una mano?
Codigo:

#include <16f874A.h>
#fuses HS, NOPROTECT, NOWDT, NOPUT, NOBROWNOUT, NOLVP, NOCPD, WRT
#use delay(clock=20000000)

#int_RTCC
pulse()
{
output_high(PIN_B7);
delay_us(500);
output_low(PIN_B7);
}

main()
           {
   enable_interrupts(GLOBAL);
                enable_interrupts(INT_RTCC);
                setup_counters(RTCC_INTERNAL, RTCC_DIV_8);
                set_rtcc(6);
                while(TRUE);
           }


De antemano gracias por la ayuda

Desconectado oshow

  • PIC18
  • ****
  • Mensajes: 321
RE: Encender un led por interrupcion
« Respuesta #1 en: 11 de Agosto de 2004, 13:30:00 »
Lo he hecho bastante rapido, y puede haber algún fallo, pero lo he simulado en proteus perfectamente. He cambiado el pin B7 por el B0, solo por comodidad, ya que tenia un esquema hecho en Proteus.

También creo que has hehco mal los calculos, para temporizar 2ms con ese cristal y ese prescaler, no puedes cargar el timer0 con 6.

Si mis calculos no me fallan se ha de cargar con 236.

Otro fallo importante es que se te había olvidado volver a cargar el timer0 cuando entras en la interrupción.

Codigo:

#include <16f874A.h>
#fuses HS, NOPROTECT, NOWDT, NOPUT, NOBROWNOUT, NOLVP, NOCPD
#use delay(clock=20000000)

#int_RTCC
pulse()
{
       
       output_high(PIN_B0);
       delay_us(500);
       output_low(PIN_B0);

       set_rtcc(236);
}

main()
           {
   setup_counters(RTCC_INTERNAL, RTCC_DIV_8);
                enable_interrupts(INT_RTCC);
                enable_interrupts(GLOBAL);
               
                set_rtcc(236);
                while(TRUE);
           }



Pruebalo y cuentas....

Saludos

Desconectado badtzdizzy

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 234
RE: Encender un led por interrupcion
« Respuesta #2 en: 11 de Agosto de 2004, 14:02:00 »
Hola, muchas gracias por la ayuda. Ahorita tengo otro problema pero creo que es el PIC que ya chafeó. Oye una pregunta: ¿Cómo se obtienen los valores a cargar en el set_rtcc dependiendo del cristal? Gracias.

Desconectado Modulay

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2651
RE: Encender un led por interrupcion
« Respuesta #3 en: 11 de Agosto de 2004, 16:29:00 »
¿Con medio milisegundo de pulso consigues ver como se enciende?

Desconectado badtzdizzy

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 234
RE: Encender un led por interrupcion
« Respuesta #4 en: 11 de Agosto de 2004, 17:52:00 »
En eso tienes razón, finalmente lo voy a ver con ayuda de un osciloscopio, pero de todos modos no se que está pasando que no pasa nada.
Ahora estoy estudiando un poco mas para ver que puedo cambiar.

Desconectado oshow

  • PIC18
  • ****
  • Mensajes: 321
RE: Encender un led por interrupcion
« Respuesta #5 en: 11 de Agosto de 2004, 17:59:00 »
Vaya, por responder a prisa, me he colado en el calculo de la temporización.

Con ese prescaler no puedes temporizar directamente 2ms, Tmax=(256*8*4)/20Mhz

El resultado de esta operación es 409.6useg. que es menor que el tiempo que quieres temporizar (2ms).

Soluciones, pues puedes cambiar el prescaler, si lo cambias a 64, Tmax=(256*64*4)/20Mhz el resultado será 3.2768ms que es mayor que 2ms y por lo tanto ya lo podrás temporizar.

Puedes utilizar el timer1 que es de 16 bits y te permite contar con ese prescaler los 2ms perfectamente, o también si no quieres usar otro timer ni cambiar el prescaler, puedes hacer bucles.

Puedes temporizar por ejemplo 200useg 10 veces  así tienes tus 2mseg.  Ejecutarías la interrupción que se ejecutaría cada 200us diez veces.

En cuanto al valor para llevar al timer0, solo tienes que echar un vistazo a las notas de microchip de como calcular una temporización o mirar por el foro que hay mucha información.

Saludos.

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
RE: Encender un led por interrupcion
« Respuesta #6 en: 12 de Agosto de 2004, 04:53:00 »
¿Como lo vas a ver encendido con 0,5ms?

Si lo quieres ver luciendo cámbialo a por ejemplo delay_ms(500); estaría medio segundo encendido.

Prueba con otros valores <--> temporizaciones.

Desconectado Modulay

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 2651
RE: Encender un led por interrupcion
« Respuesta #7 en: 12 de Agosto de 2004, 04:59:00 »
Pues si,parece difícil;pero ahora que lo pienso,si la interrupción se produce también en un lapso de tiempo de magnitud similar quizá se consiga en los terminales del led una tensión media suficiente para hacerlo lucir de forma que sea perceptible al ojo.
Pero claro,mejor como dice Pocher,prueba con temporizaciones mas amplias y cuando veas que luce ya puedes experimentar y ajustarlas a tu gusto.
Un saludo

Desconectado oshow

  • PIC18
  • ****
  • Mensajes: 321
RE: Encender un led por interrupcion
« Respuesta #8 en: 12 de Agosto de 2004, 05:30:00 »
Bien, vamos por partes, como bien te dicen mas arriba, es casi impsoble ver parpadear un led a esa frecuencia, a pesar de eso, he modificado tu codigo, dejando ese parpadeo, para que veas como debería saltar la interrupcion cada 2ms.

Bien como ya comente antes, me equivoque en el calculo de la temporización, con tu cristal a 20Mhz y ese prescaler no puedes temporizar directamente los 2ms. Como alternativa, te puse unas cuantas, cambiar el timer, el prescaler o hacer bucles, pues bien, he hecho esta última. He hecho una temporización de 200us y la repito 10 veces para obtener los 2ms.

Codigo:

#include <16F874A.h>
#use delay(clock=20000000)

#fuses HS, NOPROTECT, NOPUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD


#define interrupciones_por_200us 10


int contador=10;

#use fast_io(A)
#use fast_io(B)
#use fast_io(C)

#INT_RTCC
void clock_isr(void)
{

   

   if(--contador == 0)
      {
         output_high(PIN_B0);
         delay_us(500);
         output_low(PIN_B0);

         contador=interrupciones_por_200us;
      }
     
      set_rtcc(131);
}

void main()
{
   

   set_tris_a(0xFF);
   set_tris_b(0b11111110);
   set_tris_c(0xFF);

   setup_counters( RTCC_INTERNAL, RTCC_DIV_8);
   enable_interrupts(INT_RTCC);
   enable_interrupts(GLOBAL);
   
   set_rtcc(131);

   while(TRUE);

}





Eso sería mas o menos lo que quieres no?, ahora bien si o que quieres es simplemente ver como parpadea un led con la interrupcion del timer 0, he hecho este otro ejemplo.

Aquí, utilizo tu mismo cristal (20Mhz) y prescaler, pero hago parpadear al led cada medio segundo, para que se pueda ver.

Codigo:

#include <16F874A.h>
#use delay(clock=20000000)

#fuses HS, NOPROTECT, NOPUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD

#byte port_b=6

#define interrupciones_por_medio_segundo 5000


int16 contador=5000;

#use fast_io(A)
#use fast_io(B)
#use fast_io(C)

#INT_RTCC
void clock_isr(void)
{



   if(--contador == 0)
      {
         port_b=~port_b;

         contador=interrupciones_por_medio_segundo;
      }

      set_rtcc(193);
}

void main()
{


   set_tris_a(0xFF);
   set_tris_b(0x00);
   set_tris_c(0xFF);

   setup_counters( RTCC_INTERNAL, RTCC_DIV_8);
   enable_interrupts(INT_RTCC);
   enable_interrupts(GLOBAL);

   set_rtcc(193);

   while(TRUE);

}




Fijate que aquí he contado 5000 veces 100useg para obtener los 0,5 segundos. También has de fijarte que hago complemento a todo el puerto B no solo al pin B0, pero como ejemplo te sirve igual, conencta el led solo a ese pin.

En cuanto a como hago las temporizaciones, pues hago lo que pone en las notas de microchip para hacer una temporización, no cambia nada el que uses c o ensamblador, el micro trabaja de la misma forma, lo unico que hace al temporizar es "consumir" instrucciones sin hacer "nada" (NOP´s). Para conseguir info sobre las temporizaciones busca en las notas de microchip o por el for que seguro que encontraras mucha información.

Saludos.

Desconectado badtzdizzy

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 234
RE: Encender un led por interrupcion
« Respuesta #9 en: 12 de Agosto de 2004, 14:52:00 »
Gracias a todos por la ayuda creo que ahora voy entendiendo mejor esto de las interrupciones y pues ahora se que tengo que ponerme a estudiar.

Oye oshow, podrías explicarme los calculos que realizaste para encontrar el valor a colocar en el set_rtcc, creo que ahí es donde radica mi principal problema. Gracias por todo.

Desconectado oshow

  • PIC18
  • ****
  • Mensajes: 321
RE: Encender un led por interrupcion
« Respuesta #10 en: 12 de Agosto de 2004, 16:00:00 »
De tu pregunta deduzco que eres nuevo con esto de los pic, porque realizar una temporización con un pic es algo básico y fundamental.

Si estas empezando, también te comento que el C no es lo mejor para empezar, sin duda es el ensamblador , para saber como trabaja el pic y sus registros , los timers, interrupciones, etc. Pero bueno, yo no soy nadie para aconsejar a alguien por donde debe empezar, solo es un comentario...así que te comento como he calculado los valores del TMR0 y tú eliges, vale?

En cuanto a como calcular el número de ciclos a llevar al TMR0 para realizar una temporización son los mismos calculos que he realizado unos mensajes más arriba:

Tiempoa temporizar=(Nºciclos*4*Prescaler)/Foscilacion

TMR0=256-Nºciclos, este resultado final es el que hay que llevar al TMR0.

Si quieres saber de donde salen estos calculos (cosa mas que recomendable para conocer los timers del pic) te remito a la web de microchip y a sus notas de aplicación.

Bueno, espero que te haya podido servir de ayuda.

Saludos.

Desconectado badtzdizzy

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 234
RE: Encender un led por interrupcion
« Respuesta #11 en: 12 de Agosto de 2004, 18:04:00 »
La verdad pues si soy nuevo con esto de las interrupciones y las temporizaciones, en la escuela yo programaba en ensamblador para el HC11, pero ahora que trabajo con el PIC pues lo estoy haciendo en C. De verdad gracias por la ayuda, finalmente logré la señal que queria con este código:
Codigo:

#include <16f874A.h>
#fuses HS, NOPROTECT, NOWDT, NOPUT, NOBROWNOUT, NOLVP, NOCPD, WRT
#use delay(clock=20000000)

#INT_RTCC
pulso()
{
      set_rtcc(100);
      output_high(PIN_B7);
      delay_us(1000);
      output_low(PIN_B7);
}

main()
   {
      set_tris_b(0x00);
      set_rtcc(100);
      setup_counters(RTCC_INTERNAL,RTCC_DIV_64);
      enable_interrupts(INT_RTCC);
      enable_interrupts(GLOBAL);
      while(TRUE);
   }



 

anything