Externen Eeprom ohne Bibliothek auslesen

Hallo Leute,

Ich versuche schon seit Tagen einen externen Eeprom (24LC64) mit Hilfe des Datenblattes und OHNE Bibliothek zu beschreiben und anschließend auszulesen. Dazu müssen die im Datenblatt angegebenen Bitfolgen geschickt werden. Wenn ich mich an das Datenblatt halte schaffe ich es auch den Eeprom richtig zu beschreiben (mit Bibliotheks-Programm ausgelesen und es kamen die richtigen Ergebnisse), aber manuelles auslesen will bei mir einfach nicht funktionieren, obwohl die Funktionsweise ja ähnlich dem Beschreiben des Eeproms ist.

Hat das jemand von euch schon mal erfolgreich versucht und kann mir Tipps dazu geben?

Gruß,
Fruit_ice

Nicht probiert, aber es hilft wenn wir wissen wie Dein Sketch aussieht.
Gute Idee, findest Du nicht?

Normalerweise schickt man bei I2C die Device Adresse mit beginTransmission(), dann die Speicher Adresse mit write(). Danach endTransmission(). Dann fordert man die Daten mit requestFrom() an und macht dann entsprechend oft read()

Du kannst ja nachschauen wie es in der Lib gemacht ist

Also: schreiben funktioniert ja indem man eine Startcondition sendet, die Bausteinadresse, die Speicheradresse, den Datenwert und dann die Stopcondition. Dazwischen immer ein Clockimpuls für Acknowledge

Startsequenz:

void i2c_start(uint8_t value){
  //Startbit - Change data from High to Low while clock is High
  int i = 0;
  int maske = 1;
  //Startcondition
  digitalWrite(dataPin, 1);
  digitalWrite(clockPin, 1);
  digitalWrite(dataPin, 0);
//Bausteinadresse
  for(i = 0; i < 8; i++){
    maske = B10000000 >> i;
    digitalWrite(clockPin, 0);
    if((value & maske) == maske){
      digitalWrite(dataPin, 1);
    }
    else{
      digitalWrite(dataPin, 0);
    }
    digitalWrite(clockPin, 1);
  }
//Acknowledge
  digitalWrite(clockPin, 0);
  digitalWrite(clockPin, 1);
}

Stopsequenz

void i2c_stop(){
  digitalWrite(clockPin,0);
  digitalWrite(dataPin, 0);
  digitalWrite(clockPin, 1);
  digitalWrite(dataPin, 1);
}

Sendesequenz

void i2c_send(uint8_t F_value){
  uint8_t maske = 1;
  uint8_t i = 0;
  for(i = 0; i < 8; i++){
    digitalWrite(clockPin, 0);
    maske = B10000000 >> i;
    //Write databit while clock is low
    if((F_value & maske) == maske){ digitalWrite(dataPin, 1);}
    else{digitalWrite(dataPin, 0);}
    //change clock to high and keep data stable
    digitalWrite(clockPin, 1);
  }
  //Acknowledge
  digitalWrite(clockPin, 0);
  digitalWrite(clockPin, 1);
}

Schreiben sieht bei mir dann so aus:

i2c_start(B10100000);
  i2c_send(F_adr >> 8);
  i2c_send(F_adr & 0xFF);
  i2c_send(F_value);
  i2c_stop();
  delay(5);

Das funktioniert auch.

Auslesen soll laut Datenblatt jetzt ähnlich funktionieren:
Startsequenz, Bausteinadresse, Speicheradresse, Lesesequenz, Stop.

  i2c_start(B10100000);
  i2c_send(F_adr >> 8);
  i2c_send(F_adr & 0xFF);

  i2c_start(B10100001);
  pinMode(dataPin, INPUT);

  for(j=0;j<8;j++){
    digitalWrite(clockPin,0);
    digitalWrite(clockPin,1);
    Serial.println(digitalRead(dataPin));
  }
  digitalWrite(clockPin,0);
  digitalWrite(clockPin,1);
  i2c_stop();

Zum Einlesen der Bit's ändere ich meinen Datenpin auf Input und lese bei jedem Clockimpuls den Zustand. Er gibt mir aber immer nur einsen aus.

Warum willst Du es nicht so wie Serenifly beschreibt machen?
Du kannst nicht dei HW-Schnittstelle benutzn und dann direckt die Pins auslesen bzw setzen.
Grüße Uwe

Um zu verstehen was da passiert möchte ich weitestgehend ohne Bibliotheken arbeiten. Mit der Bibliothek den Eeprom zu beschreiben und zu lesen ist ja nicht weiter schwierig.

Wie wird das Einlesen denn in der Bibliothek realisiert? Irgendwie muss das ja gehen :-/

Dann mußt Du die i2C Schnittstelle verstehen.

http://www.elektronik-magazin.de/page/der-i2c-bus-was-ist-das-21
und genauer:
http://www.timmermann.org/ralph/index.htm?http://www.ralph.timmermann.org/elektronik/i2c.htm

Damit Du aber Daten auf dem Bus senden kannst mußt Du die HW-Steuerung aber deaktivieren. Du kannst aber auch die Schnittstelle in software auf 2 anderen Pins emulieren.

Grüße Uwe

Hallo,

danke für die Links. Sie sind eine gute Zusammenfassung von dem was man im Internet so findet. Helfen tut mir das allerdings nicht. Ich habe ja in meinem Code die verschiedenen Sequenzen umgesetzt und damit erfolgreich den Eeprom beschrieben. Auslesen arbeitet mit den gleichen Sequenzen, nur das der Datenpin jetzt als Input statt als Output genutzt wird. Kann ich den im laufenden Programm (also nachdem der Lesebefehl gesendet wurde) als Input deklarieren ohne dass kryptische Sachen passieren?

Gruß,
Fruit_ice

hi,

warum schaust Du nicht einfach in die bibliotheken rein, was die machen? ist ja alles klartext...

gruß stefan

Hey,

das war auch mein erster Ansatz, aber das ist so komplex geschrieben ich steig da nicht wirklich hinter. Hast du da mal reingeguckt?

Sogar ohne twi.c anzusehen sieht man aber ein paar Sachen

Ich habe oben z.B. hingeschrieben, dass nach dem Senden der Speicher-Adresse ein endTransmission() kommt. Das macht dann:

uint8_t TwoWire::endTransmission(void)
{
  return endTransmission(true);
}

uint8_t TwoWire::endTransmission(uint8_t sendStop)
{
  int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1, sendStop);

  ...
}

Da kommt also eine Stop Condition nach dem Senden der Speicher Adresse wenn ich das richtig verstanden habe

digitalRead/Write() ist übrigens ziemlich lahm. Wenn es mal läuft wird auch auf direkte Port Adressierung oder die digitalWriteFast Lib umsteigen

Laut Datenblatt und den oben geposteten Links zur Beschreibung von i2c darf zwischendurch keine Stop-Condition gesendet werden. Die Schnelligkeit von digitalWrite dürfte auch kein Problem sein, da sich die Geschwindigkeit vom Eeprom ja dem Takt vom Master anpasst.