Deshabilitar interrupciones dentro del codigo de otras

Hola tengo poco programando y tengo un problema al que ya le he dado muchas vueltas y no he podido resolver.
Estoy utilizando un PIC18F4525, CCS 4.0xx y proteus 7.2 SP6

Lo que estoy intentando hacer es un tablero de concursos, algo asi como los de la television, es de 8 participantes que pulsaran un boton y solo el que pulso primero debe de encender un LED respectivo para cada participante, estos botones los estoy metiendo al puerto A del pic y tambien los estoy metiendo todos a una logica OR, la salida de esta OR la utilizo para activarme la interupcion externa de RB0.

Cuando sucede la interupcion externa lo que hace es lo siguiente:
1.-Asignar el valor del puerto A aun variable llamada "participante" para que encienda su LED respectivo.

2.- Habilita la interupcion del timer0 o RTCC para que empiece a aumentar la variable "tiempo" con cada desborde, ya que el participante tiene 10 segundos para contestar, de terminarse el tiempo enciende todos los LED para indicar que se termino el tiempo (El timer0 esta habilitado como contador interno, se desborda a 1 segundo y de inicio u interupcion estaba deshabilita).

3.- Pone la variable tiempo=0 y setea el RTCC(0) para asegurar que el conteo del tiempo sea axacto.

4.- La interrupcion externa se deshabilita a si misma para que ignore las pulsaciones de los demas participantes y solo considere la primer pulsacion.

Una vez que la pregunta se contesto o que el tiempo se termino uso la interupcion 1 en RB1 de mi PIC18F4525 para prepara el programa para la siguiente pregunta lo que hago en el codigo de la interupcion es lo siguiente:
1.-Pongo la variables tiempo y participante =0
2.- Habilito de nuevo la interucion externa de RB0 y deshabilito la interrupcion del timer0, para deje de incrementar la variable tiempo y este listo para recivir la siguiente pulsacion.

"Este es el problema"
De inicio todo se ve bien si solo precionamos un boton de participante si enciende su respectivo led y precionamos el boton de RB1 si se alista para la siguiente pregunta...Perooo..cuando presiona mas de una vez cualquiera de los botones, es decir, cuando sucede mas de una vez la interupcion RB0 al momento de aplastar RB1 para preparar para la siguinte pregunta no es suficiente con aplastarlo una sola vez sino que necesita 2 veces para que haga lo que debe de hacer. Repito, este problema pasa cuando sucede mas de una vez la int_EXT, todo va bien cuando solo hay una interupcion externa.



Código:
#include <18F4525.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //Low power osc < 200 khz
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOMCLR                   //Master Clear pin used for I/O
#use delay(internal=8000000)
#use fast_io(c)
#use fast_io(b)
#use fast_io(a)
#define part input_a
#define salida output_c

int tiempo,participante;


#int_RTCC
RTCC_isr() 
{
   if (tiempo>=10){tiempo=0;participante=255;disable_interrupts(INT_RTCC);}
   tiempo++;
}

#int_EXT
EXT_isr() 
{
   enable_interrupts(INT_RTCC);disable_interrupts(INT_EXT);participante=part();tiempo=0;set_rtcc(0);
}

#int_EXT1
EXT1_isr() 
{
   tiempo=0;participante=0;disable_interrupts(INT_RTCC);enable_interrupts(INT_EXT);
}


void main()
{
   
   set_tris_a(0xff);
   set_tris_c(0x00);
   set_tris_b(0xff);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32);
   disable_interrupts(INT_RTCC); 
   enable_interrupts(INT_EXT);
   enable_interrupts(INT_EXT1);
   enable_interrupts(GLOBAL);
   tiempo=0;participante=0;
 
    while(1)
   {
    
    salida(participante);
   }
}


Lo que he observado es que la interrupcion externa 1 la primera vez que se ejecuta solo pone Tiempo=0 y participante=0, pero no hace las modificaciones correspondientes de las interrupciones, esto la hace hasta la segunta vez que se pulsa.

Quiza piensen que no es un gran detalle que se le tenga que aplastar 2 veces al boton pero este error no me deja agregarle mas funciones a mi programa.

De antemano muchas gracias por su tiempo amigos, espero con ancias sus respuestas.
 

Adjuntos

  • diagramatablerodeconcursos_388.jpg
    diagramatablerodeconcursos_388.jpg
    333.3 KB · Visitas: 21
Creo que te has complicado la vida gratuitamente

Algo asi deberia funcionar perfectamente sin interrupciones.


inicio:

bucle: leo puerto A
no se pulsado tecla salto bucle

guardo tecla
enciendo led (tecla)
tiempo =10000
bucle2:
tiempo=tiempo-1
nop
nop
nop
......
.....
si tiempo no es cero salta bucle 2
enciendo todos los led



Sin interrupciones, sin ors sin nada de eso.


Algunos detalles a tener en cuenta:

Los pulsadores son leeeeeeeentos, solo que los escanees cada 100ms hay suficiente,.
Ademas son ruidosos, al ser mecanicos rebotan y dan varios pulsos, por eso un contador se vuelve loco.
La tipica solucion es una vez pulsado queda inactivos como minimo esos 100ms, como regla memoristica utiliza la frecuencia de la red 1/50Hz.

No es necesario interrupciones, dentro del bucle principal los vas repasando repetidamente, pero sin prisas, tienes 100ms y eso para un micro es una eternidad.
Si el escaneo es mas rapido debes evaluar si es necesario añadirle un sistema antirevote.


