Forum: Mikrocontroller und Digitale Elektronik DS 1307 über I2C lesen


von Benny (Gast)


Lesenswert?

Hallo Leute

Bin im Rahmen meiner Technikerarbeit dabei einen Datenlogger zu
realisieren.
Habe den AT89C51ED2 und folgende I2C Bausteine :

DS1307   real-time-clock
M24C64   EEPROM
ADS7828  ADU

und versuche schon seid 4 Wochen die Uhrzeit aus meinem DS1307
auszulesen.
Ich bekomme es geregellt alle Bausteine anzusprechen (Bekomme von jedem
Baustein ein Acknoledge) und auch das schreiben stellt kein problem
dar.
Aber ich bekomme es nicht geregelt aus dem EEProm oder dem DS1307
Daten auszulesen.
Ich kenne die Datenblätter bereits sogut wie auswendig und bin auch der
Meinung alles verstanden zu haben.
Aber sobald ich Daten auslesen will bekomme ich nur Müll.

Es hängt genau an der Stelle an der ich eine neue Start-Bedingung
herstelle die slave-adresse + read auf den Bus lege.Dann bekomme ich
noch ein Acknoledge dieses bestätige ich und takte dann die Daten raus

Ich hoffe das ich nur einen kleinen Denkfehler mache, hat jemand eine
Idee was ich falsch machen könnte ?

Ich versuche das ganze noch zu Fuß über ein spezielles Board mit dem
ich die high oder low Zustände über zwei Schalter auf SDA und SCL legen
kann.

Da über den Atmel und meine I2c routinen auch noch nichts geht.


Hiiiilllllllllllllffffffffffffee

Ihr seid meine letzte Hoffnung

Ciao Benny

von Jochen (Gast)


Lesenswert?

Hallo Leidensgenosse ;-),

also erst mal ich habe eben mal meine DS1307 Uhr rausgekrammt und nach
etwas Gefummel tut die nu auch.

Das erste wo vielleicht der Fehler liegen könnte ist das, dass
raustakten mit der Hand, wie Du es im Moment machst, für den I2C zu
langsamm ist. Ich weiß zwar das er bis max 400kHz kann aber wie es nach
unten aussieht weiß ich leider nicht(also ob es sowas wie ne
Mindestgeschwindigkeit gibt)

Andere Möglichkeit wäre noch das Du die HW vielleicht falsch
verschaltet hast.

Grüßle Jochen

von KlaRa (Gast)


Lesenswert?

Hallo,
wenn Du eine andere real-time-clock nehmen kannst, so besuch mal
http://www.cc2net.de. Dort gibt es viele I2C - Lösungen.
Als real-time-clock nimmt man da den PCF8583. I2C Treiber stehen unter

http://www.cc2net.de/Module/module.html.
Vielleicht hilft es weiter.

Gruss Klaus.

von Benny (Gast)


Lesenswert?

Erst mal vielen Danke für eure Hilfe !!!

Also das mit der mindest Geschwindigkeit hatte ich schon abgeklärt.
Da gibt es keine Probleme das ist den Bausteinen völlig Wurst.

Und den Baustein zu wechseln bringt mir auch nichts da ich den schon im
Pflichtenheft stehen habe und es leider mit dem eeprom auch nicht klappt
(das aller gleiche Problem) deshalb glaube ich das ich einen
Grundsätzlichen Fehler mache.

Beim ADU bei dem ich keine Speicheradressen ansprechen muss klappt´s
übrigens.

Beschaltung wurde auch schon von mehreren unbeteiligten überprüft, die
haben auch keinen Fehler gefunden.

Wir machen die Technikerarbeit zu zweit und haben daher die Bauteile
doppelt bestellt die müssten also auch ok sein.

Könnte vieleicht einer ein C-Programm posten das bei Ihm funktioniert
hat ?

