Interrupcion RB y boton
Hola amigos del foro:
Tengo un problema que me lleva trabajando varios días. He hecho muchas cosas para resolverlo y la verdad no he podido.
Entre las cosas que he hecho, por supuesto, es leer varios post que tratan asuntos similares y nada… Todo lo que les
contaré es en el ambiente de simulación paso a paso usando CCS 5.070 y Proteus 8.6 SP2 build 23525. El PIC es un 16f628A.
Estoy diseñando un equipo que tiene un solo botón (un display POV), la idea es simple:
El quipo enciende y transcurrido un segundo entra en modo sleep pero se queda “escuchando” dos fuentes de interrupciones:
la interrupción por CCP1 y la interrupción por cambio de estado en los puertos RB4-RB7. Le conecte un botón que cuando se
oprime por primera vez desactiva la interrupción por CCP1 y entra nuevamente al modo sleep, pero se queda solamente
esperando la interrupción por cambio de estado en los puertos RB4-RB7 (concretamente uso RB5).
Cuando se oprime el botón, sale adecuadamente del sleep, yo le hice, dentro de la interrupción por RB una rutina
antirebote un poco más extensa de lo normal (más de un segundo, para encender un led que indique que se está encendiendo o
apagando el equipo). El problema es que dicha interrupción, a veces sale y vuelve a entrar inmediatamente. Le puse un
clear_interrupts(INT_RB) y sigue haciendo lo mismo. En otras ocasiones fuera de la interrupción, se habilita la bandera de
la interrupción RB estando la interrupción desabilitada y si habilito la interrupción, al instante entra sin oprimir
ningún botón. Le pongo el clear_interrupts(INT_RB) antes de habilitar la interrupción RB y de igual manera se interrumpe.
La verdad es que no se qué sucede…
Les voy a poner el código de la interrupción. Espero que me puedan ayudar, tengo el datasheet y lo leo y lo analizo
constantemente para encontrar un posible error, pero no lo he encontrado. No sé si hay alguna operación que “dispare” la
interrupción, o alguna condición que impida que el clear_interrupts no funcione. Incluso, traté de controlar el asunto
directamente manipulando el TRISB y nada. Lo que me llama la atención es que, el mismo código a veces falla en un punto y
algunas veces en otro… incluso, algunas veces me ha “saltado” el sleep (antes y después del sleep pongo un delay_us(1)
para simular el NOP que solicita el datasheet del 16F628A cuando se sale del SLEEP. ¿Alguien ha tenido una experiencia
similar?, ¿Debo cambiar de versiones de CCS y/o de Proteus?, ¿Cuál versión de cada uno de estos programas es más estable?
(para mudarme por un tiempo). Si alguien tiene una recomendación al problema del botón, les estaré agradecido.
Aquí les va el fragmento de código que contiene la interrupción por cambio en los puertos RB4-RB7:
#INT_RB
void rb_isr()
{
int boton = 0;
delay_ms(1000); //mecanismo antirebote
boton = input(PIN_B5);
if((boton == 1)&&(apagado_completo == 0))
{
modo = 2;
output_high(led1);
delay_ms(1000);
output_low(led1);
delay_ms(500);
}
else if((boton == 1)&&(apagado_completo == 1))
{
modo = 2;
efectos_simples(); //poner efecto indicador de bajo voltaje
}
if(estado_sleep == 1) //si estaba en modo ligth sleep
estado_sleep = 2; //cambio a modo deep sleep.
else if(estado_sleep == 2)// si estaba en deep sleep
estado_sleep = 1; //cambio a modo ligth sleep
clear_interrupt(int_RB);
}
El ligth sleep es el sleep con la interrupcion CCP1 y RB habilitada, el deep sleep es solamente con la interrupcion RB
habilitada.
Si es necesario poner otro fragmento de codigo, solo soliciten y lo pongo, no quiero abrumar con mas de 700 lineas de codigo...