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 :(
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.
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. 😉
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.
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.
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?).
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?
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.
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!
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.