# Programando en sleep mode



## Alvaritoo (Abr 26, 2007)

Hola, alguien podría pasarme un ejemplo de un programa en c, en el cuál pusiera en sleep mode a un uC,uso un atmel,pero no creo q coincida tanto,gracias.


----------



## marcosbrusa (Oct 10, 2007)

Yo puse supuestamente un pic en sleep mode es un16F876. El problema que tengo es que en ese modo me consume como 1mA. Lo cual es mucho.


----------



## merlosss (Abr 27, 2008)

Hola marcosbrusa, dices que has programado el pic para entrar en sleep mode? queria preguntarte que como haces para despertarlo y volver a la normalidad que no soy capaz de hacerlo. gracias


----------



## f_point (Abr 27, 2008)

Hola merlosss. La unica manera de re-activar un PIC del estado de Sleep es por medio de una interrucpion (interna o externa). En muchos PIC existe una gran cantidad de fuentes de interrupcion que permiten a un PIC "despertar". Una buena estrategia para salir del modo sleep puede ser el uso de un timer que genere una interrupcion periodicamente, provocando la reactivacion del PIC (Ojo: el timer debe tener entrada de reloj externa). Otra buena solucion es el uso de interrupciones externas, tal como el pin RB0/INT o la interrupcion por cambio de estado del puerto B.

Entiendo tambien que el WDT permite a un PIC despertar del estado de Sleep mediante un Reset.

Casi cualquier interrupcion generable puede ayudar, incluso la del ADC ;-)

Si no conoces mucho de interrupciones, te recomiendo que te informes del tema.

Saludos.


----------



## merlosss (Abr 28, 2008)

Es más que obvia tu respuesta, todo eso ya lo leí en el datasheet. En realidad mi pregunta no tiene otra respues. gracias d toas maneras, ya lo resolví.

Saludos.


----------



## electronical (Feb 23, 2010)

Hola, trabajo con un PSOC kit 3271 con Cyfi y no me funciona el algoritmo que hago para el sleep timer. Es este:


```
#include <m8c.h>        // part specific constants and macros
#include "PSoCAPI.h"    // PSoC API definitions for all User Modules

//-----------------------------------------------------------------------------
//  Sleep timer ISR function declaration
//-----------------------------------------------------------------------------
#pragma interrupt_handler SleepTimerISR; 

//-----------------------------------------------------------------------------
//main() function
//-----------------------------------------------------------------------------
void main(void)
{
    // Insert your main routine code here.
	
	// Turn on interrupts
	M8C_EnableGInt ; 
	
	//Turn on the Sleep Timer
	SleepTimer_Start();
	
	// Set interrupt to 1 Hz Rate. User can set this to any of 1, 8, 64 or 512 Hz. Refer User module datasheet for more details
	SleepTimer_SetInterval(SleepTimer_1_HZ); 
	LED_1_On();
	//Enable Interrupts for Sleep timer
	SleepTimer_EnableInt(); 
	SleepTimer_SetTimer(10);

	// Put the M8C to sleep
	M8C_Sleep; 
	
	//Loop continously
	while(1)
	{
		// If there are other resources running in the project, this is the right place
		// to stop the resources
		
		// Put the processor to sleep
		M8C_Sleep;
		
		// If there are other operations to perform, add code to turn on all the resources and 
		// perform the necessary operations.
	}
}

//-----------------------------------------------------------------------------
//  Sleep timer ISR function definition
//-----------------------------------------------------------------------------
void SleepTimerISR_C(void)
{//Start of Sleep Timer ISR, M8C executes this ISR after it comes out of sleep
//M8C ejecuta esta interrupción después de que salga del sueño.
	//Toggle P0[0]
	LED_1_Off();
}
```

No se duerme, el LED no se apaga. Alguien ve algún fallo? Gracias!


----------



## jjavivi (Dic 30, 2011)