Sobre el tema de la temporizacion hay varios metodos,

Metodo de perdida de tiempo:
Como el micro no tiene nada mas que hacer , pues que pierda el tiempo

tiempo=10000

bucle: tiempo=tiempo-1
nop
......
si tiempo no es 0 bucle


Utilizando el timer

timer=255-tiempo

bucle:
si flag timer bucle


sin necesidad de interrupciones



Sobre el esquema:

Eliminar las puertas, no son necesarias
Cuidado con las uniones, en el esquema tienes todos los pulsadores cortocircuitados.
Es recomendable anadir en paralelo a los pulsadores un condensador de unos 100nF evitaremos revotes muy largos y eliminara un poco las posibles interferencias.

Los diodos led mejor añadirles una resistencia limitadora de por ejemplo unos 330ohms.

Si deseas que los led sean mas grandes puedes utilizar un troz de espuma de plorexpan expandido como reflector, es el tipico corcho blanco de bolitas. Para cortarlo se utiliza un hilo caliento, pero calentando ligeramente un cuchillo tambien funciona.
Como portecion puedes utilizar CDROM transparetes lijados con papel de lija finillo para que funcione como difusor.
Finalmente solo se puede utilizar cianoclilatos (superglue) para el cocho blanco.
 
Ok muchas gracias por tus ecomendaciones tiopepe123 quedaron perfectamente entendidas, las tomare muy en cuenta.
Yo se que no es la unica manera de hacerlo, y si es mas sencillo como comentas pero ahora me gustaria saber por que no habilita y deshabilita correctamente las interupciones pertinentes dentro del codigo de otra interupcion, esto lo hace hasta la segunda vez que se pulsa la interrupcion. Ya que este es un proyecto personal, pero en el caso de que me tope con el mismo problema en algun proyecto de la universidad me gustaria saber el porque de esto.
Quiero saber si es un problema de prioridades de las interrupciones, ya que en los PIC18 ya se maneja esta cuestion o si simplemente no se puede activar/desactivar dos interupcciones, ya que me di cuenta que si manejo solo una si la cambia.

tiopepe123 dijo:
Sobre el esquema:

Eliminar las puertas, no son necesarias
Cuidado con las uniones, en el esquema tienes todos los pulsadores cortocircuitados.
Es recomendable anadir en paralelo a los pulsadores un condensador de unos 100nF evitaremos revotes muy largos y eliminara un poco las posibles interferencias.

Los diodos led mejor añadirles una resistencia limitadora de por ejemplo unos 330ohms.

Nota: El diagrama de proteus no esta cortocircuitado nada, las lineas pasan una encima de la otra para ahorar espacio por que desactive el wire autorouter, pero estan bien conectadas una independiente de las otra. Y este esquema es solo para simular, omiti las resistencias de los LED para hacerlo mas rapido, pero toda persona que conosca la ley de ohm sabe que hay que protejer los LEDs...jejeje
 
Gracias a las recomendaciones de tiopepe123 ya resolvi mi problema del tablero de concursos, deje de usar interrupciones y lo hice con ejecucion de codigo normal y asi me quedo genial. A continuacion pongo el codigo
Código:
#include <18F4525.h>
#device adc=8
#FUSES NOWDT, HS, NOPROTECT, NOPUT, MCLR
#use delay(internal=8M)
#use fast_io(a)
#use fast_io(b)

int participante=0,i=0;

void main()
{
   
   set_tris_a(0xff);
   set_tris_b(0x00);
   output_b(0xff);

   while(participante==0)
   {
      participante=input_a();
      delay_ms(50);
   }
   
   output_b(participante);
   
   for(i=0;i<15;i++)
   {
      delay_ms(1000);
   }
   
   output_b(0xff);
   participante=0;
   
   while(participante==0)
   {
      participante=input_a();
      delay_ms(50);
   }
   
   output_b(participante);
   
   for(i=0;i<10;i++)
   {
      delay_ms(1000);
   }
   
   output_b(0xff);
   participante=0;
   
   while(participante==0)
   {
      participante=input_a();
      delay_ms(50);
   }
   
   output_b(participante);
   
   for(i=0;i<5;i++)
   {
      delay_ms(1000);   
   }
   participante=0;
   output_b(0xff);
   delay_ms(2000);
   output_b(0x00);
}

Y ya le agrege las funciones extra que comentaba, ahora en caso del que el primer participante que presione no sepa la respuesta y se le termine el tiempo, el programa pide de nuevo que se presionen los botones para permitir a un segundo participante contestar, a este segundo le da 10 segundos, en el caso que no sepa le da oportunidad a un tercero que presiones primero y conteste en un tiempo de 5 segundos en caso de que este ultimo tampoco conteste, que seria un caso muy extremo, ya deja de ejecutar y no permite nada.
Utilice el master reset como boton para preparar el programa para la siguiente pregunta. Todo me va muy bien. Ahora estoy para implementarlo...gracias...
 

Adjuntos

  • diagramatablerodeconcursos_176.jpg
    diagramatablerodeconcursos_176.jpg
    247.6 KB · Visitas: 10
Hablando de interrupciones si dentro de la implementacion de por ejemplo

#int_ext2
void prueba(){
//dentro de este procedimiento se dehabilita automaticamente la int_ext2?
}

o hay que hacerlo manualmente

#int_ext2
void prueba(){
disable_interrupts(INT_EXT2);
// tratamiento de la interrupcion
}
 
Atrás
Arriba