Wake up from sleep mode

Hola, buenas a todos del foro

Estoy haciendo una placa para TFG, y tengo una duda:
pongo en modo sleep, y luego quiero despertarla con WDT, es posible cuando PIN_A0=1, que me hace un restart_WDT? o otra posible forma? Es que según mi codigo, me parece que una vez que esten en modo SLEEP, ya no ejecuta las instrucciones, con lo cual no ejecutara el WDT.
Cualquier ayuda me iria bien, gracias.

Código:
#include <16f628a.h>

#fuses NOWDT   //Watch dog timer no esta activado desde principio

#fuses NOPROTECT,NOPUT,LP
#fuses MCLR,NOBROWNOUT
#fuses INTRC_IO             // Internal RC Osc, no CLKOUT

#use delay(INTERNAL=48000,RESTART_WDT)     // Ojo a INTERNAL, determina la duracion

#include <tones.c>


 }
void main(){  
setup_oscillator( OSC_48kHZ ); //esta determina la frecuencia
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2 );//usamos un reloj interno, division 2
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   
  SET_TIMER0(236);//CARGA 220 =>0.012s

TRISB=0b0000001;//declara que RB0 sea entrada, las otras de RB sea salida
PORTB=0x00;
enable_interrupts(INT_TIMER0);
enable_interrupts(INT_EXT_H2L); // turn on external interrupt H->L
enable_interrupts(GLOBAL);


while(true){

if (input(PIN_A0)==1)
  {
   RESTART_WDT();  //activa el WATCH DOG TIMER, para despertar el micro. wake up from sleep
  
  enable_interrupts(INT_EXT_H2L); //no puedo poner esto aqui ya que no funcionara, porque esta en modo sleep, estas instrucciones no se ejecutara.

  if(vibracion==1)
  {
      setup_oscillator( OSC_4MHZ );
      generate_tone(2000,2000);
      setup_oscillator( OSC_48kHZ );
  }}


 if (input(PIN_A0)==0){

 output_low(PIN_A1);
 delay_ms(100);
 
 setup_WDT(WDT_18MS);
 disable_interrupts(INT_EXT_H2L);
 SLEEP();


}

}
}
 
No, no, no. Así no se despierta el microcontrolador.
Si ya está en modo "Sleep" no puede obedecer instrucciones. (Se detiene la ejecución del programa principal)
El microcontrolador únicamente puede despertar del modo "Sleep" si ocurre una interrupción.

Usa la interrupción externa por RB0.
Con eso ya no es necesario hacer un reset del Watch-Dog Timer.
 
Gracias por contestar, pero la cosa es que RB0/ INT ya esta ocupado, y esta interrupcion actua omo un contador, lo desactivo para que no despertara el micro, asi que solo me queda el Reset de MCLR o WDT, y estoy buscando si hay alguna forma de usar el WDT para despertarlo.
 
Tienes varias interrupciones con las que se puede salir del modo "Sleep"
Gracias por contestar, pero la cosa es que RB0/ INT ya está ocupado, y esta interrupción actúa como un contador, lo desactivo para que no despertara el micro, así que sólo me queda el Reset de MCLR o WDT
RA4 es la entrada de reloj del Timer 0 (T0CKI) y comúnmente se usa para contar pulsos.
Y también tienes las del puerto B (RB4<>RB7)

Internamente también se puede despertar con la interrupción por desborde de los Timers, por ejemplo; el Timer 0
y estoy buscando si hay alguna forma de usar el WDT para despertarlo.
Claro que se puede despertar con el Watch-Dog Timer, es para eso.
 
Última edición:
Se que las de puerto B pueden actuar como interrupciones, pero son de señal TTL, y estoy utilizando solo los de ST, ya que mi fuente de alimentación sería una pila lipo de 3.7V, asi que los de puerto B no creo que van a funcionar excepto RB0/INT, ya que cuando es una interrupcion externa es de ST.
Y el timer0 ya lo estoy utilizando como un temporizador interno, se puede volver a usar?
el cogido completo es asi:
Código:
#include <16f628a.h>

#fuses NOWDT   //Watch dog timer no esta activado desde principio

#fuses NOPROTECT,NOPUT,LP
#fuses MCLR,NOBROWNOUT
#fuses INTRC_IO             // Internal RC Osc, no CLKOUT

#use delay(INTERNAL=48000,RESTART_WDT)     // Ojo a INTERNAL, determina la duracion

#include <tones.c>


#byte TRISB=0x86 //indicar si es entrada o salida
#byte PORTB=0x06  //indica si esta en nivel alto o bajo 

//int16 i=0;
int1 vibracion=0;
int16 contadorT0=0;
int16 contadorVIB=0; //int8=>256 cuentas, cuando contadorVIB llega 10<x<30, sigue contando, entonces llegara 256 algun momento, y vuelve a contar desde 0.
int16 tres=1000;

#int_ext          //Interrupcion a la pata numero 6, RB0/INT, usaremos el INT para la interrupcion externa, ya que es de salida ST
void RB0(){
contadorVIB++;}

