Error al conectar DS1307 RTC con PIC32

4

Estoy interconectando DS1307 RTC con PIC32MX795F512L . Estoy usando I2C1 para DS1307 RTC y luego uso UART2 para enviar el valor RTC al terminal. He escrito el código pero no sé por qué no obtengo datos.

En mi código estoy usando

OpenI2C2 to open the i2c channel.
StartI2C2() to start the communication
StopI2C2() to stop the communication
MasterWriteI2C() to write the data
MasterReadI2C() to read the data

Estos se incluyen en el archivo plib.h

CÓDIGO actualizado:

OpenI2C2(I2C_EN, 163); // I2C channel Configuration

StartI2C2();            
IdleI2C2();             
n = MasterWriteI2C2(0xD0);  //device address
IdleI2C2();              
MasterWriteI2C2(0x07);      
IdleI2C2();
MasterWriteI2C2(0x00);
IdleI2C2();
StopI2C2();

StartI2C2();            
IdleI2C2();             
MasterWriteI2C2(0xD0);  
IdleI2C2(); 
MasterWriteI2C2(0x01);
IdleI2C2(); 
MasterWriteI2C2(0b00010011);
IdleI2C2(); 
StopI2C2();


StartI2C2();
IdleI2C2();
MasterWriteI2C2(0xD0);
IdleI2C2();
MasterWriteI2C2(0x01);
IdleI2C2();
StopI2C2();

StartI2C2();
IdleI2C2();
MasterWriteI2C2(0xD1);
IdleI2C2();
**res = MasterReadI2C2();**
IdleI2C2();
NotAckI2C2();
IdleI2C2();
StopI2C2();

Estoy utilizando 163 ((33000000/2/100000)-2) como valor BRG para la comunicación I2C. Estoy depurando el código y puedo ver que todos los valores en los registros I2C son correctos, pero en res = MasterReadI2C2() , no aparece nada en el registro I2C2RCV , que contiene el valor recibido e incluso nada aparece en la variable res . También utilicé una variable n para verificar si los valores realmente están transmitiendo o no. Así que recibí 0x00 como el valor de n y de acuerdo con el documento, 0 significa transmisión exitosa.

No sé dónde me estoy perdiendo el punto.

    
pregunta Aircraft

3 respuestas

1
  1. Basado en la hoja de datos:
  

El bit 7 del registro 0 es el bit de detención del reloj (CH). Cuando este bit se establece   a 1, el oscilador está deshabilitado. Cuando se borra a 0, el oscilador   está habilitado

Entonces, cuando establece el segundo, asegúrese de que el bit 7 (CH) es 0. Y establezca el bit 7 (CH) en cero cada vez que se encienda el IC.

  1. Intente agregar un pequeño retraso (10ms) antes del inicio de I2C y después de la detención de I2C.
  2. Intente establecer un registro a la vez.
  3. Ajuste la resistencia de pull-up, intente cambiar a 1.5k / 1.8k Ohm

Trabajé este RTC con ATMega128 y CodeVisionAVR Este código funciona:

rtc_init(0,1,0); // output pin for debugging

delay_ms(10);
i2c_start();
i2c_write(0xD0);
i2c_write(0x00);
i2c_write( (data_rtc[10]-48)*16 + (data_rtc[11]-48));      //second
i2c_stop();

delay_ms(10);
i2c_start();
i2c_write(0xD0);
i2c_write(0x01);
i2c_write( (data_rtc[8]-48)*16 + (data_rtc[9]-48));        // minutes
i2c_stop();

delay_ms(10);
i2c_start();
i2c_write(0xD0);
i2c_write(0x02);
i2c_write( (data_rtc[6]-48)*16 + (data_rtc[7]-48));        // hour
i2c_stop();

delay_ms(10);   
i2c_start();
i2c_write(0xD0);
i2c_write(0x04);
i2c_write( (data_rtc[4]-48)*16 + (data_rtc[5]-48));        // day
i2c_stop(); 

delay_ms(10);   
i2c_start();
i2c_write(0xD0);
i2c_write(0x05);
i2c_write( (data_rtc[2]-48)*16 + (data_rtc[3]-48));        // month
i2c_stop();

delay_ms(10);   
i2c_start();
i2c_write(0xD0);
i2c_write(0x06);
i2c_write( (data_rtc[0]-48)*16 + (data_rtc[1]-48));        // year
i2c_stop();

delay_ms(10); 
rtc_init(0,1,0);
    
respondido por el Oka
1

Al utilizar las bibliotecas heredadas de Microchip PLIB para I2C, debe realizar una encuesta manual para que el bus esté inactivo después de cada operación. A continuación se muestra un ejemplo:

StartI2C2(); // Send the Start Bit
IdleI2C2(); // Wait to complete
MasterWriteI2C2(0xE0); // Send slave address with write bit
IdleI2C2(); // Wait to complete
MasterWriteI2C2(addr);
IdleI2C2(); // Wait to complete
StopI2C2(); // Send Stop bit
IdleI2C2();
StartI2C2(); // Send the Start Bit
IdleI2C2(); // Wait to complete
MasterWriteI2C2(0xE1); // Send slave address with read bit
IdleI2C2(); // Wait to complete
val = MasterReadI2C2();
IdleI2C2();
NotAckI2C2(); // Master  Aknodledge End of transfer
StopI2C2(); // Send Stop bit
IdleI2C2(); 

La función IdleI2C2 () es simplemente la siguiente:

while(I2C2CONbits.SEN || I2C2CONbits.PEN || I2C2CONbits.RSEN || I2C2CONbits.RCEN || I2C2CONbits.ACKEN || I2C2STATbits.TRSTAT);

Esta línea simplemente está comprobando cualquier bit que signifique que el periférico está ocupado (por ejemplo, una condición de inicio o parada activa, datos actualmente sincronizados, etc.)     

respondido por el justing
0

Mirando tu código, no veo nada que esté muy mal, pero si miramos el DS1307 hoja de datos , página 13, especifica que para hacer una lectura de datos desde una ubicación específica, escriba la dirección, la ubicación en los registros del DS1307, luego inicie una rutina de "Inicio repetido", envíe la dirección nuevamente y luego lea los datos. Puede leer una ráfaga multibyte, secuencialmente o un solo byte y luego enviar una PARADA y comenzar el proceso nuevamente en una ubicación de registro diferente.

Recientemente encontré un intento de comunicación entre un PIC maestro y un esclavo que no tuvo éxito, y tenía un DS1307 por ahí, así que hice un código. Afortunadamente, para i2c.h, no más golpes de bits. El código está escrito para el PIC18F8722, pero debería encontrar que algo similar funcionará para usted:

#include <pic18f8722.h>
            #include <i2c.h>
            #include <spi.h>
            #include <delays.h>
            #include "LCD.h"
            #include "SerComm.h"

            #pragma config OSC = HSPLL
            #pragma config WDT = OFF
            #pragma config FCMEN = OFF

            #define newline 0x0A
            #define carriageReturn 0x0D

            void initialize(void);
            unsigned char x;
            unsigned char seconds = 0x00;
            unsigned char minutes = 0x36;
            unsigned char hours = 0x48;
            unsigned char days = 0x03;
            unsigned char date = 0x17;
            unsigned char month = 0x08;
            unsigned char year = 0x15;
            unsigned char hyear, lyear, hmonth, lmonth, hdate, ldate, hdays, ldays, hhours, lhours, hminutes, lminutes, hseconds, lseconds;
            unsigned char time[7];

            void main(void)
            {
                lcdInit();
                initialize();
                CloseI2C2();

                OpenI2C2(MASTER, SLEW_OFF);

                IdleI2C2();
                StartI2C2();
                WriteI2C2(0xD0);
                WriteI2C2(0x00);
                WriteI2C2(seconds);
                WriteI2C2(minutes);
                WriteI2C2(hours);
                WriteI2C2(days);
                WriteI2C2(date);
                WriteI2C2(month);
                WriteI2C2(year);
                StopI2C2();

                while(1)
                {
                IdleI2C2();
                StartI2C2();
                WriteI2C2(0xD0);
                WriteI2C2(0x00);
                RestartI2C2();
                WriteI2C2(0xD1);
                for(x = 0; x < 6; x++)
                {
                   time[x] = ReadI2C2();
                   AckI2C2();
                }
                time[6] = ReadI2C2();
                NotAckI2C2();
                StopI2C2();

                hyear = ((time[6] & 0xF0) >> 4) + 0x30;
                lyear = (time[6] & 0x0F) + 0x30;
                hmonth = ((time[5] & 0xF0) >> 4) + 0x30;
                lmonth = (time[5] & 0x0F) + 0x30;
                hdate = ((time[4] & 0xF0) >> 4) + 0x30;
                ldate = (time[4] & 0x0F) + 0x30;
                hdays = ((time[3] & 0xF0) >> 4) + 0x30;
                ldays = (time[3] & 0x0F) + 0x30;
                hhours = ((time[2] & 0x10) >> 4) + 0x30;
                lhours = (time[2] & 0x0F) + 0x30;
                hminutes = ((time[1] & 0xF0) >> 4) + 0x30;
                lminutes = (time[1] & 0x0F) + 0x30;
                hseconds = ((time[0] & 0xF0) >> 4) + 0x30;
                lseconds = (time[0] & 0x0F) + 0x30;



                lcdGoTo(0x00);
                lcdWriteString("Time: ");
                lcdChar(hhours);
                lcdChar(lhours);
                lcdChar(':');
                lcdChar(hminutes);
                lcdChar(lminutes);
                lcdChar(':');
                lcdChar(hseconds);
                lcdChar(lseconds);
                SerTx(hhours);
                SerTx(lhours);
                SerTx(':');
                SerTx(hminutes);
                SerTx(lminutes);
                SerTx(':');
                SerTx(hseconds);
                SerTx(lseconds);
                SerTx(newline);
                SerTx(carriageReturn);
                }

            }

            void initialize(void)
            {
                TRISAbits.RA2=0; // Chip select pin for the SPI port expander;

                TRISDbits.RD5 = 1;  //Set the ports of the I2C bus;
                TRISDbits.RD6 = 0;

                SSP2STAT = 0x80;    //Disable the slew rate control;
                SSP2CON1 = 0x28;    //Enable the Serial Port, Set the mode to: Master Mode, clock = Fosc/(4*(SSP1ADD + 1);
                SSP2CON2 = 0x00;    //No bits to set here;

                SSP2ADD = 0x59;     //Set to 100 kHz at 40 MHz clock;

                TXSTA1 = 0x24;      //Set serial communication to High Speed, TX enabled, 8 bit mode;
                RCSTA1 = 0x90;      //Enable the serial port, Enable the Receiver;
                BAUDCON1 = 0x00;    //;

                SPBRG1 = 42;        //57600 kBaud;
            }

Por favor, no seas demasiado severo con el código. Espero que esto ayude.

    
respondido por el Alex Baum

Lea otras preguntas en las etiquetas