¿Dónde guardar el programa DS1307 para obtener un valor en tiempo real?

0

Estoy integrando DS1307 en mi proyecto y usando PIC32MX795F512L MCU. De alguna manera, he logrado hacer la comunicación I2C en ella y obtener los valores en tiempo real. Estoy mostrando el valor en tiempo real en el terminal usando UART. Así que el tiempo se está actualizando automáticamente. Pero cuando apagué el dispositivo y lo encendí de nuevo, el DS1307 no me dio el valor en tiempo real, sino que comienza el tiempo que establecí en el código.

En el código que establezco, 14:27:12 , así que después de apagarlo y volverlo a encender, el tiempo comenzó desde 14:27:12 , lo que creo que no debería ocurrir. Tengo la batería unida con DS1307 .

Así que pensé que para obtener un valor en tiempo real, podría tener que guardar el código en otro lugar en el microcontrolador.

¿Necesitas ayuda con esto?

CÓDIGO:

int main(void)
{
  OpenUART1( UART_EN | UART_NO_PAR_8BIT | UART_1STOPBIT  , UART_RX_ENABLE | UART_TX_ENABLE, (FPB/16/BAUDRATE)-1 );


  I2C2BRG = 0xA3;     //I2C Baudrate
  I2CEnable(EEPROM_I2C_BUS, TRUE);    //I2C module On
  if( !StartTransfer(FALSE) )
  {
    while(1);
  }
  TransmitOneByte(0xD0);  //slave address
  TransmitOneByte(0x00); //register pointer pointing to first register 
  TransmitOneByte(0x00); //seconds  value
  TransmitOneByte(0x56); //min value
  TransmitOneByte(0x12); //hr value
  StopTransfer(); //I2C Stop
  if(!Success)
  {
     while(1);
  }
  while(1)
  {
    RTC_read();
    **//sending time to UART**
    putsUART1("Time: ");
    putsUART1(value6);
    putsUART1(value5);
    putsUART1(":");
    putsUART1(value4);
    putsUART1(value3);
    putsUART1(":");
    putsUART1(value2);
    putsUART1(value1);
    putsUART1("\n");
   }
}

**///******** FUNCTION TO READ FROM I2C ****************//**
void RTC_read()
 {

  StartTransfer(FALSE); //I2C Start
  TransmitOneByte(0xD0); //I2C slave address
  TransmitOneByte(0x00);
  StopTransfer(); //I2C Stop

 IdleI2C2(); //i2C Stop

 StartTransfer(TRUE);    //I2C Restart
 TransmitOneByte(0xD1);  //Slave address to read
 **//Reading from I2C slave**
 if(I2CReceiverEnable(EEPROM_I2C_BUS, TRUE) == I2C_RECEIVE_OVERFLOW)
 {
  putsUART1("Error: I2C Receive Overflow1\n");
 }
 else
 {
    **//read sec**
   while(!I2CReceivedDataIsAvailable(EEPROM_I2C_BUS));
   Nop();
   sec = I2CGetByte(EEPROM_I2C_BUS); 
   AckI2C2();
   while (!I2CAcknowledgeHasCompleted(I2C2));  

   **//read min**
   I2CReceiverEnable(EEPROM_I2C_BUS, TRUE);
   while(!I2CReceivedDataIsAvailable(EEPROM_I2C_BUS)); 
   Nop();
   min = I2CGetByte(EEPROM_I2C_BUS);  
   AckI2C2();
   while (!I2CAcknowledgeHasCompleted(I2C2)); 

   **//read hr**
   I2CReceiverEnable(EEPROM_I2C_BUS, TRUE);
   while(!I2CReceivedDataIsAvailable(EEPROM_I2C_BUS)); 
   Nop();
   hr = I2CGetByte(EEPROM_I2C_BUS);  
   NotAckI2C2();
   while (!I2CAcknowledgeHasCompleted(I2C2)); 

 }

 StopTransfer(); //I2C Stop
 if(!Success)
 {
    while(1);
 }

    **//converting sec to ASCII**
    x1 = sec & 0x0F;
    p1 = x1 | 0x30;
    y = sec & 0xF0;
    y = y >> 4;
    p2 = y | 0x30;

    sprintf(value1,"%c",p1);
    sprintf(value2,"%c",p2);

    **///converting min to ASCII**
    x2 = min & 0x0F;
    p3 = x2 | 0x30;
    y2 = min & 0xF0;
    y2 = y2 >> 4;
    p4 = y2 | 0x30;
    sprintf(value3,"%c",p3);
    sprintf(value4,"%c",p4);

    **////converting hr to ASCII**
    x3 = hr & 0x0F;
    p5 = x3 | 0x30;
    y3 = hr & 0xF0;
    y3 = y3 >> 4;
    p6 = y3 | 0x30;
    sprintf(value5,"%c",p5);
    sprintf(value6,"%c",p6);

}

EDIT

Las siguientes son las funciones utilizadas en el código:

StartTransfer (reinicio de BOOL): -

//Description:This routine starts (or restarts) a transfer to/from the EEPROM, waiting (in a blocking loop) until the start (or re-start) condition has completed.

 //Parameters:restart - If FALSE, send a "Start" condition
         //         - If TRUE, send a "Restart" condition

 //Returns: TRUE    - If successful
  //         FALSE   - If a collision occured during Start signaling


