Hallo zusammen,
ich bin seit Tagen daran ein 25LCxxx EEPROM am SPI zum laufen zu
bekommen.
Ich bin sogar soweit, dass ich den Rest vom SPI Bus (der funktioniert)
abgetrennt habe und bereits eine RC Terminierung mit 100Ohm und 22pC am
SCL, sowie einen 100nF Abblockkondensator zwischen Vcc und Gnd
nachgerüstet habe. Allerdings gibt das EEPROM immernoch zufällige Wert
zurück, bzw. es wird irgendwas empfangen.
Der Chip ist ein AVR ATmega32A, CPU Takt: 11,0592MHz. Meine Vermutung
ist, dass die SPI nicht richtig eingestellt ist. Aber ich habe schon
vieles probiert und auch die Outputs des ATmega im Masterbetrieb über
die UART ausgeben lassen. Soweit sieht alles korrekt aus. Die Befehle
werden alle laut Datenblatt korrekt gesendet.
Irgendwas muss ich übersehen oder der EEPROM ist defekt!? Irgendwo hatte
ich auch mal gelesen, dass beim Masterbetrieb die Reihenfolgen der SPI
Befehle und das Setzen der Ausgänge entscheidet wäre. Allerdings
funktioniert das Senden derzeit ohne Probleme und empfangen wird auch
etwas - aber nichts brauchbares :(
Ich würde mich über Hilfe sehr freuen. Grüße Kai
Kai schrieb:> static uint8_t dev_25LC512_SPI_REC(void)> {> while (!(SPSR & (1<<SPIF))); //Warten bis Byte empfangen> return SPDR;> }
Da fehlt das Senden von Daten. Das muss man auch bei Lesen tun, denn SPI
sendet und empfängt immer gleichzeitig.
1
SPDR=0x00;
2
while(!(SPSR&(1<<SPIF)));//Warten bis Byte empfangen
Du kannst die gleiche Funktion für senden und lesen nutzen.
Wenn du lesen willst, übergibst du halt ne 0 und wenn du nur senden
willst ignorierst du den Rückgabewert.
1
uint8_tspi_8bit(uint8_tdata){
2
SPDR=data;
3
while(!(SPSR&(1<<SPIF)));//Warten bis Byte empfangen
Ok, verstehe! Vielen Dank!
Aber mir kommt da gerade die Frage: Wieso bekomme ich irgendwelche
zufälligen Werte ausgegeben? Also wenn der Empfang nicht klappt sollte
der Return doch immer NULL sein oder das letzte Byte was ich gesendet
habe?
Ich möchte nur verstehen wie die Werte zustande kommen, um
Hardware-seitig irgendwelche weitere Fehler auszuschließen.
Kai schrieb:> Aber mir kommt da gerade die Frage: Wieso bekomme ich irgendwelche> zufälligen Werte ausgegeben? Also wenn der Empfang nicht klappt sollte> der Return doch immer NULL sein oder das letzte Byte was ich gesendet> habe?
Nein, das letzte empfangene Byte. Es gibt aber Situationen, da sendet
der EEPROM nix beim Schreibzugriff. MISO hängt dann in der Luft und
erzeugt Zufallsdaten, die dein AVR empfängt. Um das zu verhindern,
sollte man MISO mit 10k Pull Up versehen. Dann empfängt man sicher nur
0xFF.
Deine fehlerhaft Empfangsroutine macht keinen Lesezugriff sondern
liefert das zuvor zuletzt empfangene Byte.
By the way: Mein Code hat bei einem ATmega644P funktioniert. Auf diesen
Chip hatte ich ihn entwickelt. Interessant, dass der ATmega32A wohl vor
dem Empfang ein Schreiben des SPI Data Register benötigt. Der ATmega644P
wohl nicht. Da hat das EEPROM tadellos gespielt. 😉
Falk B. schrieb:> Es gibt aber Situationen, da sendet> der EEPROM nix beim Schreibzugriff.
Woran am Datenblatt machst Du das fest? Für mich sieht es so aus, als
sei High-Z an SO nur möglich, wenn CS inaktiv ist.
Kai schrieb:> By the way: Mein Code hat bei einem ATmega644P funktioniert. Auf diesen> Chip hatte ich ihn entwickelt. Interessant, dass der ATmega32A wohl vor> dem Empfang ein Schreiben des SPI Data Register benötigt. Der ATmega644P> wohl nicht.
Ganz sicher nicht. Auch der braucht das.
> Da hat das EEPROM tadellos gespielt. 😉
Klingt nach Zufall.
Walter T. schrieb:>> Es gibt aber Situationen, da sendet>> der EEPROM nix beim Schreibzugriff.>> Woran am Datenblatt machst Du das fest? Für mich sieht es so aus, als> sei High-Z an SO nur möglich, wenn CS inaktiv ist.
Siehe Anhang.
Kai schrieb:> Sicher, das man an SO , MISO einen Pullup von 10kO anschließen sollte,> wenn mehrere Slaves an dieser Leitung hängen?
Muss man nicht, man muss nur wissen welche Empfangsdaten man ignorieren
muss. Bzw. eine wirklich funktionierende SPI-Transferfunktion benutzen,
wie sie hier gezeigt wird. Das ist Standard.
Beitrag "Re: 25LC512 SPI EEPROM seltsames Verhalten / defekt?"
Falk B. schrieb:>> Da hat das EEPROM tadellos gespielt. 😉>> Klingt nach Zufall.
Kann sein...
Aber an dieser Stelle erstmal vielen Dank für die Hilfe! Manchmal sieht
man vor lauter programmieren, die einfachsten Fehler nicht. 😉
Kai schrieb:> Manchmal sieht> man vor lauter programmieren, die einfachsten Fehler nicht.
Meistens liegt der Fehler am Bauteil, weil es aus China kommt
und wahrscheinlich ein Fake bzw. ein schlecht nachgebautes Teil
ist. Oder der deutsche Lieferant liefert einfach "schlechte"
Ware aus. Oder der Hersteller des Bauteils liefert noch Beta-
Ware aus in der noch nicht alle Fehler ausgemerzt sind, und man
hat soeben einen solchen Fehler gefunden.
Am Layer 8 liegt es eigentlich nie, das sagt schon der Thread-
Titel (SPI EEPROM seltsames Verhalten / defekt?).
Wastl schrieb:> Am Layer 8 liegt es eigentlich nie, das sagt schon der Thread-> Titel (SPI EEPROM seltsames Verhalten / defekt?).
Vielen dank für die Ironie!
Hannes schrieb:> Du kannst die gleiche Funktion für senden und lesen nutzen.>> Wenn du lesen willst, übergibst du halt ne 0 und wenn du nur senden> willst ignorierst du den Rückgabewert.> uint8_t spi_8bit(uint8_t data){> SPDR = data;> while (!(SPSR & (1<<SPIF))); //Warten bis Byte empfangen> return SPDR;> }
Ich habe die Funktion angepasst. AAAber... leider werden immer noch
zufällige Werte auslesen. Stimmt doch etwas mit spi_init() nicht? Jemand
noch eine Idee?
Kai schrieb:> Ich habe die Funktion angepasst. AAAber... leider werden immer noch> zufällige Werte auslesen. Stimmt doch etwas mit spi_init() nicht? Jemand> noch eine Idee?
Deinem Code im Anfangsbeitrag nach wird das SPI-Interface mit CPHA=1
benutzt – hast Du es schon mal mit CPHA=0 probiert? Eigentlich müsste
man Mode=0,0 sagen, das heißt CPOL und CPHA müssten dann beide auf 0
gesetzt sein und das wird bei den meisten ICs auch so eingestellt (im
Anhang meine Einstellungen für MAX7219). Clock ist dann im Ruhezustand
Low und getaktet wird mit der ersten (steigenden) Flanke, mit Deinem
CPHA=1 nimmst Du momentan die fallende Flanke, was die falschen Werte
erklären könnte.
___
Nur so nebenbei: man kann die ganzen Einstellungen auch in einer Zeile
machen – so wie Du das hast, wird das Interface eingeschaltet und dann
umgestellt. Das macht man eigentlich umgekehrt – man stellt alles ein
und schaltet dann das Schnittstelle ein (SPE=1). Ich erwähne das wie
gesagt nur vollständigkeitshalber wie man es richtig machen sollte bzw.
es von Anfang an richtig lernen sollte, denn mit Deinem Fehler hat das
nichts zu tun.
Gregor J. schrieb:> das SPI-Interface mit CPHA=1> benutzt – hast Du es schon mal mit CPHA=0 probiert? Eigentlich müsste> man Mode=0,0 sagen, das heißt CPOL und CPHA müssten dann beide auf 0> gesetzt sein und das wird bei den meisten ICs auch so eingestellt
VIELEN DANK FÜR DIE HILFE!! => GENAU DAS war der Fehler! Mit steigender
Flanke funktioniert es! DANKE!
Kai schrieb:> VIELEN DANK FÜR DIE HILFE!! => GENAU DAS war der Fehler! Mit steigender> Flanke funktioniert es! DANKE!
Sehr gerne. Wenn wir jetzt mal kurz die Sendeproblematik ausblenden,
dann war das eine kleine Ursache (ein Bit falsch gesetzt) mit großer
Wirkung, denn es läuft dann quasi gar nix mehr, der µC sendet und
sampelt immer zu falschen Zeit, genau dann, wenn das EEPROM Datenwechsel
auf der Leitung macht. Mode_1,1 müsste jetzt aber auch gehen, für diesen
Test müssten aber diese beiden Konfigurationspins auf 1 gesetzt werden,
Standard ist aber – wie ich bereits schrieb – Mode_0,0 und den wollen
die meisten ICs. Solche Fehler vergisst man lebenlang nicht mehr.
Von meiner Seite auch noch Danke, denn durch Deinen Thread bin ich auf
den Speicher gestossen, der einen Kompromiss zwischen den 24ern mit I²C,
wovon ich kein Fan bin, und den 25ern mit SPI bildet – bei den großen
SPI-Speichern gibt es keine einfachen Bytezugriffe mehr, man muss vorher
immer einen kleinen Block an Bytes löschen, um anschließend z.B. ein
Byte zu schreiben. Ich habe mir allerdings den M95256 und M95512 von ST
ausgesucht – die aktuell hergestellten Speicher sind nämlich nicht mehr
mit 100 Tausend, sondern mit 4 Millionen Schreibzugriffen spezifiziert,
was meinen Algorithmus zur Lebensdauerverlängerung eines Flashspeicher
überflüssig macht, d.h. programmtechnisch vereinfacht sich alles
radikal, bei 64 Kilobyte kann man aber diesen natürlich immer noch
einsetzen, um noch mehr Schreibzugriffe zu erhalten, falls das nötig
ist. Chinesische, günstige Alternativen habe ich mir jetzt auch
testweise besorgt – ob sie wirklich auch so gut sind, wird sich noch
zeigen. FRAM mit 10 hoch 14 Zugriffen habe ich mir auch testweise
bestellt (basiert auf ferroelektrischem Effekt) – für meine Roboter sind
diese aber noch zu teuer bzw. zu teuer bei größeren Kapazitäten, was
sich in der Zukunft hoffentlich bald nach und nach ändern wird.