Forum: Compiler & IDEs Problem beim Schreiben in I2C EEPROM


von Christof Kauba (Gast)


Lesenswert?

Hallo, ich benutze die I2C Master Library von P. Fleury und habe da ein 
kleines Problem.
Hin und wieder, wenn ich mit meiner Funktion ein Datum + Uhrzeit in den 
externen I2C EEPROM AT24C512 speichern will, schreibt er mir den ersten 
Eintrag, also die Stunde nicht, sondern stattdessen einfach gar nichts, 
also ich bekomme dann beim Auslesen entweder das, was vorher schon unter 
dieser Adresse stand oder 0xFF.
Hier meine Funktion:
1
void recTime(void)
2
{
3
  // Überprüfung auf Änderung des Monats oder des Jahres
4
  
5
  if ((prevMonth != recMonth) || (count == 0))
6
  {
7
    eeprom_write_word(&eeMonthAddress[recMonth-1], address);
8
  }
9
10
  // Schreiben der Werte in externen EEPROM
11
  
12
  i2c_start_wait(i24c512+I2C_WRITE);
13
  i2c_write(address >> 8);
14
  i2c_write(address);
15
  i2c_write(recHour);
16
  i2c_write(recMinute);
17
  i2c_write(recSecond);
18
  i2c_write(recDate);
19
  i2c_write(recMonth);
20
  i2c_stop();
21
  
22
  address += 5;    // Adresse erhöhen
23
  
24
  count++;  
25
}
Ich sollte vielleicht noch dazu sagen, dass ich nicht den Hardware TWI 
meines ATMEGA32 verwende, da dieser komischerweise gar nicht 
funktioniert hat, also jedes mal, wenn ich aus dem EEPROM lesen bzw. in 
den EEPROM schreiben wollte, blieb das Programm einfach stehen.
Also verwende ich die softwareemulierte Version auf den Pins des 
Hardware TWI Interface.

Außerdem verwende ich noch den internen Timer2 zwecks Uhrzeit.

Woran kann nun dieses EEPROM Problem liegen, bzw. hat einer von euch 
eine Idee, wie ich es beheben kann?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Hast du schon probiert zu warten, bis die Zugriffe auf das interne 
EEPROM beendet sind?
1
  // ... Restcode ...
2
3
  // Warten Bis vorangegangene EEPROM Zugriffe
4
  // beendet sind und ggf. gesperrte Interrupts
5
  // wieder eingeschaltet sind.
6
  eeprom_busy_wait();
7
8
  i2c_start_wait(i24c512+I2C_WRITE);
9
10
  // ... Restcode ...

EEPROM in der AVR-Libc
http://www.nongnu.org/avr-libc/user-manual/group__avr__eeprom.html

von Daniel H. (heppi_)


Lesenswert?

Gute Idee, stimmt aber leider nicht. Es liegt an der Übergabe der 
Adresse des I2C Gerätes und des Read/Write Bits. Im ersten über I2C 
gesendeten Byte steht die Adresse und die Art des Zugriffs. Daher ergibt 
sich für Schreibzugriff:
Adresse * 2
da Bit 0 beim Schreibzugriff 0 sein muss und in 1 bis 7 die Adresse 
steht,
und fürs Lesen:
Adresse * 2 + 1
da Bit 0 beim Lesezugriff 1 sein muss. Habs grad eben noch getestet.

von holger (Gast)


Lesenswert?

@ Daniel

So ein Quatsch !
Wenn die I2C Adresse 0xA0 ist dann bleibt sie das auch.
Da muss nix geschoben werden. Schreiben geht dann mit
0xA0 und lesen mit 0xA1. Punkt und aus.

Wenn DU deine I2C Adresse anders definierst,
dann musst DU wohl schieben.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Dann ist doch eigentlich i24c512 ungeschickt definiert.

EDIT: Holger war schneller.

von Daniel H. (heppi_)


Lesenswert?