#int_timer0
Void timer0(){

SET_TIMER0(236);//CARGA 220 =>Xms
contadorT0++;
//output_toggle(PIN_A3);

if (contadorT0==158)   // 158X5.06ms == 799.48ms( este valor aun tendremos que cambiar segun la situacion
                        // he comprobado con una carga de 1000, el cual tiene que entrar en la interrupcion despues de dejar el pulsador de reset 5 segundos.
{     
      if((contadorVIB>10) && (contadorVIB<30))//hay que discutir en los valores
      {
      vibracion=1;       
      }
      else
      {
      vibracion=0;
      }
contadorVIB=0;  
contadorT0=0;//resetea el contador
}
 
 }
void main(){  
setup_oscillator( OSC_48kHZ ); //esta determina la frecuencia
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2 );//usamos un reloj interno, division 2
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   
  SET_TIMER0(236);//CARGA 220 =>0.012s

TRISB=0b0000001;//declara que RB0 sea entrada, las otras de RB sea salida
PORTB=0x00;
enable_interrupts(INT_TIMER0);
enable_interrupts(INT_EXT_H2L); // turn on external interrupt H->L
enable_interrupts(GLOBAL);


while(true){

if (input(PIN_A0)==1)
  {
   RESTART_WDT();  //activa el WATCH DOG TIMER, para despertar el micro. wake up from sleep
  
  enable_interrupts(INT_EXT_H2L); //no puedo poner esto aqui ya que no funcionara, porque esta en modo sleep, estas instrucciones no se ejecutara.

  if(vibracion==1)
  {
      setup_oscillator( OSC_4MHZ );
      generate_tone(2000,2000);
      setup_oscillator( OSC_48kHZ );
  }}


 if (input(PIN_A0)==0){

 output_low(PIN_A1);
 delay_ms(100);
 
 setup_WDT(WDT_18MS);
 disable_interrupts(INT_EXT_H2L);
 SLEEP();


}

}
}
 
Sé que las de puerto B pueden actuar como interrupciones, pero son de señal TTL, y estoy utilizando solo los de ST, ya que mi fuente de alimentación sería una pila lipo de 3.7V, así que los de puerto B no creo que van a funcionar excepto RB0/INT, ya que cuando es una interrupción externa es de ST.
3.7 V ya es considerado como un 1 lógico a nivel TTL. De hecho desde 3.0 V. en cada pin de entrada.
Así que sí las puedes usar.
Y el Timer 0 ya lo estoy utilizando como un temporizador interno.
¿Se puede volver a usar?
Si, pero hay que estructurar el código para dividir tareas y es más complicado.
Recuerda que tienes otros timers aparte del Timer 0. El Timer 1 y el Timer 2.
 
Hola, tengo una duda sobre como despertar el PIC con la interrupcion de RDA.

Tengo el SIM900A(flasheado) y PIC16F628A.

Queria preguntar si es possible despertar el PIC con INT_RDA.
He leido el datasheet y dice que si esta en SLAVE MODE, entonces se puede recibir datos en SLEEP.
En este caso debería conectar un cristal externo a la RB2, y la otra pata del cristal donde lo conecto?
Y como se setea el SLAVE MODE?
 
Buenas. Más abajo veréis un ejemplo que he hecho de como parar SLEEP mediante una interrupción externa y que encienda un LED durante unos segundos.

El problema es que por más cambios y pruebas que he hecho, no funciona.
Cuando se le pone un valor muy bajo a SLEEP, por ejemplo 2 o 3, si funciona, pero está claro que es porque al ser tan bajo, cuando pulso en RB0 lo pillo en ese intervalo.

Esto es una prueba, ya que la intención real, es que al pulsar en RB0 se encienda y apague el PIC, o sea, entre en SLEEP o salga de él.
He mirado tanto aquí como en otros foros, y aunque he visto bastantes cosas, no me han servido, conste que las he estudiado detenidamente.

Por cierto, que el perro guardián le da igual que este suelto o amarrado.
Muchas gracias de antemano y disculpen mi ignorancia.
PHP:
@ DEVICE pic16f628A, WDT_OFF           ' Watchdog Timer desconectado.-
A VAR BYTE
LED1 VAR PORTA.0
INTCON = %10010000

ON INTERRUPT GOTO LED 
DORMIR: 
SLEEP 100
GOTO DORMIR
DISABLE
LED:
FOR A = 1 TO 50
HIGH LED1
PAUSE A
NEXT A
INTCON = %10010000
A = 0
LOW LED1
RESUME 
ENABLE 
END
 
No entendí muy bien qué es lo que quieres hacer.
Tomé tu código como referencia y le hice algunas modificaciones, que según creo es lo que quieres hacer.
Lo adjunto con simulación para que puedas ver el funcionamiento.
También comenté la partes importantes del programa para su mejor comprensión.

Nota: Usé PBPX y la palabra de configuración es diferente, pero también la dejé comentada para PBP.
 

Adjuntos

  • 16F628A Sleep & Wake-up.rar
    23.9 KB · Visitas: 18
Disculpen las molestias, pero como explique, busque aqui y en otros foros, y lo que encontraba
no me servia de guia. A lo mejor es por que no supe lo que habia que poner para que me llevara
a la respuesta adecuada.
Muchas gracias por su archivo, voy a estudiarlo, un saludo.
 
Atrás
Arriba