Autor Tema: Interrupcion RB y boton  (Leído 3052 veces)

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

Desconectado rafaelrg06

  • PIC12
  • **
  • Mensajes: 54
Interrupcion RB y boton
« en: 29 de Enero de 2018, 22:42:55 »

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...

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Interrupcion RB y boton
« Respuesta #1 en: 29 de Enero de 2018, 23:18:38 »
Trata de leer el puerto b completo (junto con el clear_interrupt), usa un input_b() aunque no sea necesario y descarta ese valor. Recorda que para usarlo sin ningun problema deberias tener al menos el #USE FAST_IO(B) y los set_tris_b

A pesar de que CCS deberia hacerlo, la interrupcion por cambio exige que se lea el puerto para que se pueda borrar el flag de interrupcion.

Por otro lado tenes que recordar que al presionar y soltar el boton son si o si 2 entradas a la interrupcion, asi que creo que tu codigo de "estado_sleep" no creo que funcione como queres. Ya que presionas ( tenes que tenerlo presionado 1 segundo ) termina la interrupcion, y luego cuando sueltes va a entrar nuevamente.

Citar
la interrupción RB estando la interrupción desabilitada y si habilito la interrupción, al instante entra sin oprimir

Siempre antes de habilitarlas hay que limpiar los flags.

Citar
   delay_ms(1000);   //mecanismo antirebote

Tu antirebote, hace que nunca se atienda las demas interrupciones, por lo que al terminar esta si tenias activo la del CCP1 va a entrar directamente. Demas esta decir que con ese delay, deberian haber pasado VAAARIAS interrupciones del CCP1.
« Última modificación: 29 de Enero de 2018, 23:21:27 por KILLERJC »

Desconectado rafaelrg06

  • PIC12
  • **
  • Mensajes: 54
Re:Interrupcion RB y boton
« Respuesta #2 en: 17 de Febrero de 2018, 11:17:57 »
Hola amigos:
Ya resolví el asunto. Yo necesitaba usar un solo botón, y lo conecté a la entrada del comparador analógico, y me funcionó mucho mejor, así que lo dejé de esa manera.
Sin embargo, voy a implementar cada sugerencia que me han dado para mejorar la forma de controlar el pic y que pueda leer mejor los botones en el futuro, mil gracias amigos.
Saludos