Buenas, soy novato, pero mis pruebas y problemas han llegado a la conclusion que puede estar en sleep y no apagar los led, de hecho lo he comprobado, viendo los errores que generan el ADC puesto como captador y cuando duerme deja de dar errores, yo lo que hago es justo antes de llevarlo a sleep , limpio los puertos.

el problema que tengo yo es, que si antivo el WDT, la pic se duerme e inmediatamente despierta, segun el tiempo que le tenga puesto al WDT, no activado interrupcion para que sea el WDT quien saque al pic de sleep, lo saco atraves de #int RB, si alguien sabe el porque...

Saludos


----------



## Gringaso (Feb 6, 2016)

*Aclaremos algunas cosas:* el modo sleep equivale a detener el reloj principal del PIC, por ende se detiene el Program Counter (PC), lo que reduce el consumo al mínimo, esto es fácil de lograr con la función sleep.
Algunas consideraciones a tener en cuenta:
*El estado de los puertos I/O y los tris mantienen su estado durante el sleep, si tenemos un pin de salida en alto alimentando un hardware nos generará consumo extra.
*Para salir del modo sleep se puede lograr a travez de cualquier reset (MCLR, WDT, etc), o generando una interrupción.
*Nota sobre salir del sleep con una interrupción:* no todos los periféricos que generan interrupciones funcionan en el modo sleep, debemos leer el manual en donde trata el periferico específico y ver si opera en modo sleep y de que manera lo hace, esto también incluye los timer, no todos los timer funcionan en modo sleep. Otra cosa importante a tener en cuenta es que para salir del modo sleep solo necesitamos que se active determinado flag, el uso de la interrupción asociada a ese flag es opcional, por ejemplo; si activamos el flag de INT externa en RB0 y no activamos las interrupciones GLOBALES, cuando tengamos el flanco correspondiente en RB0 el pic saldra del modo sleep y cuantinuará con la secuencia de código donde se había detenido (no se genera interrupción y por lo tanto no es necesario definir la función de la interrupción externa), en cambio, si estan activadas las interrupciones GLOBALES durante el sleep, cuando tengamos el flanco correspondiente en RB0, el pic saldrá del modo sleep e inmediatamente ira al vector de interrupciones para atender a esta interrupción (en este caso debemos tener la función asociada a la interrupción programada), espero que les sirva el dato.

*No se puede despertar un pic del modo sleep por sofware*, ya que como el sofware está completamente detenido en el modo sleep no nos sirve para desperar a un pic.

PD.: Sepan disculpar los errores de tipeo y ortografía, .

Saludos


----------



## Jose1306 (Nov 28, 2016)

Hola. 

Tengo un consumo elevado de energía en mi proyecto, por el hecho de que la mayor parte del tiempo el pic (18f4550) "no hace nada" pero se encuentra ejecutando millones de ciclos de instrucción "hasta que hace algo". Ese "algo", es guardar un dato cada una hora. El motivo por el cual el pic se mantiene activo es porque tiene que funcionar el reloj ds1307 para que cada una hora, en tiempo real, le diga al pic que tiene que guardar el dato. El problema es que la bateria no me dura mas que unos dias y la necesito durante meses.

Por este motivo me incline a incrementar la eficiencia del uso de la energia de mi proyecto, no puedo seguir agregando pilas y derrochando energía. 

Estoy pensando en utilizar el modo *Sleep*, pero si lo implemento el integrado ds1307 dejaria de funcionar porque funciona en conjunto con el micro. Si es posible, para salir del modo sleep pretendo que cada una hora el ds1307 mande una señal y genere una *interrupción*. 

Es posible que el micro se encuentre en modo sleep y el ds1307 siga corriendo en tiempo real ? como hago eso ? 

Que alternativa me pueden presentar con su experiencia ?

Muchas gracias.
Saludos.


----------



## Ardogan (Nov 29, 2016)

Jose1306 dijo:


> Hola.
> 
> Tengo un consumo elevado de energía en mi proyecto, por el hecho de que la mayor parte del tiempo el pic (18f4550) "no hace nada" pero se encuentra ejecutando millones de ciclos de instrucción "hasta que hace algo". Ese "algo", es guardar un dato cada una hora. El motivo por el cual el pic se mantiene activo es porque tiene que funcionar el reloj ds1307 para que cada una hora, en tiempo real, le diga al pic que tiene que guardar el dato. El problema es que la bateria no me dura mas que unos dias y la necesito durante meses.
> 
> ...



¿Consideraste NO usar el ds1307 y conectar un cristal de 32768 Hz directamente al pic? (pines T1OSO y T1OSI, usando timer1 como temporizador con T1OSCEN=1).
Lleva más trabajo llevar un registro de fecha y hora con eso, pero si como mencionas arriba solamente precisas temporizar un intervalo de tiempo de 1 hora, entonces está más que bien. 
El timer1 desbordaría cada 2 segundos, pero se puede usar el prescaler hasta x8, con lo que podrías despertarlo hasta cada 16 segundos como máximo.

No digo de usar el watchdog porque toma señal del oscilador RC interno, que no es muy preciso (más si se quiere registrar una marca temporal junto con el dato guardado). Pero si no te preocupa que sea una hora exacta (+/-10% de error máximo para RC) podrías usar eso también. El problema es que el error en tiempo se acumula...


----------



## Jose1306 (Nov 30, 2016)

Gracias por la respuesta Ardogan.

Con este modo que planteas el Pic se encenderia cada 16 seg como maximo ? no se puede llegar a que se encienda cada 1 hora ? 

Saludos


----------



## Ardogan (Nov 30, 2016)

Jose1306 dijo:


> Gracias por la respuesta Ardogan.
> 
> Con este modo que planteas el Pic se encenderia cada 16 seg como maximo ? no se puede llegar a que se encienda cada 1 hora ?
> 
> Saludos



Estuve suponiendo que el cristal externo era de 32768 Hz, que es lo más habitual.
Veamos la hoja de datos a ver si soporta un cristal de menor frecuencia...
http://ww1.microchip.com/downloads/en/DeviceDoc/39632e.pdf

Sección 12.3 Timer1 Oscillator página 135/438


> The oscillator is a low-power circuit rated for 32 kHz crystals. It will continue to run during all power-managed modes. The


Se ve que la circuitería interna viene preparada para 32KHz nomás.

La otra posibilidad sería seguir usando el ds1307 y usar la señal de salida SQW como señal de reloj del timer1 (o de cualquier otro timer).
A ver... sí, la hoja de datos del ds1307 dice que puede dar frecuencias menores a 32 KHz (sino estamos igual).
Lo mínimo es 1Khz, con un timer de 16 bits llegamos a
2^16 /1K = 65 segundos ~ 1 minuto

No es mucho mejor tampoco... pero agregamos prescaler del timer0 que llega a valores más altos que el timer1. Lo usé antes porque es el único que puede trabajar con un oscilador de 32768Hz pero ahora no haría falta porque la señal la daría el ds1307.
Por ejemplo con x256 del timer0 (según pag. 129) llegamos a ~256 minutos ~ 4 horas.

Entonces esa es otra opción: seguir con el ds1307 pero configurarle para que en SQW ofrezca una señal de 1KHz, y eso usarlo como entrada a un timer (configurado como contador con entrada por pin externo).
A ese timer hay que configurarlo como contador con señal de cuenta por pin externo, pre-escala, y seguramente habrá que ponerlo en modo de comparación para lograr un tiempo cercano a 1 hora (y no quedarse solo con el desborde por cero).

¿Cual sería el valor de comparación?
Había dicho que señal SQW del ds1307 es 1KHz, bueno, creo que 1024 Hz en realidad.
Prescala de 256: al timer entraría una señal de 1024/256 = 4 Hz -> 0.25s de perído.
Sería 1hora = 60 min = 3600s / 0.25s = 14400 cuentas