Tut mir leid das stimmt nicht. Die Adresse wird auch nciht geändert 
sondern nur das Byte, dass über den I2C Bus geschickt wird. Lies z.B. 
das Datenblatt des PCA9554/PCA9554A (8-bit I2C and SMBus I/O port with 
interrupt) auf Seite 7 .

von Daniel H. (heppi_)


Angehängte Dateien:

Lesenswert?

Im Anhang ein Bild der Bytes die über I2C gesendet werden müssen. 
Interessant in das Control Byte! 7 bit für die Adresse und ein Bit für 
Lesen/Schreiben!

von holger (Gast)


Lesenswert?

@ Daniel

Ach du meinst die Subadress die man aussen an den
Pins einstellen kann. Gut, die musst du schieben.
Oder definier sie gleich mit dem geschobenen Wert.
Dann sparst du dir das schieben.

von holger (Gast)


Lesenswert?

Ich denke mal das ist ein Problem mit den Pages.
Mehrere Bytes kann man nur innerhalb einer Page
direkt nacheinander schreiben.

Wenn nicht sicher ist das alle Bytes in einer
Page liegen muss man sie alle EINZELN schreiben.
Und nach jedem Byte schön warten (20ms reicht oder
per ACK-Polling) bis es auch drin ist.

von Falk B. (falk)


Lesenswert?

@ holger (Gast)

>Wenn nicht sicher ist das alle Bytes in einer
>Page liegen muss man sie alle EINZELN schreiben.

Oder mit ein wenig Grips die Page-Grenze berechnen und dann wieder 
teileweise/volle Pagezugriffe machen.

alle Bytes bis zu nächsten Page-Grenze schreiben
N mal volle Pages schreiben
Rest schreiben.

MFG
Falk

von Gast (Gast)


Lesenswert?

Ich hatte die gleichen Probleme, dass nur jedes Zweite Byte geschrieben 
wurde. Das liegt an den Timings vom EEPROM. Dadurch dass es bei mir 
nicht schnell gehen sollte, habe ich für jedes Byte eine Start+Stopp 
Routine gemacht mit einer kleinen Wartezeit zwischendurch.

von Christof Kauba (Gast)


Lesenswert?

Hi, also das mit den Pages habe ich auch schon wo gelesen, aber ich habe 
es auch schon so probiert, das ich jeden Wert einzeln in den EEPROM 
geschrieben habe, also jeweils mit Start und Stopp.
Außerdem passiert mir das ja immer nur beim ersten Wert, den ich in den 
EEPROM schreibe, also glaube ich fast, das es daran nicht liegt.

von Manfred S. (Gast)


Lesenswert?

Hallo,

ich habe die letzten Tage auch mit dieser Routine versucht ein Slave 
anzusprechen. Über den Fehler mit der Adresse bin ich auch gestolpert. 
Weiterhin funktioniert diese Routine nur, wenn der Slave schnell genug 
ist, da eine vom Slave low gehaltene CLK-Leitung ingoriert wird (Da ist 
das Protokoll nur teilweise implementiert). Nachdem ich die Routine 
entsprechen geändert hatte ging es dann. Am besten mit einem 
Speicheroszi mal den Übertragungsversuch aufzeichen. So habe ich die 
Fehler bei mir auch gefunden.

von Christof Kauba (Gast)


Lesenswert?

Hallo, leider habe ich zur Zeit kein Speicheroszi zur Verfügung, mitdem 
ich die Übertragung aufzeichnen könnte.
Inwiefern hast du die Routine geändert, damit es dann funktioniert hat?

von Manfred S. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Christof,

alle Details weiß ich nicht mehr. Ich hatte solange geändert, bis ich 
auf dem Oszi das passende hatte. Ich habe meine aktuelle i2cmaster.S 
angehängt. Probier sie doch einfach mal aus, ob es was hilft. Durch die 
Änderung kann es theoretisch vorkommen dass er bei einem Fehler auf dem 
Buss "hängen" bleibt (wenn CLK während einer Übertragung auf low geht 
und low bleibt). Diese Problem hatte ich bei der Orginal Atmel USI 
Application Note als Slave, wenn der Sedebuffer im Slave leer war.

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.