BOOL StartTransfer( BOOL restart )
{
I2C_STATUS  status;

// Send the Start (or Restart) signal
if(restart)
{
    I2CRepeatStart(EEPROM_I2C_BUS);
}
else
{
    // Wait for the bus to be idle, then start the transfer
    while( !I2CBusIsIdle(EEPROM_I2C_BUS) );

    if(I2CStart(EEPROM_I2C_BUS) != I2C_SUCCESS)
    {
        DBPRINTF("Error: Bus collision during transfer Start\n");
        return FALSE;
    }
}

// Wait for the signal to complete
do
{
    status = I2CGetStatus(EEPROM_I2C_BUS);

} while ( !(status & I2C_START) );

return TRUE;
}

BOOL TransmitOneByte (datos UINT8): -

 //Description:This transmits one byte to the EEPROM, and reports errors for any bus collisions.
//Returns:TRUE    - Data was sent successfully
          FALSE   - A bus collision occured

BOOL TransmitOneByte( UINT8 data )
{
// Wait for the transmitter to be ready
while(!I2CTransmitterIsReady(EEPROM_I2C_BUS));

// Transmit the byte
if(I2CSendByte(EEPROM_I2C_BUS, data) == I2C_MASTER_BUS_COLLISION)
{
    DBPRINTF("Error: I2C Master Bus Collision\n");
    return FALSE;
}

// Wait for the transmission to finish
while(!I2CTransmissionHasCompleted(EEPROM_I2C_BUS));

return TRUE;
}

void StopTransfer (void): -

 //Description:This routine Stops a transfer to/from the EEPROM, waiting (in //a blocking loop) until the Stop condition has completed.

void StopTransfer( void )
{
I2C_STATUS  status;

// Send the Stop signal
I2CStop(EEPROM_I2C_BUS);

// Wait for the signal to complete
do
{
    status = I2CGetStatus(EEPROM_I2C_BUS);

} while ( !(status & I2C_STOP) );
}
    
pregunta user007

2 respuestas

2

Solo tienes que configurar el tiempo una vez y luego solo leerlo.

Por lo tanto, la próxima vez no incluya la función de configuración de la hora en su código, ya que anteriormente ha establecido la hora. Los registros de DS1307 contendrán la hora actualizada y usted tendrá que leerlo.

Digamos que tienes las siguientes funciones:

RTC_init     : to initialise I2C channel
RTC_setTime  : to set time
RTC_readTime : to read time

Luego, al principio, incluye las tres funciones en tu código. Algo como abajo:

main()
{
  RTC_init();
  RTC_setTime();

  while(1)
  {
    RTC_readTime();
  }
}

y luego la segunda vez, comente la función RTC_setTime() y vuelva a programar su dispositivo. Como abajo

main()
{
  RTC_init();
  //RTC_setTime();

  while(1)
  {
    RTC_readTime();
  }
}

Ahora, si no le dio energía a su dispositivo, la batería ayudará a DS1307 a mantener los valores actualizados de time & Fecha a sus registros y seguirá haciendo esto.

    
respondido por el Aircraft
4

A simple vista, parece que la única forma en que el código NO ACTUALIZA el DS1307 es si StartTransfer(FALSE) detecta que el DS1307 ya se ha inicializado .

¿Hace eso? (Para entender el programa, deberíamos ver el código y una explicación de cómo funciona).

De lo contrario, el código parece que siempre intenta establecer el mismo tiempo en el DS1307.

Copie el programa y cámbielo para que no establezca la hora en el DS1307 y vuelva a ejecutarlo.

Piense en el problema como dos casos diferentes (de uso):

  1. Establezca la hora DS1307
  2. Usa el tiempo DS1307

para simplificar, escriba dos programas, uno que solo establece la hora y el otro resuelve el problema (el otro caso).

Editar:
Dice que la aplicación no tiene una interfaz de usuario y normalmente almacenará datos en una tarjeta SD.

Así que las opciones son:

  1. Agregue un botón adicional (o incluso un pin que pueda cortarse a tierra de manera segura) que se usará para activar el programa para configurar el temporizador Podría usar una variante de los métodos 2 o 3, a continuación

  2. Escriba la hora en un archivo con un nombre específico en la tarjeta SD usando una PC (de algún tipo). Dependiendo de la biblioteca de su tarjeta SD, incluso puede obtener los datos y el tiempo de la marca de tiempo del archivo. Si el archivo existe cuando el sistema está REAJUSTADO, el sistema debe leer la información de fecha y hora, configurar el DS1307 y luego eliminar el archivo para evitar que se reinicie accidentalmente el reloj nuevamente.

  3. Use su terminal 'debug', conectado a través de UART, para configurar el DS1307 reloj. Escriba un poco de código para detectar si el terminal está conectado (I Supongamos que normalmente no lo es), y si el terminal está conectado, lea la información del tiempo.

También existe la opción de mantener el 'programa de ajuste del reloj' por separado, ejecutarlo cuando el sistema esté listo para instalarse y reemplazarlo con el código de producción. (No tan ordenado)

    
respondido por el gbulmer

Lea otras preguntas en las etiquetas