Fehler beim Verbinden von DS1307 RTC mit PIC32

Ich habe eine Schnittstelle DS1307 RTCzu PIC32MX795F512L. Ich benutze I2C1for DS1307 RTCund benutze dann, UART2um den RTC-Wert an das Terminal zu senden. Ich habe den Code geschrieben, weiß aber nicht, warum ich keine Daten erhalte.

In meinem Code verwende ich

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

Diese sind in der Datei plib.h enthalten.

Aktualisierter CODE:

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();

Ich verwende 163 ((33000000/2/100000)-2)als BRG-Wert für die I2C-Kommunikation. Ich debugge den Code und kann sehen, dass alle Werte in I2C-Registern korrekt sind, aber bei wird res = MasterReadI2C2()nichts im Register angezeigt , das den empfangenen Wert enthält, und sogar nichts wird in der Variablen I2C2RCVangezeigt . resIch habe auch eine Variable verwendet, num zu überprüfen, ob die Werte tatsächlich übertragen werden oder nicht. Also habe ich 0x00als Wert von n erhalten und laut Dokument bedeutet 0 Übertragung erfolgreich.

Ich weiß nicht, wo ich den Punkt verfehle.

Du meinst nichts wie in wirklich nichts, oder nichts wie in allen drei Bytes sind 0?
manchmal bekomme ich Müllwerte wie ? oder * oder etwas anderes. Manchmal ist das Terminal komplett leer oder manchmal bekomme ich NULL. Ich verwende Docklight
Initialisieren Sie die Zeichen vielleicht auf einen für Menschen lesbaren, aber unsinnigen Wert wie 'Z', derzeit klingt es eher so, als hätten Sie ein Problem mit Ihrem UART. (Und Sie haben bemerkt, dass Sie die Zeit nur einmal bekommen und für immer ausdrucken?) Und für diese Art von Test stellen Sie sicher, dass Ihr Terminal Hex- oder Dezimalwerte anzeigt, da ASCII-Werte sehr irreführend sein können.
Was meinst du mit "initialisiere die Zeichen für Menschen lesbar", von welchen Zeichen du sprichst? mein uart funktioniert, denn wenn ich so etwas wie helloworld sende, erhalte ich dies auf dem terminal
Sie haben die Zeichen ijk und i1 (die nicht verwendet werden) unitialisiert, die Sie in die GetTime-Funktion einfügen, um zu überprüfen, ob sich die Werte geändert haben und somit eine Zeit gelesen wird, sollten Sie sie mit einem Wert initialisieren, der sich gut auf dem ausgibt Terminal.
Wenn ich sie mit einem Wert initialisiere, werden sie denselben Wert drucken. Ich speichere tatsächlich Werte von rtc in ihnen
Sie verwenden I2C2 in Ihrem Code und erwähnen in der Beschreibung, dass sich Ihr Gerät auf I2C1 befindet. Was ist es - I2C1 oder I2C2? (Sie sind normalerweise auf verschiedenen Pins)
Ich habe vergessen, die vollständige Frage zu bearbeiten. Es ist ein alter Beitrag, jetzt benutze ich I2C2.

Antworten (3)

  1. Basierend auf dem Datenblatt:

Bit 7 von Register 0 ist das Takthaltebit (CH). Wenn dieses Bit auf 1 gesetzt ist, ist der Oszillator deaktiviert. Wenn auf 0 gelöscht, ist der Oszillator aktiviert

Stellen Sie also beim zweiten Einstellen sicher, dass Bit 7 (CH) 0 ist. UND setzen Sie Bit 7 (CH) jedes Mal auf Null, wenn der IC eingeschaltet wird.

  1. Versuchen Sie, eine kleine Verzögerung (10 ms) vor dem I2C-Start und nach dem I2C-Stopp hinzuzufügen.
  2. Versuchen Sie, jeweils ein Register einzustellen.
  3. Stellen Sie den Pull-up-Widerstand ein, versuchen Sie, ihn auf 1,5 k/1,8 k Ohm zu ändern

Ich habe diese RTC mit ATMega128 und CodeVisionAVR bearbeitet. Dieser Code funktioniert:

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);
Okay, um das richtige Timing zu erhalten, sollten wir den Oszillator immer aktivieren, was bedeutet, dass Bit 7 immer 0 ist, und in meinem Code bedeutet RTC_SetTime (0x16,0x00,0x10) 0x10 0001 0000, was bedeutet, dass ich das bereits getan habe. also, was ist das Problem.
@CZabhinav, entschuldige meinen Fehler, ich habe meine Antwort bearbeitet
was machst du in dieser Zeile i2c_write( (data_rtc[0]-48)*16 + (data_rtc[1]-48)); ??
Uhrzeit einstellen, aber data_rtc[x] im ASCII-Format, also subtrahiere ich mit 48. Dann multipliziere ich die linke Ziffer mit 16. Wir wollen zum Beispiel second = 21 setzen, dann i2c_write( ('2'-48)* 16 + ('1'-48))
Ich habe diese Art der Konvertierung in meinem Code nicht durchgeführt. Vielleicht ist das der Fehler in meinem Code. Habe ich recht?
Ich glaube nicht, Sie verwenden bereits das BCD-Format

Wenn Sie die älteren PLIB-Bibliotheken von Microchip für I2C verwenden, müssen Sie nach jeder Operation manuell abfragen, ob der Bus im Leerlauf ist. Ein Beispiel ist unten gezeigt:

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(); 

Die Funktion IdleI2C2() ist einfach die folgende:

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

Diese Leitung überprüft einfach alle Bits, die anzeigen, dass das Peripheriegerät beschäftigt ist (z. B. eine aktive Start- oder Stoppbedingung, derzeit Daten austakten usw.

Ich habe Ihren Code verwendet, um ihn mit DS1307 zu verbinden. Ich habe meinen Code aktualisiert. Kannst du mir dabei helfen.!

Wenn ich mir Ihren Code ansehe, sehe ich nichts offensichtlich Falsches, aber wenn wir uns das DS1307- Datenblatt auf Seite 13 ansehen, gibt es an, dass Sie zum Lesen von Daten von einem bestimmten Ort die Adresse schreiben, den Ort in den DS1307-Registern, Starten Sie dann eine "Wiederholte Start"-Routine, senden Sie die Adresse erneut und lesen Sie dann die Daten. Sie können einen Multibyte-Burst sequentiell oder ein einzelnes Byte einlesen und dann ein STOP senden und den Prozess an einer anderen Registerstelle erneut starten.

Ich habe kürzlich festgestellt, dass ein Versuch, zwischen einem Master- und einem Slave-PIC zu kommunizieren, erfolglos war, und ich hatte einen DS1307 herumliegen, also habe ich etwas Code gepeitscht. Zum Glück gibt es für i2c.h kein Bit-Banging mehr. Der Code ist für den PIC18F8722 geschrieben, aber Sie sollten feststellen, dass etwas Ähnliches für Sie funktioniert:

#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;
            }

Bitte seien Sie nicht zu streng mit dem Code. Ich hoffe das hilft.

In Ihrer while(1) haben Sie WriteI2C2(0x00); geschrieben, wozu das.?? und mit dieser Zeile WriteI2C2(0xD1); Sie versuchen, Daten zurückzulesen, haben aber nicht angegeben, welches Register gelesen werden soll. Auf jeden Fall vielen Dank für das Teilen Ihres Codes, ich werde das auf jeden Fall versuchen.!