Si te gusta de esa manera (usando el ds1307) podés implementarlo de esa forma.

Si te gustó la idea de prescindir del ds1307, también lo podrías implementar despertando el micro cada 16s, se despertaría un intervalo de tiempo breve (para incrementar un contador en la ISR) y se volvería dormir enseguida.
Digamos por exagerar que al despertar el micro está activo 1 segundo (muy exagerado), eso significaría que en 1 hora estarías despertando 3600/16s = 225 veces, tiempo activo en 1 hora = 225 segundos.
Eso mismo sería el ahorro que tendrías respecto a tu consumo actual. Bueno, no exactamente, porque el micro no consume cero corriente cuando duerme, tiene una corriente de standby, pero lo desprecio ya fuí absurdamente pesimista al considerar que al despertarse iba a demorar 1 segundo entero en ejecutar la ISR.

Así que ahora hay 2 opciones, una con más hardware, y la otra con más software y algo menos de eficiencia energética (tal vez, no consideré el consumo del ds1307 en comparación con no usarlo).


----------



## Scooter (Dic 1, 2016)

No entiendo eso de "funciona en conjunto"
¿Es que se alimenta de un pin?
El pic puede dormir y el DS generar una interrupción cada hora o cada día...
Solo consumirá el DS que es poco. El PIC, lo mínimo.


----------



## Dhu3028 (Abr 21, 2021)

Hola! Estoy diseñando un sistema digital de control basado en microcontroladores y RTC, en el cual tengo que controlar un elemento de potencia AC por medio de un relay. Tengo que implementar el modo sleep o modo de bajo consumo de energia indicadolo por medio de un parpadeo de un LED y este control debe ser por medio del RTC. Ya logre controlar el elemento de potencia, sin embargo no he logrado realizar lo del modo sleep, me podrian ayudar por favor! Estoy usando un DS1307 y pic18f4682


----------



## DJ T3 (Abr 21, 2021)

Cuál seria la parte en que trabas, y cuál el código?
Mirá acá para formatear el código;
https://www.forosdeelectronica.com/...o-subir-archivos-xenforo.157730/#post-1295349


----------



## Dhu3028 (Abr 21, 2021)

Este seria el código, ya lei la hoja de datos del pic, pero no entiendo como programar para que funcione el modo sleep por medio del pin SOUT del DS1307, por medio de un boton que cuando lo presione entre en modo sleep y cuando lo vuelva a presionar salga de ese modo. 





