Hallo an alle Cracks, :)
ich habe ein Problem an dem ich mittlerweile seit ca. 30 Arbeitsstunden
sitze und so langsam mit meinem Latein am Ende bin.
Mein System:
- atmega32 wahlweise auch atmega16
- EEprom 24HC512
- Hardware TWI (100kHz) des µCs per Bibliothek von Peter Flury
- Debugausgabe per Uart
- avr-gcc 4.3.4
- 5V Versorgungsspannung
- 16 MHz Quarz am µc
Ein Problem mit der Bibliothek und der Hardware kann ich fast
ausschließen, da ich an dem I2C Bus noch weitere Bausteine angeschlossen
habe und diese einwandfrei funktionieren. Zum testen habe ich allerdings
meinen Code und meine Schaltung auf das nötigste beschränkt.
Ich möchte gerne viele Werte hintereinander in den Speicher schreiben.
Am Anfang schreibe ich ein paar Byte als Startwerte die ich später
benötige und anschließend kommt eine lange reihe von Messwerten. Bei
kleinen Messungen funktioniert dies auch sehr gut aber sobald ich über
4096 Byte komme treten sehr komische Effekte auf. Dazu aber gleich mehr.
Das schreiben in den EEprom erfolgt für jedes Byte nach einander. Ich
greife sowohl auf das acknowlege polling zurück und warte zusätzlich
zwischen dem schreiben der einzelnen Werte auf jeden Fall die 10ms die
der EEprom benötigt. Somit habe ich zu sowohl sichergestellt, dass werte
nicht verschluckt werden sowohl auch, dass die Aufteilung von 512 Seiten
im EEprom a 128 Byte mir egal sein sollte.
Das Phänomen ist jetzt folgendes: Sobald ich ein Byte mehr als 4096
schreibe wird automatisch das aller erste beschriebene Byte (bei dem ich
angefangen habe) nicht direkt überschrieben sondern mit dem neuen wert
per logischem UND verknüpft.
Um es verständlicher zu machen hier ein kleines Beispiel:
Adresse Wert
0 193
4095 97
4096 97 ---> hier wird aber NICHT der korrekte in 4096 geschrieben,
sondern der
Werte in 0 und 4096 ist plötzlich 65. Das entspricht 193 & 97.
Als ob die beiden Speicherbereiche irgendwie mit einander verknüpft
wären.
Das Phänomen taucht nicht nur auf, wenn ich bei 0 anfange, sondern auch
wenn ich bei 60 oder 1000 anfange. Aber auch erst wieder nach 4096
Bytes.
Wenn ich dann noch weiter schreibe wird der geschriebene Wert mit dem
Speicherbereich Start+1 Verknüpft und in beide Speicherbereiche
geschrieben.
So langsam weiß ich einfach nicht mehr woran es liegen könnte. Die
Adresse zum beschreiben wird immer um 1 iteriert und als Word (16Bit) an
das EEprom gesendet.
Hier noch ein paar Ausschnitte aus meinem Code:
eeprom_write_inc verweist auf eeprom_write nur dass sie zusätzlich den
übergebenen Adresswert um eins erhöht.
Ich hoffe einfach, dass mir jemand von euch weiter helfen kann.
Gruß
Kalle
Moin erst einmal,
ich freue mich, dass sich so schnell schon jemand gemeldet hat um mir zu
helfen.
thb4hw45 schrieb:> Oszilloskop an den Bus hängen und mitloggen, was da wirklich passiert.
Ja daran habe ich natürlich auch schon gedacht, aber es ist leider nicht
so einfach eins zu besorgen. Daher fällt das leider erst einmal flach.
Ich denke aber auch nicht, dass es so dringend notwendig ist, da ich mit
der gleichen Bibliothek mehrere I2C Geräte (die zB auch einen kleinen
EEprom dabei haben ähnlich dem 24C512) einwandfrei ansprechen kann.
Darüber hinaus funktioniert es mit kleineren Datenmengen ja auch.
Außerdem tritt das Problem auch auf, wenn ich bei dem Beschreiben der
Werte in der Mitte eine längere Pause mache.
c-hater schrieb:> Pascal G. schrieb:>>> Ich>> greife sowohl auf das acknowlege polling zurück>> Wo? In dem geposteten Code ist davon jedenfalls nichts zu sehen.
Tut mir leid, ich hatte angenommen, dass hier im Forum die Bibliothek
von Peter Flury sehr bekannt ist und daher den Code nicht auch noch
gepostet. Aber hier ein kleiner Ausschnitt dazu. Der Rest ist im Code
als Anhang dabei.
// wait until stop condition is executed and bus released
39
while(TWCR&(1<<TWSTO));
40
41
continue;
42
}
43
//if( twst != TW_MT_SLA_ACK) return 1;
44
break;
45
}
46
47
}/* i2c_start_wait */
Darüber hinaus ist es vermutlich für mein Problem nicht so relevant ob
das Acknowlege Polling funktioniert oder nicht da ich im Moment zu
Testzwecken ja sowieso die Doppelte Zeit warte die der EEprom zum
Speichern benötigt.
Trotzdem habe ich das noch mal getestet. Wenn ich den Delay weglasse
nach dem schreiben, dann werden einige Werte verschluckt, da das
Acknowlege Polling anscheinend nicht 100% funktioniert. Auch nicht wenn
ich es auf folgende Art nach baue:
1
aiagin:;
2
uint8_tr=i2c_start(Dev24C512+I2C_WRITE);
3
if(r!=0)
4
{
5
i2c_stop();
6
gotoagian;
7
}
Falls ich mich aber irre, freue ich mich sehr über
Verbesserungsvorschläge. Anscheinend muss ich an irgend einer Stelle ja
einen Denkfehler haben.
Gruß
Kalle
Sebastian W. schrieb:> 24HC512? Original-IC oder Plagiat?
Ich habe mittlerweile zwei verschiedene denke ich getestet.
Das eine ist ein
ATMLU040
2FB 2
Im DIP8 Gehäuse. Das Ding von Atmel.
Und das andere IC ist im SOIC8 Gehäuase also als SMD Bauform. Drauf
steht:
24512WA
Ich glaube dort ein Atmel Logo erkennen zu können, aber das kann auch
nur ein Fake sein.
Sebastian W. schrieb:> Ansonsten mal deinen kompletten Test-Quellcode.
Der komplette Code ist anbei. Ich hoffe, dass man halbwegs
nachvollziehen kann was ich hier mache. Es ist sicherlich etwas
umständlich, aber zum testen reicht es.
Eine Kurze Erklärung dazu:
Am Anfang schreibe ich überall Nullen rein damit ich immer die gleiche
Ausgangslage habe.
Anschließend erfolgt eine kleine Ausgabe.
Dann werden die Startwerte geschrieben. Hierbei habe ich nur zum testen
auf die Pagewrite Funktion zurück gegriffen.
Danach folgt wieder eine Ausgabe des gleichen Adressintervalls.
Darauf Folgend werden dann die Testmesswerte geschrieben. Hier habe ich
gerade zum testen einmal nicht mehr jeden Werte, sondern jeden zweiten
Wert geschrieben. Leider selbes Ergebnis. Das heißt beim Startwert +
4096 Treten die gleichen Probleme wieder auf. Obwohl ich nur jeden
zweiten Adresse beschreibe.
Am Ende erfolgt dann wieder eine Ausgabe der selben Bereiche.
Ich programmiere das ganze unter Ubuntu mit dem AVR Eclipse Plugin. Die
Frequenz und der Controllertyp sind in den Einstellungen richtig
eingestellt. Aber es macht auch kein Unterschied wenn ich das ganze mit
einem eigenen Makefile kompiliere. Das heißt Probleme bei Eclipse sind
auch eher aus zu schließen.
Ach so und die Fusebits sind wie fogl gesetzt:
low:CF
high:D9
Vielen Danke noch mal für die schnellen Antworten.
Gruß
Kalle
Ich kenn die I2C-Bibliothek nicht, aber i2c_start_wait gibt ja keinen
Fehlercode zurück. Vielleicht solltest du in eeprom_read und
eeprom_write mal alternativ i2c_start mit Auswertung des Rückgabewerts
benutzen, vor allem, wenn du weder Logikanalyser (z.b Saleae & Co) noch
Oszi hast.
Pascal G. schrieb:> Tut mir leid, ich hatte angenommen, dass hier im Forum die Bibliothek> von Peter Flury sehr bekannt ist
Bei den C-lern vermutlich schon. Ich bin aber keiner, jedenfalls
höchstens unfreiwillig. Wie auch immer...
Dein Code macht jedenfalls nicht das, was nötig wäre. Was das ist, steht
im Datenblatt des 24C512 auf Seite 9.
> Darüber hinaus ist es vermutlich für mein Problem nicht so relevant
Im Gegenteil, das ist sogar höchst relevant, denn...
> Wenn ich den Delay weglasse> nach dem schreiben, dann werden einige Werte verschluckt, da das> Acknowlege Polling anscheinend nicht 100% funktioniert.
Eben. Genau das ist der springende Punkt. Du solltest du dich doch wohl
ernsthaft fragen, warum das wohl so sein mag...
Ich würde mal folgende Fassung vorschlagen:
void eeprom_write(uint16_t addr, uint8_t val)
{
i2c_start_wait(Dev24C512+I2C_WRITE);
i2c_write((addr>>8)&0xFF);
i2c_write(addr&0xFF);
i2c_write(val);
}
Funktioniert das besser?
Pascal G. schrieb:> Am Anfang schreibe ich überall Nullen rein damit ich immer die gleiche> Ausgangslage habe.
Sicher, daß da im Leerzustand Nullen drin sein sollen, und nicht Einsen?
Mit sowas hatte ich auch schon mal Probleme, allerdings bei einem
anderen EEPROM-Typ.
Sebastian W. schrieb:> Ich kenn die I2C-Bibliothek nicht, aber i2c_start_wait gibt ja keinen> Fehlercode zurück. Vielleicht solltest du in eeprom_read und> eeprom_write mal alternativ i2c_start mit Auswertung des Rückgabewerts> benutzen, vor allem, wenn du weder Logikanalyser (z.b Saleae & Co) noch> Oszi hast.
"i2c_start_wait" gibt keinen Code zurück, da in dieser Funktion so lange
eine Schleife durchläuft bis kein Fehler mehr entsteht. Also braucht es
auch keinen zurück geben. Aber dennoch habe ich wie oben vorher
beschrieben auch schon die Variante mit "i2c_start" versucht.
------------------------------------------------------------
c-hater schrieb:> Dein Code macht jedenfalls nicht das, was nötig wäre. Was das ist, steht> im Datenblatt des 24C512 auf Seite 9.
Das verstehe ich jetzt nicht so ganz. Wieso macht mein Code nicht das
was es machen sollte? Da wäre ein Hinweis ganz nett.
Und ja ich habe das Datenblatt schon mehr als einmal gelesen. Falls du
darauf abzielen solltest.
>> Wenn ich den Delay weglasse>> nach dem schreiben, dann werden einige Werte verschluckt, da das>> Acknowlege Polling anscheinend nicht 100% funktioniert.>> Eben. Genau das ist der springende Punkt. Du solltest du dich doch wohl> ernsthaft fragen, warum das wohl so sein mag...
Ja das habe ich mich auch schon gefragt. Aber das ist ja im Moment nicht
mein Problem, da ich dem EEprom ja genug Zeit gebe um die Daten aus
seinem flüchtigen Speicher in den nicht flüchtigen Speicher zu
schreiben.
Ich sehe im Moment nicht den direkten Zusammenhang zwischen diesem
Problem und meinem Hauptproblem. Für Eine Erklärung bin ich aber immer
offen.
> Ich würde mal folgende Fassung vorschlagen:>> void eeprom_write(uint16_t addr, uint8_t val)> {> i2c_start_wait(Dev24C512+I2C_WRITE);> i2c_write((addr>>8)&0xFF);> i2c_write(addr&0xFF);> i2c_write(val);> }>> Funktioniert das besser?
Damit ich dich nicht falsch verstehe. Dein Vorschlag entspricht meinem
Code mit der Ausnahme dass der Delay und das Stopp Signal weg gelassen
werden sollen? Das "i2c_start_wait" ist in meinem code auch drinne, nur
es ist hier im Forum in eine Zeile drüber gerutscht.
Ich kann das gerne versuchen, aber sehe da den Sinn noch nicht so ganz.
Ohne Delay habe ich es bereits versucht. Darüber hinaus ist im
Datenblatt genau beschrieben, dass nach dem Schreibvorgang ein Stopp
Signal gesendet werden muss.
Mal komplett abgesehen davon. Wieso treten die Fehler nur auf, wenn ich
viel in den Speicher schreibe und bei anderen ICs über die I2C
Schnittstelle gar nicht? Das Verstehe ich halt nicht so recht.
------------------------------------------------------------
Wilhelm Ferkes schrieb:> Sicher, daß da im Leerzustand Nullen drin sein sollen, und nicht Einsen?>> Mit sowas hatte ich auch schon mal Probleme, allerdings bei einem> anderen EEPROM-Typ.
Nein da bin ich mir gar nicht sicher. Aber ich würde ungern 1 Nehmen, da
1 auch ein Messwert sein könnte. Aber auch das werde ich kurz testen.
Vielen Dank für eure Vorschläge. Ich werde mich wieder melden, wenn ich
weitere Informationen habe oder es sogar funktionieren sollte. :-)
Gruß
Kalle
Weiß nicht obs Dir hilft, aber diese Verknüpfung zweier Werte klingt für
mich so, als ob diese Adresse doppelt beschrieben wird ohne den EEPROM
zu löschen.
Pascal G. schrieb:> Damit ich dich nicht falsch verstehe. Dein Vorschlag entspricht meinem> Code mit der Ausnahme dass der Delay und das Stopp Signal weg gelassen> werden sollen?
Genau so ist das.
c-hater schrieb:> Pascal G. schrieb:>>> Damit ich dich nicht falsch verstehe. Dein Vorschlag entspricht meinem>> Code mit der Ausnahme dass der Delay und das Stopp Signal weg gelassen>> werden sollen?>> Genau so ist das.
Okay. Ich werde es versuchen und mich dann wieder melden. Könntest du
mir vielleicht noch erklären, aus welchem Grund ich das Stoppsignal weg
lassen soll?
Und wenn es dadurch funktionieren sollte würde ich mit meinem µC doch
den I2C Bus dauerhaft blockieren oder?
Gruß
Kalle
Pascal G. schrieb:> Nein da bin ich mir gar nicht sicher. Aber ich würde ungern 1 Nehmen, da> 1 auch ein Messwert sein könnte. Aber auch das werde ich kurz testen.
Dann stimmt grundsätzlich mit deinem Konzept was nicht.
Ich fand das in meiner Anfangszeit auch mal merkwürdig, daß in einem
leeren Baustein Einsen drin stehen. Bei Flash ist das auch so, und ein
EPROM hat nach dem UV-Löscher auch nur Einsen. Die Speicherzellen werden
mit Null aktiv beschrieben. Man gewöhnt sich dran.
Wilhelm Ferkes schrieb:> Dann stimmt grundsätzlich mit deinem Konzept was nicht.>> Ich fand das in meiner Anfangszeit auch mal merkwürdig, daß in einem> leeren Baustein Einsen drin stehen. Bei Flash ist das auch so, und ein> EPROM hat nach dem UV-Löscher auch nur Einsen. Man gewöhnt sich dran.
Das Konzept zu ändern ist im Moment noch kein großes Problem das würde
ich hin bekommen.
Meinst du wirklich für jedes Byte = 1 oder für jedes Bit?
Also beim beschrieben 0x01 oder 0xFF?
Gruß
Kalle
Pascal G. schrieb:> Meinst du wirklich für jedes Byte = 1 oder für jedes Bit?> Also beim beschrieben 0x01 oder 0xFF?
Es ist wurscht, was man reinschreibt, der EEPROM macht grundsätzlich ein
Erase vor jedem Schreiben, das kannst Du nicht verhindern.
Deshalb heißt er ja EEPROM, wäre ein Erase nötig, hieße er Flash.
Ob man nun ungültig als 0x00 oder 0xFF oder sonstwas markiert, ist rein
persönlicher Geschmack.
Pascal G. schrieb:> Könntest du> mir vielleicht noch erklären, aus welchem Grund ich das Stoppsignal weg> lassen soll?
Weil der nächste Aufruf sowohl von eeprom_write als auch für eeprom_read
für das Device das implizit in i2c_start_wait erledigt und zwar (im
Gegensatz zu deinem Code) auch noch im richtigen "Moment".
> Und wenn es dadurch funktionieren sollte würde ich mit meinem µC doch> den I2C Bus dauerhaft blockieren oder?
Richtig, gut mitgedacht. Deswegen sollte dein letzter Zugriff auf das
Device auch immer ein eeprom_read sein. Das dortige i2c_stop kannst du
übrigens auch gleich noch entsorgen. Es richtet hier zwar wenigstens
keinen Schaden an, nützt aber auch nix. Warum? Auf Seite 10 des
Datenblattes steht die Antwort.
Pascal G. schrieb:> Meinst du wirklich für jedes Byte = 1 oder für jedes Bit?
Jedes Bit natürlich.
Peter Dannegger schrieb:> Es ist wurscht, was man reinschreibt, der EEPROM macht grundsätzlich ein> Erase vor jedem Schreiben, das kannst Du nicht verhindern.> Deshalb heißt er ja EEPROM, wäre ein Erase nötig, hieße er Flash.
Nicht generell. Ich habe hier noch einige parallele 28C16A, die auch der
EPROMMER nicht generell löscht. Will ich den Baustein neu beschreiben,
dann muß ich den EPROMMER vorher mit einem Hex-File laden, welches nur
Einsen hat, dann brennen. Erst nach diesem Vorgang kann ich den Baustein
neu beschreiben. Diese parallelen 28C16A hatten aber auch keinen
Löschbefehl intern, keine Steuerung, waren simpelst. Das einzige, was
die machten, war eine interne Programmierspannungserzeugung, wenn man
den Nicht-A-Typ hatte.
Pascal G. schrieb:> Könntest du> mir vielleicht noch erklären, aus welchem Grund ich das Stoppsignal weg> lassen soll?
Das STOP ist unbedingt nötig!
Senden man ein (Repeat-)Start, d.h. ohne vorheriges Stop nach den zu
schreibenden Daten, wird das Schreiben abgebrochen. Der EEPROM behält
die alten Daten. Das steht auch eindeutig im Datenblatt.
Der EEPROM kann ja nicht hellsehen, wieviel Bytes Du reinschreiben
willst. Daher wartet er mit dem Schreibzyklus bis zum Empfang des Stop.
c-hater schrieb:> Ja, natürlich. Nur nicht an dieser Stelle im Code. Dort ist es noch "zu> früh" dafür.
Vermutlich meinst Du nach dem Senden der Adresse und vor dem Umschalten
auf Lesen. Da braucht man es nicht, aber es stört auch nicht.
Es würde nur in einer Multimasterumgebung stören, dann könnte sich ein
anderer Master den EEPROM krallen und das Lesen schlägt fehl.
c-hater schrieb:> Peter Dannegger schrieb:>>> Vermutlich meinst Du nach dem Senden der Adresse und vor dem Umschalten>> auf Lesen>> Nein.
Ergänzung: Jetzt erkenne ich erst, daß sich deine Anmerkung auf meinen
Vorschlag bezieht, auch in eeprom_read das i2c_stop wegzulassen.
Diesbezüglich hast du völlig recht, das war Blödsinn. Datenblatt zu
flüchtig gelesen.
Moin,
also ich denke auch nicht, dass man es beim schreiben weg lassen sollte.
Im Datenblatt ist eindeutig zu erkennen, dass nach dem Wert den man
schreiben möchte ein Stoppsignal zu senden ist.
Ich habe es auch mal ohne versucht, daher
Dieser Code ist ja auch nur ein kleiner Test. Später sollen alle 10
Sekunden ein Byte in den EEprom geschrieben werden. Innerhalb der 10
Sekunden greift der Controller auf andere I2C ICs zu.
In dem gepostetem Code soll das zum Testen nur etwas beschleunigt
werden. Das heißt es ist für mich wirklich nötig nach dem Schreiben den
Bus wieder frei zu geben um mit anderen Geräten kommunizieren zu können.
Wenn ich die Stoppbedingung nicht senden würde, dann würde ich doch ein
einfaches Pagewrite machen oder? Und das ist ja eigentlich nicht das was
ich möchte.
Ich hoffe mal, dass wir nicht aneinander vorbeireden.
Also zum schrieben:
1
i2c_start_wait(Dev24C512+I2C_WRITE);
2
i2c_write((addr>>8)&0xFF);
3
i2c_write(addr&0xFF);
4
i2c_write(val);
5
i2c_stop();
Wenn ich hier die Rückgabewerte abfrage nach jedem write, bekomme ich
auch keinen Fehler zurück.
Und zum lesen
1
i2c_start_wait(Dev24C512+I2C_WRITE);
2
i2c_write((addr>>8)&0xFF);
3
i2c_write(addr&0xFF);
4
i2c_rep_start(Dev24C512+I2C_READ);
5
uint8_tret=i2c_readNak();
6
i2c_stop();
Peter Dannegger schrieb:> Es ist wurscht, was man reinschreibt, der EEPROM macht grundsätzlich ein> Erase vor jedem Schreiben, das kannst Du nicht verhindern.> Deshalb heißt er ja EEPROM, wäre ein Erase nötig, hieße er Flash.>> Ob man nun ungültig als 0x00 oder 0xFF oder sonstwas markiert, ist rein> persönlicher Geschmack.
Danke für den Post und ich dachte schon ich hätte alles falsch
verstanden. ;-)
Gruß
Kalle
Pascal G. schrieb:
Ja und? Was ist dabei rausgekommen? Das wäre interessant gewesen.
> Dieser Code ist ja auch nur ein kleiner Test. Später sollen alle 10> Sekunden ein Byte in den EEprom geschrieben werden. Innerhalb der 10> Sekunden greift der Controller auf andere I2C ICs zu.
So what? Du machst einfach, was ich dir vorgeschlagen habe (abzüglich
des von Peter bereits korrigierten Blödsinns über das Weglassen von
i2c_stop in eeprom_read natürlich).
Du läßt also das i2c_stop in eeprom_write weg und baust zusätzlich eine
neue Funktion
int eeprom_write_and_verify(uint16_t addr, uint8_t val)
{
eeprom_write(addr, val);
return eeprom_read(addr) == val;
}
und rufst die (und nicht direkt eeprom_write) alle 10 Sekunden auf. Da
hast du dann obendrein immer auch gleich noch die Rückinformation, ob
das Schreiben wirklich geklappt hat.
Und der Bus ist dann in der Zwischenzeit auch frei.
Und wenn ich die Ursache des Problems wirklich richtig erkannt habe,
verschwinden dann auch die "kuriosen Effekte".
c-hater schrieb:> Ja und? Was ist dabei rausgekommen? Das wäre interessant gewesen.
Es hatte nicht funktioniert.
> Du läßt also das i2c_stop in eeprom_write weg und baust zusätzlich eine> neue Funktion>> int eeprom_write_and_verify(uint16_t addr, uint8_t val)> {> eeprom_write(addr, val);> return eeprom_read(addr) == val;> }>> und rufst die (und nicht direkt eeprom_write) alle 10 Sekunden auf. Da> hast du dann obendrein immer auch gleich noch die Rückinformation, ob> das Schreiben wirklich geklappt hat.
Wie ich vermutet habe, funktioniert das leider nicht.
Der Controller macht nach meinem Verständnis jetzt auch nicht das was er
tun sollte.
Nach deinem Vorschlag macht er glaube ich Folgendes:
- Start Signal
- write Device Adresse + Write Bit (0)
- write Wert
- sendet ein erneutes Start signal
- write Device Adresse + Read bit (1)
- stop Signal
- erneutes Start Signal
usw......
So das ist aber laut Datenblatt ja nicht richtig, da das EEprom ein
Stoppsignal benötigt damit er weis, dass ich nicht weiter schreiben
möchte.
Daher wirft er die Schreibwerte einfach weg.
Dies wurde aber weiter oben in einem Post auch schon erwähnt.
Und falls das gerade nicht so herüber kommt. Ich bin wirklich dankbar,
dass du dich so mit meinem Problem Auseinander setzt. Aber wir scheinen
einfach wirklich aneinander vorbei zu reden oder zwei verschiedene
Sachen machen zu wollen.
Ich werde gegen Ende der Woche mal versuchen mit einem I2C Sniffer
wirklich zu schauen, was auf dem Bus vor sich geht und mich dann hier
wieder melden.
Daher wirklich vielen Dank für deine Mühen!
Gruß
Kalle
Pascal G. schrieb:> Es hatte nicht funktioniert.
OK. Dann eine andere Variante. Dein ursprünglicher Code, aber die
Reihenfolge von i2c_stop und delay getauscht. Wenn das funktioniert,
delay ggf. verkürzen.
Sebastian W. schrieb:> Mal noch ne andere Idee: Hast du A0, A1 und WP mit GND verbunden?
Ja das habe ich gemacht. Aber das ist ja nur für die Device Adresse. Das
Device kann ich ja einwandfrei ansprechen.
Eher könnte es sein, dass der WP (Write Protection) Pin intern nicht
richtig auf Masse gelegt ist, aber das habe ich mittlerweile auch schon
vorgenommen.
c-hater schrieb:> OK. Dann eine andere Variante. Dein ursprünglicher Code, aber die> Reihenfolge von i2c_stop und delay getauscht. Wenn das funktioniert,> delay ggf. verkürzen.
Okay danke. Aber führt leider auch nicht zu dem gewünschten Effekt.
Habe es mit verschiedenen Werten zwischen 1ms und 15ms versucht.
Wie gesagt, am Wochenende werde ich mir mal mit einem anderen Atmega
anschauen, was wirklich auf der Schnittstelle los ist.
Darüber hinaus werde ich als nächstes einmal versuchen ein Page Write
vor zu nehmen, dass ich auf einmal 128 Werte schreibe und dann wieder
solange bis ich dann zu einem Fehler komme.
Gruß
Kalle
Moin noch mal,
jetzt habe ich den Code mal auf ein Minimu reduziert und es scheint mir
einfach, dass ich anscheinend entgegen meiner Meinung die Adressierung
des EEproms doch nicht richtig verstanden habe.
Der Minimalcode mit Debugausgabe:
1
intmain()
2
{
3
// initialisieren des I2C bus
4
i2c_init();
5
6
// initialisiere uart
7
usart_init(BAUDRATE);
8
9
sei();
10
11
eeprom_init();
12
13
14
_delay_ms(100);
15
usart_write(CRCR"-- start --"CR);
16
_delay_ms(100);
17
18
printf("test mit 0x%x - h:0x%x l:0x%x"CR,0x1000,(0x1000>>8)&0xFF,0x1000&0xFF);
19
20
eeprom_write(0x00,0x0);
21
_delay_ms(100);
22
eeprom_write(0x1000,0x0);
23
24
_delay_ms(100);
25
uint8_tv1=eeprom_read(0x00);
26
uint8_tv2=eeprom_read(0x1000);
27
printf("0:%x - 1000:%x"CR,v1,v2);
28
_delay_ms(100);
29
30
eeprom_write(0x00,0xf0);
31
32
_delay_ms(100);
33
v1=eeprom_read(0x00);
34
v2=eeprom_read(0x1000);
35
printf("0:%x - 1000:%x"CR,v1,v2);
36
_delay_ms(100);
37
38
eeprom_write(0x1000,0xee);
39
40
_delay_ms(100);
41
v1=eeprom_read(0x00);
42
v2=eeprom_read(0x1000);
43
printf("0:%x - 1000:%x"CR,v1,v2);
44
_delay_ms(100);
45
46
for(;;);
47
48
return0;
49
}
Die Ausgaeb dazu:
1
-- start --
2
test mit 0x1000 - h:0x10 l:0x0
3
0:0 - 1000:0
4
0:f0 - 1000:0
5
0:e0 - 1000:ee
Das Sieht doch wirklich stark danach aus, dass die Adressierung nicht
stimmt oder?
Jetzt muss ich wohl doch mal schauen, dass ich ein Oszi bekommen um mir
das mal genauer an zu sehen.
Gruß
Kalle
Hallo, ich mal wieder. ;)
Das Problem schient bei den höchstwertigen 4 Bit zu liegen und auch
immer nur bei Adresse die n * 0x1000 auseinander liegen.
Das heißt wenn ich 0x00 beschriebe und anschließend 0x1000 tritt das
Problem auf wie im Post vorher zu sehen, aber auch wenn ich 0x1000 und
0x3000 beschreibe.
Mit anderen Worten die höchstwertigen 4 Bit werden anscheinend nicht
richtig übertragen.
Aber um dies genau zu testen, muss ich erst mal warten bis ich ein Oszi
zur verfügung habe.
Gruß
Kalle
>Das Problem schient bei den höchstwertigen 4 Bit zu liegen und auch>immer nur bei Adresse die n * 0x1000 auseinander liegen.
Hast du da vieleicht ein 24C32 EEPROM und kein 24C512?
Ich glaub hier haben schon alle aufgegeben;)
Ein langer Leidensweg ist zu Ende. Der Fehler ist gefunden. ;-)
Erst einmal vielen Dank an alle die sich die Köpfe für mich angestrengt
haben.
Hatte vor lägerem alles andere abgezogen, was noch an meinem µC mit dran
hängt, aber zwischenzeitlich um etwas anderes zu testen eine RTC wieder
mit angeschlossen. Und diese war der Übeltäter.
Fhutdhb Ufzjjuz schrieb:> öhm ... welche Pullups hast Du denn drannen?> kannst ja mal etwas mit dem Takt arbeiten, mal nen höheren oder tieferen> Bustakt ausprobiert?
Hatte mehrmals zwischen 100kHz und 400kHz variiert. An Pullups verwende
ich 10kOhm.
Gruß
Kalle
Falls es noch wen interessiert.
Ein kleiner Nachtrag noch. Mittlerweile habe ich auch das Problem
komplett analysieren können.
Der EEprom auf dem RTC Modul ist ein 32K EEprom mit der gleichen Adresse
wie mein 512K EEprom. Das heißt, immer wenn das RTC Modul angeschlossen
war, habe ich ohne es zu merken das EEprom beschrieben und nicht das
Große, dass ich angeschlossen habe.
Die Adresse habe ich jetzt über die Hardeware Adressierung verändert und
es funktioniert einwandfrei.
Auch der I2C Code funktioniert jetzt ohne delay.
Gruß
Kalle
Georg G. schrieb:> Verrätst du uns bitte noch, wie das RTC Modul heißt, damit wir das> Fettnäpfchen vermeiden können?
Na klar sorry.
Wie das Board jetzt genau heißt kann ich dir allerdings nicht genau
sagen. Das scheint aber in der AVR Welt bekannt zu sein.
Auf dem Board ist ein DS1307 mit nem 24C32 von Atmel. In den gänigen
Suchmaschinen findet man ziemlich schnell etwas dazu.
Gruß
Kalle