RTC_DS1307 + PIC18F458 mostrando la hora y la fecha como ceros

0

Estoy intentando que el hardware del PIC RTCDS1307 + funcione para mostrar los datos y la hora adecuados. Pero el problema es que, muestra la hora y la fecha como 00:00:00 y 00/00/2000 como se muestra en el complemento a continuación.

SupongoquelosregistrosRTCnoseconfigurancorrectamenteoquenoseproducendatostxyrxcuandosetratadelhardware.Reviséloscálculosdelcódigo/tasadebitsytodopareceestarbien.Noentiendoporquénofunciona.¿HayalgomaloconlainicializacióndeI2Comienfoque?Cualquierayudaconrespectoaestoseríaapreciada.Aquíestáelcódigo:

#include<P18F458.h>#include<xc.h>#include<htc.h>#include"LCD.h"

#define RTC_ADDRW 0xD0
#define RTC_ADDRR 0xD1
#define _XTAL_FREQ 20000000

unsigned char sec,min,hour,date,month,year;
unsigned char data[7] = {0x45,0x59,0x71,0x04,0x05,0x10,0x06};
int i;

void I2C_idle()
{
    while((SSPCON2 & 0x1F)|(SSPSTATbits.R_W));
}
void I2C_start()
{
    I2C_idle();
    SSPCON2bits.SEN = 1; //Set start enable bit
    while(SSPCON2bits.SEN); //Wait until cleared by hardware
}


void I2C_stop()
{
    SSPCON2bits.PEN = 1; //Set stop enable bit
    while(SSPCON2bits.PEN); //Wait until cleared by hardware
    I2C_idle();
}

void I2C_restart()
{
    SSPCON2bits.RSEN = 1; //Initiates Repeated Start Condition on SDA   and SCL pins 
    while(SSPCON2bits.RSEN==1); //Wait until cleared by hardware
    I2C_idle();
}

void RTC_Write(unsigned data,unsigned char addr)
{
    I2C_start();
    I2C_idle();
    SSPBUF = RTC_ADDRW; //Slave address +Write Command
    I2C_idle();
    SSPBUF = addr; //Write the location
    I2C_idle();
    SSPBUF = data; //Write the data
    I2C_idle();
    I2C_stop(); //Enable stop bit
    I2C_idle();
}
void I2C_Init()
{
    TRISCbits.TRISC3 = 1; // SCL direction input
    TRISCbits.TRISC4 = 1; //SDA direction input
    SSPCON1bits.SSPM3 = 1; //SSPM0:SSPM3 = 0001 (Master Mode
    SSPCON1bits.SSPM2 = 0;
    SSPCON1bits.SSPM1 = 0;
    SSPCON1bits.SSPM0 = 0;
    SSPSTATbits.SMP = 1;
    SSPADD = 0x31; /*For Fosc 20MHz, Required Bit Rate = 100 KHz
                                                       SSPADD = ((20MHz/4)/100 KHz - 1)= 0x31*/
    PIR1bits.SSPIF = 0;
    SSPCON2 = 0;
    SSPCON1bits.SSPEN = 1;
    RTC_Write(0,0x00);
 }

unsigned char RTC_Read(unsigned char addr)
{
    unsigned char x;
    I2C_start(); //Enable repeated start condition
    SSPBUF = RTC_ADDRW;
    I2C_idle();
    SSPBUF = addr;
    I2C_idle();
    I2C_restart();
    SSPBUF = RTC_ADDRR;
    I2C_restart();
    SSPCON2bits.RCEN = 1; //Enable to recieve data
    I2C_idle();
    SSPCON2bits.ACKDT = 1; //Acknowledge the operation (Send NACK)
    SSPCON2bits.ACKEN = 1; //Acknowledge sequence on SCL and SDA pins
    I2C_stop();
    x = SSPBUF; //store the recieved value in a var
    return(x);

}
unsigned char BCD2Upperch(unsigned char bcd)
{
    unsigned char temp;
    temp = bcd >> 4;
    temp = temp | 0x30;
    return (temp);

}

unsigned char BCD2Lowerch(unsigned char bcd)
{
    unsigned char temp;
    temp = bcd & 0x0F;
    temp = temp | 0x30;
    return (temp);
}


void main()
{
    TRISCbits.TRISC0 = 0;
    TRISCbits.TRISC1 = 0;
    TRISCbits.TRISC2 = 0;
    TRISD = 0;
    char16x2LCDInit();
    __delay_ms(20);
    I2C_Init();
    for(i=0 ; i<7 ; i++)
        RTC_Write(data[i],i);
    __delay_ms(20);


    while(1)
    {
        sec = RTC_Read(0x00);
        min = RTC_Read(0x01);
        hour = RTC_Read(0x02);
        date = RTC_Read(0x04);
        month = RTC_Read(0x05);
        year = RTC_Read(0x06);

        arraydisp("Time: ",0x80);
        Write_Data(BCD2Upperch(hour));
        Write_Data(BCD2Lowerch(hour));
        Write_Data(':');
        Write_Data(BCD2Upperch(min));
        Write_Data(BCD2Lowerch(min));
        Write_Data(':');
        Write_Data(BCD2Upperch(sec));
        Write_Data(BCD2Lowerch(sec));
        arraydisp("Date: ",0xC0);
        Write_Data(BCD2Upperch(date));
        Write_Data(BCD2Lowerch(date));
        Write_Data('/');
        Write_Data(BCD2Upperch(month));
        Write_Data(BCD2Lowerch(month));
        Write_Data('/');
        LCDWriteInt(20,2);
        Write_Data(BCD2Upperch(year));
        Write_Data(BCD2Lowerch(year));


    }

Gracias a todos por adelantado.

Saludos cordiales ~ VD

    
pregunta PsychedGuy

2 respuestas

1

Su función RTC_Read debe comenzar con un inicio de I2C, no un reinicio de I2C.

El I2C_restart solo pertenece al punto donde cambias del modo de escritura (enviando la dirección de registro) al modo de lectura (lectura de datos).

Para responder a sus otras preguntas:

  • debe comprobar el bit de ACK después de enviar la dirección de lectura / escritura de RTC (y esperar a I2C_Idle) justo al comienzo de sus funciones RTC_read / RTC_write. No puede esperar hasta que se complete la transacción I2C antes de verificar ACK.
  • Si el RTC falla en ACK, debe finalizar la transacción I2C (enviando un I2C_stop) y luego intentarlo nuevamente y / o mostrar un mensaje de error. Una vez que haya funcionado, lo más probable es que un error ACK indique un error de hardware de algún tipo ...

También, como anishkumar ha notado en su respuesta, ha confundido su dirección & parámetros de datos en su llamada a la función RTC_write.

    
respondido por el brhans
1

Estás intercambiando i2c addr y datos mientras los pasas a RTC_Write () . Simplemente marque la función RTC_Write () y el código después de I2C_Init () que entenderá.

// para (i = 0; i < 7; i ++)
RTC_Write (0,0x45); // cuando i = 0

En la función RTC_Write ()
RTC_Write (datos sin firmar, sin signo) - {
  // ...
  SSPBUF = addr; // Escribe la ubicación
  // ...
  SSPBUF = datos; // escribe los datos
  // ...
}

    
respondido por el anishkumar

Lea otras preguntas en las etiquetas