```
#include <proyecto2.h>

#define LCD_RS_PIN      PIN_D0
#define LCD_RW_PIN      PIN_D1
#define LCD_ENABLE_PIN  PIN_D2
#define LCD_DATA4       PIN_D3
#define LCD_DATA5       PIN_D4
#define LCD_DATA6       PIN_D5
#define LCD_DATA7       PIN_D6
 
#fuses HS,NOWDT,NOPROTECT,NOLVP                       
#use delay(clock = 20MHz)
#use fast_io(B)
#use fast_io(D)
#include <lcd.c>
#use I2C(master, I2C1, FAST = 100000)
 
int1 alarma1_status, alarma2_status;
char time[]     = "  :  :  ",
     calendar[] = "      /  /20  ",
     alarma1[]   = "A1:   :  :00", alarma2[]   = "A2:   :  :00";
  
int8  i, segundo, minuto, hora, dia, fecha, mes, ano,
      alarma1_minuto, alarma1_hora, alarma2_minuto, alarma2_hora,
      status_reg;
#INT_EXT                                         // External interrupt routine
void ext_isr(void){
  output_high(PIN_B4);
  clear_interrupt(INT_EXT);
}
void DS1307_read(){                              // Funcion de hora real y calendario
  i2c_start();                                 
  i2c_write(0xD0);                               // Direccion del ds3232
  i2c_write(0);                                  // Envia direccion de registro (segundos)
  i2c_start();                                   
  i2c_write(0xD1);                               // Inicializa info para leer
  segundo = i2c_read(1);                          // Segundos se leen en registro 0
  minuto = i2c_read(1);                          // Minutos en el 1
  hora   = i2c_read(1);                          // Hora en el 2
  dia   = i2c_read(1);                          // Dia en el 3
  fecha   = i2c_read(1);                          // Fecha en el 4
  mes  = i2c_read(1);                          // Mes en el 5
  ano   = i2c_read(0);                          // A*o en el 6
  i2c_stop();                                   
}
void alarms_read_display(){                      // Para leer en display funcion de las alarmas
  int8 control_reg, temperature_lsb;
  signed int8 temperature_msb;
  i2c_start();                                   
  i2c_write(0xD0);                               // DS3232 direccion
  i2c_write(0x08);                               // Envia direccion de registro de los minutos
  i2c_start();                                   
  i2c_write(0xD1);                               // Inicializa lectura de datos
  alarma1_minuto = i2c_read(1);                   // Lee minutos de alarma 1
  alarma1_hora   = i2c_read(1);                   // Lee horas de alarma 1
  i2c_read(1);                                   // Skip alarm1 day/date register
  control_reg = i2c_read(1);                     // Lee registro de control del ds3232
  status_reg  = i2c_read(1);                     // Lee estado del registro
  i2c_read(1);                                   // Skip aging offset register
  temperature_msb = i2c_read(1);               
  temperature_lsb = i2c_read(0);               
  i2c_stop();                                 
    // Conversion de BCD a Decimal
  alarma1_minuto = (alarma1_minuto >> 4) * 10 + (alarma1_minuto & 0x0F);
  alarma1_hora   = (alarma1_hora   >> 4) * 10 + (alarma1_hora & 0x0F);
  alarma2_minuto = (alarma2_minuto >> 4) * 10 + (alarma2_minuto & 0x0F);
  alarma2_hora   = (alarma2_hora   >> 4) * 10 + (alarma2_hora & 0x0F);
    // Fin de la conversion
  alarma1[8]     = alarma1_minuto % 10  + 48;
  alarma1[7]     = alarma1_minuto / 10  + 48;
  alarma1[5]     = alarma1_hora   % 10  + 48;
  alarma1[4]     = alarma1_hora   / 10  + 48;
  alarma2[8]     = alarma2_minuto % 10  + 48;
  alarma2[7]     = alarma2_minuto / 10  + 48;
  alarma2[5]     = alarma2_hora   % 10  + 48;
  alarma2[4]     = alarma2_hora   / 10  + 48;
  alarma1_status = bit_test(control_reg, 0);      // Read alarm1 interrupt enable bit (A1IE) from DS3231 control register
  alarma2_status = bit_test(control_reg, 1);      // Read alarm2 interrupt enable bit (A2IE) from DS3231 control register
 
  lcd_gotoxy(17, 1);                             
  printf(lcd_putc, alarma1);                     
  lcd_gotoxy(30, 1);                             
  if(alarma1_status)  lcd_putc("ON ");            // If A1IE = 1 print 'ON'
  else               lcd_putc("OFF");            // If A1IE = 0 print 'OFF'
  lcd_gotoxy(17, 2);                           
  printf(lcd_putc, alarma2);                     
  lcd_gotoxy(30, 2);                             
  if(alarma2_status)  lcd_putc("ON ");           
  else               lcd_putc("OFF");
 
}
void calendar_display(){                         //Funcion del calendario
  switch(dia){
    case 1:  strcpy(calendar, "Dom   /  /20  "); break;
    case 2:  strcpy(calendar, "Lun  /  /20  "); break;
    case 3:  strcpy(calendar, "Mar   /  /20  "); break;
    case 4:  strcpy(calendar, "Mie   /  /20  "); break;
    case 5:  strcpy(calendar, "Jue   /  /20  "); break;
    case 6:  strcpy(calendar, "Vie  /  /20  "); break;
    default: strcpy(calendar, "Sab   /  /20  "); break;
  }
  calendar[13] = ano  % 10 + 48;
  calendar[12] = ano  / 10 + 48;
  calendar[8]  = mes % 10 + 48;
  calendar[7]  = mes / 10 + 48;
  calendar[5]  = fecha  % 10 + 48;
  calendar[4]  = fecha  / 10 + 48;
  lcd_gotoxy(1, 2);                             
  printf(lcd_putc, calendar);                   
}
void DS1307_display(){
  // Convierte de BCD a Decimal
  segundo = (segundo >> 4) * 10 + (segundo & 0x0F);
  minuto = (minuto >> 4) * 10 + (minuto & 0x0F);
  hora = (hora >> 4) * 10 + (hora & 0x0F);
  fecha = (fecha >> 4) * 10 + (fecha & 0x0F);
  mes = (mes >> 4) * 10 + (mes & 0x0F);
  ano = (ano >> 4) * 10 + (ano & 0x0F);
  //Fin de conversion
  time[7]     = segundo % 10  + 48;
  time[6]     = segundo / 10  + 48;
  time[4]     = minuto % 10  + 48;
  time[3]     = minuto / 10  + 48;
  time[1]     = hora   % 10  + 48;
  time[0]     = hora   / 10  + 48;
  calendar_display();                            // Llama a la funcion de calendario en display
  lcd_gotoxy(1, 1);                             
  printf(lcd_putc, time);                        // Display hora
}
void blink(){
  int8 j = 0;
  while(j < 10 && (input(PIN_B1) || i >= 5) && input(PIN_B2) && (input(PIN_B3) || i < 5)){
    j++;
    delay_ms(25);
  }
}
int8 edit(parameter, x, y){
  while(!input(PIN_B1) || !input(PIN_B3));       // espera hasta que boton RB0 se suelte
  while(TRUE){
    while(!input(PIN_B2)){                       //Si boton RB2 esta presionado
      parameter++;
      if(((i == 0) || (i == 5)) && parameter > 23)    // Horas > 23 ==> horas = 0
        parameter = 0;
      if(((i == 1) || (i == 6)) && parameter > 59)    // Minutos > 59 ==> minutos = 0
        parameter = 0;
      if(i == 2 && parameter > 31)               // Si fecha > 31 ==> fecha = 1
        parameter = 1;
      if(i == 3 && parameter > 12)               // Mes > 12 ==> mes = 1
        parameter = 1;
      if(i == 4 && parameter > 99)               // A*o > 99 ==> a*o = 0
        parameter = 0;
      if(i == 7 && parameter > 1)                // Para alarmas ON o OFF (1: alarma ON, 0: alarma OFF)
        parameter = 0;
      lcd_gotoxy(x, y);
      if(i == 7){                                // Para alarmas ON & OFF
        if(parameter == 1)  lcd_putc("ON ");
        else                lcd_putc("OFF");
      }
      else
        printf(lcd_putc,"%02u", parameter);      // Display parametro
      if(i >= 5){
        DS1307_read();                         
        DS1307_display();                        // Display DS3231 hora y calendario
      }
      delay_ms(200);                             
    }
    lcd_gotoxy(x, y);                           
    lcd_putc("  ");                              // Imprime 2 espacios
    if(i == 7) lcd_putc(" ");                    // Espacion para ON y OFF
    blink();                                     // Llama a la funcion blink
    lcd_gotoxy(x, y);                            //
    if(i == 7){                                  // Para larmas ON & OFF
      if(parameter == 1)  lcd_putc("ON ");
      else                lcd_putc("OFF");
    }
    else
      printf(lcd_putc,"%02u", parameter);       
    blink();
    if(i >= 5){
      DS1307_read();
      DS1307_display();}
    if((!input(PIN_B1) && i < 5) || (!input(PIN_B3) && i >= 5)){
      i++;                                       // Incrementa 'i' para el siguiente parametro
      return parameter;                          // Devuelve el valor del parametro y termina
    }
  }
}
void main(){
  output_b(0);
  set_tris_b(0x0F);                              // Configura RB0 ~ 3 como pin de entrada
  set_tris_d(0);                                 // Pines del puerto D como salida
  port_b_pullups(TRUE);                          // Enable PORTB internal pull-ups
  enable_interrupts(GLOBAL);                     // Interrupciones globales
  enable_interrupts(INT_EXT_H2L);                // Enable external interrupt with edge from high to low
  lcd_init();                                   
  lcd_putc('\f');                                // Limpia LCD
  while(TRUE){
    if(!input(PIN_B1)){                          // Si boton RB1 esta presionado
      i = 0;
      hora   = edit(hora, 1, 1);
      minuto = edit(minuto, 4, 1);
      while(!input(PIN_B1));                     // Espera hasta que boton rb0 se suelte
      while(TRUE){
        while(!input(PIN_B2)){                   // Si boton rb2 esta presionado
          dia++;                                 // Incrementa el dia
          if(dia > 7) dia = 1;
          calendar_display();                   
          lcd_gotoxy(1, 2);                   
          printf(lcd_putc, calendar);           
          delay_ms(200);
        }
        lcd_gotoxy(1, 2);                       
        lcd_putc("   ");                         
        blink();
        lcd_gotoxy(1, 2);                       
        printf(lcd_putc, calendar);             
        blink();                                 
        if(!input(PIN_B1))                       // Si boton rb1 esta presionado
          break;
      }
      fecha = edit(fecha, 5, 2);                   
      mes = edit(mes, 8, 2);                 
      ano = edit(ano, 13, 2);                 
      // Convierte de decimal a BCD
      minuto = ((minuto / 10) << 4) + (minuto % 10);
      hora = ((hora / 10) << 4) + (hora % 10);
      fecha = ((fecha / 10) << 4) + (fecha % 10);
      mes = ((fecha / 10) << 4) + (mes % 10);
      ano = ((ano / 10) << 4) + (ano % 10);
      // Fin de la conversion
      // Escribe info de tiempo y calendario al DS3232 RTC
      i2c_start();                               
      i2c_write(0xD0);                           // Direccion del RTC
      i2c_write(0);                              //
      i2c_write(0);                              // Reset segundos
      i2c_write(minuto);                         // Escribe valor de minutos al DS3231
      i2c_write(hora);                           //  " hora
      i2c_write(dia);                            //  " dia
      i2c_write(fecha);                          // " fecha
      i2c_write(mes);                            // " mes
      i2c_write(ano);                           // " a*o
      i2c_stop();                               
      delay_ms(200);                           
    }
    if(!input(PIN_B3)){                          // Si boton RB3 esta presionado
      while(!input(PIN_B3));                     // Espera hasta que se suelte ese boton
      i = 5;
      alarma1_hora   = edit(alarma1_hora, 21, 1);
      alarma1_minuto = edit(alarma1_minuto, 24, 1);
      alarma1_status = edit(alarma1_status, 30, 1);
   i = 5;
      alarma2_hora   = edit(alarma2_hora, 21, 2);
      alarma2_minuto = edit(alarma2_minuto, 24, 2);
      alarma2_status = edit(alarma2_status, 30, 2);
      alarma1_minuto = ((alarma1_minuto / 10) << 4) + (alarma1_minuto % 10);
      alarma1_hora   = ((alarma1_hora / 10) << 4) + (alarma1_hora % 10);
      alarma2_minuto = ((alarma2_minuto / 10) << 4) + (alarma2_minuto % 10);
      alarma2_hora   = ((alarma2_hora / 10) << 4) + (alarma2_hora % 10);
      // Escribe info del las alarmas en DS3232
      i2c_start();                               
      i2c_write(0xD0);                           // Direccion del RTC
      i2c_write(7);                              // Envia direccion del registro (segundos)
      i2c_write(0);                              // Escribo 0 a alarma1 segundos
      i2c_write(alarma1_minuto);                  // Escribir alarma1 minutos valor al DS3232
      i2c_write(alarma1_hora);                   
      i2c_write(0x80);                           // Alarma1 cuando horas, minutos y segundos son iguales
      i2c_write(alarma2_minuto);                 
      i2c_write(alarma2_hora);                   
      i2c_write(0x80);                           
      i2c_write(4 | alarma1_status | (alarma2_status << 1));      // Write data to DS3231 control register (enable interrupt when alarm)
      i2c_write(0);                              // Clear alarm flag bits
      i2c_stop();                               
      delay_ms(200);                             
    }
    if(!input(PIN_B2) && input(PIN_B4)){         // Cuando se presiona el boton B2 con la alarma, se restablece y apaga la alarma
      output_low(PIN_B4);                        // Se apaga el indicador de la alarma
      i2c_start();                               
      i2c_write(0xD0);                         
      i2c_write(0x0E);                           // Envia direccion de registro (registro de control)
      //Escribe los datos en el registro de control (apaga alarma y mantiene la otra como esta)
      i2c_write(4 | (!bit_test(status_reg, 0) & alarma1_status) | ((!bit_test(status_reg, 1) & alarma2_status) << 1));
      i2c_write(0);                              // Clear alarm flag bits
      i2c_stop();                               
    }
    DS1307_read();                               
    alarms_read_display();                     
    DS1307_display();                           
    delay_ms(50);                               
  }
}
```