Ganz simpel ohne Ihrgendwelche funktionen wie z.B. I2C (da wir die
funktionen vieleicht nicht haben)
alles per hand SDA =1 SCL=1 "schreiben in eine Speicherzeile und wider
auslesen mit Start-Bedingung usw" auslesen je einfacher desto besser.
Hoffe das wir wenns funzt dann unseren Fehler aus diesem Programm
rauslesen können

Ciao Benny

von Jochen (Gast)


Lesenswert?

Huhu Benny,

Also ganz so Low-Level hab ich keinen Code. Kann Dir aber hier mal
Posten was ich mit I2C Funktionen verwende. Die I2C funktionen machen
dann aber auf Low-Level Ebene auch nur das was im Datenblatt steht.

unsigned int ret;
//Senden der I2C Startbedienung mit der Addresse des EEPROMs
//chip_adr = 0xA0 für EEPROM 0xD0 Für RTC
//mem_adr  = Die Adresse die gelesen werden soll
ret = i2c_start(chip_adr+WRITE);
if ( !ret )
{
    //Senden der zu lesenden Speicherstelle
    i2c_write(mem_adr);
    //Senden der I2C Wiederholten-Startbedienung mit der Addresse des
      EEPROMs
    ret = i2c_rep_start(chip_adr+READ);
    if ( !ret )
    {
      //Einlesen der Daten
      back = i2c_readNak();
    }
    else
    {
      //Fehler Routine wenn Chip nicht erreicht werden kann
    }
}
else
{
    //Fehler Routine wenn Chip nicht erreicht werden kann
}

Also wenn Du mit der obigen Code z.B. die Speicherstelle 0x0000 des
EEPROMS lesen willst musst du als chip_adr 0XA0 und als mem_adr 0x00
übergeben.

Für die Speicherstelle 0x027F wäre es analog dazu chip_adr = 0xA4 und
mem_adr= 0x7F.

Hoffe das hilft Dir vielleicht weiter.


Grüßle Jochen

P.S. auf meiner HP http://www.rurlaender.net/ Habe ich eine Library zum
auslesen bzw. schreiben eines I2C EEPROMS liegen. Ist allerdings auf
Basis des i2cmasters und für ein atmega.

von Benny (Gast)


Lesenswert?

Hallo Leute

Die Library funktioniert leider nicht mit unserem compiler (Ride
Version 6.10.15) bringt meldung das das nur mit einem ATM GCC compiler
funzt

Mit diesen Funktionen arbeiten wir bis jetzt RTC.h






************************************************************************ 
***********/
/*
           */
/* Funktionen zur Ansteuerung des DS1307 RealTimeClocks
           */
/* ----------------------------------------------------
           */
/*
           */
               */
/* Version 1.0
*/
/*
           */
/*********************************************************************** 
************/

//********************** Definitionen ***************
//#define adr_lies           0xD1            // Adresse ueber die auf
den DS1307 geschr. wird
//#define adr_schreib         0xD0           // Adresse ueber die auf
den DS1307 geschr. wird


char  system_time_ss;
char  system_time_mm;
char  system_time_hh;
char  system_time_dayofweek;
char  system_time_day;
char  system_time_month;
char  system_time_year;


//****************************** Funktionen
****************************************

/*********************************************************************** 
************/
/* Fkt.   rtc_bcd_to_hex: wandelt BCE zu HEX Zahl um
           */
/*
           */
/*********************************************************************** 
************/
char rtc_bcd_to_hex(char v)
{
  char n;

  n=v;
  n=n & 0xF0;
  n=n/16;
  v =v & 0x0F;
  n=n*10+v;
  return(n);
}

/*********************************************************************** 
************/
/* Fkt.   rtc_hex_to_bcd: wandelt HEX zu BCD Zahl um
           */
/*
           */
/*********************************************************************** 
************/
char rtc_hex_to_bcd(char v)
{
  char n;

  n=v;
  n=n/10;
  n=n*16;
  v =v % 10;
  n=n+v;
  return(n);
}

/*********************************************************************** 
************/
/* Fkt.   write_rtc_ram: Schreibt ein Byte ueber I2C auf den DS1307
           */
/*
           */
/*********************************************************************** 
************/
char write_rtc_ram(char ad,char  d)
{
  d=rtc_hex_to_bcd(d);
  starti2c();
  ausgabei2c(adr_schreib);
  ausgabei2c(ad);
  ausgabei2c(d);
  stoppi2c();
  //delay_ms(11);
  _nop_();
}

/*********************************************************************** 
************/
/* Fkt.   read_rtc_ram: Liest ein Byte ueber I2C aus dem DS1307
           */
/*
           */
/*********************************************************************** 
************/
char read_rtc_ram(char ad)
{
  char d;

  starti2c();
  ausgabei2c(adr_schreib);
  ausgabei2c(ad);
  starti2c();
  ausgabei2c(adr_lies);
  d= einleseni2c(1);
  stoppi2c();
  d=rtc_bcd_to_hex(d);
  return(d);
}

/*********************************************************************** 
************/
/* Fkt.   gettime: Liest Sekunden, Minuten und Stunden ein
           */
/*
           */
/*********************************************************************** 
************/
void gettime()
{
  system_time_ss        = read_rtc_ram(0);
  _nop_();//5
  system_time_mm        = read_rtc_ram(1);
  _nop_();//5
  system_time_hh        = read_rtc_ram(2);
  _nop_();//5
  system_time_dayofweek = read_rtc_ram(3);
  _nop_();//5
  system_time_day       = read_rtc_ram(4);
  _nop_();//5
  system_time_month     = read_rtc_ram(5);
  _nop_();//5
  system_time_year      = read_rtc_ram(6);

}

/*********************************************************************** 
************/
/* Fkt.   init_uhr: Initialisiert den DS1307
           */
/*        Achtung nach einem Stromausfall wird init_uhr() aufgerufen,
da der DS1307*/
/*        Batterie gepuffer ist darf nicht alles geresettet werden!!
           */
/*********************************************************************** 
************/
void init_uhr()
{
   system_time_mm = read_rtc_ram(0);            // alten Minutenwert
vor dem ueberschreiben Lesen
   write_rtc_ram(0x00,00);                      // CH=0
   write_rtc_ram(0,system_time_mm);             // alten Minutenwert
wieder speichern
   system_time_hh = read_rtc_ram(2);            // alten Stundenwert
vor dem ueberschreiben Lesen
   write_rtc_ram(0x02,00);                      // auf 24h Mode
stellen
   write_rtc_ram(2,system_time_hh);             // alten Stundenwert
wieder speichern
   write_rtc_ram(0x07,00);                      //OSC ON
}

/*********************************************************************** 
************/
/* Fkt.   set-Funktionen: um alle Parameter zu schreiben.
           */
/*
           */
/*********************************************************************** 
************/
void setsecond(char d)   {write_rtc_ram(0,d);}
void setminute(char d)   {write_rtc_ram(1,d);}
void sethour(char d)     {write_rtc_ram(2,d);}
void setdayofweek(char d){write_rtc_ram(3,d);}
void setday(char d)      {write_rtc_ram(4,d);}
void setmonth(char d)    {write_rtc_ram(5,d);}
void setyear(char d)     {write_rtc_ram(6,d);}
void sqw(char d)         {write_rtc_ram(7,d);}








und mit der header Datei I2C.h


#include <c51rd2.h>        /* Registerdefinitionen  */
#include <intrins.h>        /*  für Rotationsfunktion */
#include <stdio.h>              /*Standart Ein/Ausgabe Funktionen*/


/****** verwendete Adressen und Kontrollbyte für den AD- und
DA-Umsetzter ******************/

unsigned char  adr_lies    = 0xD1;  /*  10010001  ->  11010001 */
unsigned char  adr_schreib      = 0xD0;  /* 10010000  ->  11010000 */