----------



## D@rkbytes (Abr 21, 2021)

Dhu3028 dijo:


> por medio de un botón que cuando lo presione entre en modo sleep y cuando lo vuelva a presionar salga de ese modo.


Busca el archivo "EX_WAKUP.C" en la carpeta de ejemplos de PIC C Compiler.
Ahí está el código que necesitas.


----------



## Dhu3028 (Abr 21, 2021)

Disculpa y eso donde lo encuentro? 
Gracias!!


----------



## Dr. Zoidberg (Abr 21, 2021)

D@rkbytes dijo:


> en la carpeta de ejemplos de PIC C Compiler.


----------



## Dhu3028 (Abr 22, 2021)

Estuve intentando mas sin embargo no me funciona, porque tengo que hacerlo con un led desde el pin SOUT del DS1307, como lo explica Ardogan, con la senal cuadrada que sale del DS, utilizando el boton para entrar y salir del modo, pero no me funciona


----------



## D@rkbytes (Abr 22, 2021)

Yo no entiendo nada de lo que planteas.
El pin SOUT del DS1307 cambia de estado cada segundo y suele utilizarse una interrupción externa para realizar la lectura.
El microcontrolador sale del modo de bajo consumo por interrupciones, así que una externa también lo despertaría.
Por lo tanto, usar un botón para activar y desactivar el modo de bajo consumo cuando el DS1307 lo estará despertando cada segundo, no se me hace algo muy útil.


----------



## sebsjata (Abr 22, 2021)

Creo que lo que intentas hacer no se puede, el pic solo sale del modo sleep por interrupcion, reset o WDT, asi que solo puedes despertar el pic mandando una señal a dicho pin que configuraste en el registro del vector de interrupcion.

edit.
@D@rkbytes se me adelantó.


----------



## Scooter (Abr 23, 2021)

Que yo sepa ningún micro se programa en sleep Mode. Entran en sleep Mode y dejan de funcionar, ibernan y se despiertan básicamente por una interrupción.
Asi que formalmente no se programa EN sleep Mode, se programa la entrada en ese modo y se despierta por un aviso externo.

Y si no es así es que estoy equivocado.


----------