/****** verwendete I2C-Leitungen
**********************************************************/

sbit  daten  =  P3^5;    /*  0xB5  P3.5 = SDA, i2c-Datenleitung */
sbit  clock  =  P3^4;    /*  0xB4  P3.4 = SCL, i2c-Taktleitung  */

/*********************************************************************** 
*******************/


sbit  acc7 = ACC^7;    /*  für Aus- und Eingabe eines Bits des Akkus */

/*********************************************************************** 
*******************

 * I2C-Bus-Funktionen initi2c, starti2c, stoppi2c, ausgabei2c,
einleseni2c auch für andere
 * I2C-Bus-ICs verwendbar

************************************************************************ 
******************

/****** Startbedingung I2C-Bus
************************************************************/

void starti2c (void)
  {
  daten = 1;
  clock = 1;
  daten = 0;
  clock = 0;
  }

/****** Stoppbedingung I2C-Bus
************************************************************/

void stoppi2c (void)
  {
  clock = 1;
  daten = 1;
  }

/*********************************************************************** 
*******************
 * Byte ausgeben an I2C-Bus , Rückgabewert = Acknoledgebit = 1 wenn
erfolgreich

************************************************************************ 
******************/


bit ausgabei2c (unsigned char byte)
  {
  unsigned char z;        /* Zähler */
  bit ack;              /* Acknoledge-Bit */
  ACC = byte;            /*  Rotationsregister Akku */
  for (z = 8; z != 0; z --)  /*  Zähler: serielle Ausgabe von 8 Bit */
    {
    daten = acc7;        /*  Bit7 des Akku ausgeben */
    nop  ();
    clock = 1;          /*  Daten sind gültig */
    ACC = crol (ACC,1);  /* links rotieren, Funktion von intrins.h */
    clock = 0;          /*  Datenausabe beendet  */
    }
  daten = 1;          /*  Leitung freigeben für Acknoledge-Bit */
  nop  ();
  clock = 1;          /*  Slave kann bestätigen */
  nop ();          /* warten */
  ack = daten;        /* Acknoledge-Bit lesen  */
  clock = 0;          /* Slave soll Ackn-Ausgabe beenden  */
  return (ack);        /* Acknoledge-Bit ist Rückgabewert der Funktion 
*/

  }


/*********************************************************************** 
*******************
 * Byte einlesen vom I2C-Bus. Bei Ack=1 wird Acknoledgebit gesendet,
sonst nicht

************************************************************************ 
******************/


unsigned char einleseni2c (bit ack)
  {
  unsigned char z,byte;
  daten = 1;                /*  Leitung freigeben (high) für Daten  */
  for (z = 8; z != 0; z --)      /*  Zähler: serielles Einlesen von 8 
Bit
*/
    {
    clock = 1;              /*  Daten sind gültig */
      nop  ();
    acc7 = daten;            /*  Datenbit in den Akku */
    ACC = crol (ACC,1);      /* links rotieren, Funktion von intrins.h 
*/

    clock = 0;              /*  Daten lesen beendet  */
    }
  byte = ACC;                /* Eingelesenes Byte */
  if (ack == 1)    {daten = 0;}  /* Acknowledge-Bit senden  */
          else  {daten = 1;}  /*  kein Acknowledge-Bit */
    nop  ();
  clock = 1;                /*  Ackn. gültig */
  clock = 0;                /* Ackn. beendet */
    nop  ();
  daten = 0;                /* Leitung nicht mehr frei für Daten  */
  return (byte);              /*  eingelesenes Byte = Rückgabewert  */
   }

/*********************************************************************** 
*******************
 /*                 _nop_()

/*********************************************************************** 
*******************/

  void nop (void)
 {

    int i;

    for(i=1;i=30000;i++)
    {
    }

 }




Wenn Ihr es in den compiler kopiert müsste es lesbar sein

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.