Hallo! Ich bin Elektroniker Azubi und soll für die Arbeit ein Projekt machen, bei dem ich per SPI mit einer Peripherie kommunizieren soll. Als erste Anlaufstelle habe ich die Avrlib benutzt wo auch ganz hilfreiche Sachen drinstanden. Ich kann meinen AT90ST8115 einwandfrei als Master deklarieren. Allerdings habe ich beim Simulieren mit AVRStudio 4 gemerkt, dass das SPI Interface lediglich 4 statt 8 Bits rausgibt. Danach wird im SPSR der SPIF gesetzt. Ich habe echt keine Ahnung warum und auch keine Lösungsansätze mehr... Den Quellcode habe ich als Anhang beigefügt. Hat jemand da Hilfestellungen oder Lösungsansätze? Danke schonmal im Vorraus!
"SPI_Transfer_complete" Wird ja nirgndwo auf False gesetzt. Das heißt du unterbrichst die Laufende Übertragung für eine eventuell Nächste Übertragung. Achja: Du brauchst diese Variable nicht. Schmeiß die Raus. Die Warteschleife geht einfacher: while(!(SPSR & (1<<SPIF))) nop(); das ist das Interruptbit, das wird nach erfolgreicher Übertragung gelöscht. Du musst diese Schleife allerdings nach "SPDR = BYTE" einbauen, statt davor. PS: Es ist ein guter Stil Variablennamen klein zu schreiben und Makro-Namen in GROßBUCHSTABEN
Danke für die schnelle Antwort! Also ich habe die Warteschleife entsprechend abgeändert. Nur jetzt gibt er nur noch 2 Bits raus und setzt danach den SPIF. Meintest du, dass ich die Interrupts generell abstellen soll oder nur die Warteschleife ändern?
"DDRB |= ~(1 << 6);// Bit 6 - MISO als Eingang" ...und definiert nebenbei Pins 0-5,7 als Ausgang. Besser: DDRB &= ~(1 << 6);// Bit 6 - MISO als Eingang" Weiter unten sieht's ähnlich düster aus. Empfehlenswert ist es auch, das SPCR komplett zu setzen, also SPCR = bitX | bitY | bitZ; statt alle Bits einzeln abzuklappern.
wenn das SPIF flag gesetzt ist, bedeutet das, dass das SPDR register wieder beschrieben werden kann. wenn ich mich recht entsinne dann ist dieses register double buffered, das heisst, die daten werden erst an ein andere register übergeben und dann an den ausgang geschiftet. wenn diese register übertragung fertig ist, wird das SPIF bit gesetzt.
Hi! So jetzt habe ich ein paar Änderungen am Stil des Codes vorgenommen. @Simon: Wie meinst du deinen Vorschlag genau? War mir nicht ganz sicher ob ich die Interrupts jetzt komplett raus nehmen soll oder nicht und hab sie deshalb nochmal drinne gelassen. Jetzt habe ich aber das Problem, dass nur noch 2 Bits gesendet werden und danach das SPIF gesetzt wird. Ich habe den geänderten Code dran gehangen damit ihr vielleicht mal drübergucken könnt und mir sagen könnt was ich denn falsch mache. Oder wenns bei euch funktioniert kann mir dann vielleicht mal jemand Code von sich schicken? Danke!
Sturheit siegt nicht immer. Prozessoren sind immer sturer als der Programmierer. Wenn schon die o.A. Zeile nicht stimmt, kann PORTB |= ~(1 << 4); auch nicht besser sein. Versuch mal zu verstehen, was das bedeutet. Wenn du das SPI ja ohnehin komplett initialisieren musst, warum tust du das nicht einfach mit SPCR = ... anstelle von SPCR |= ... Könnte auch sinnvoll sein, bei der Initialisierung das SPIF zurückzusetzen.
Es empfiehlt sich generell, erst die Kiste samt I/O zu initialisieren, und danach die Interrupts einzuschalten.
@A.K. : Naja das mit dem Verstehen is so ne Sache, ich benutze das AVR-GGC Tutorial. Und da wird mit "|=" gesetzt und mit "&=" gelöscht. Hab aber keine Ahnung warum. Ich hab das einfach mal akzeptiert. Ok, dass mit den Interrupts werde ich ändern. Danke
Warum verwendest du dann den Operator für's setzen um zu löschen? Und ich kann nur dringend empfehlen, den Hintergrund dieser Operatoren zu lernen. Also was ist "|", was ist "|=" usw. Völliger Blindflug, ohne diese Grundlagen, da wird das garantiert nichts. Und nervt über kurz oder lang diejenigen du hier fragst.
Übrigens wird nicht mit "&=" gelöscht, sondern mit "&= ~". Nur so als Hinweis... A.K. hat schon den richtigen Hinweis gegeben: Guck dir mal die Bit-Manipulationsmethoden in C an...
OK, also ich habe eben nochmal die Interruptabfrage weggelassen und softwaremäßig das Setzen den SPIF festgestellt. Danach hat er alle 8 Bits einwandfrei ausgegeben. Allerdings ist er danach nicht mehr aus der Schleife herausgesprungen. Desweiteren habe ich ja keine Möglichkeit den SPIF zu löschen da es sich ja um ein nur Leseregister handelt. Danach habe ich die Interruptsteuerung wieder reingenommen und der SPIF wurde wieder nach 2 Bitübertragungen gesetzt. Mein Problem besteht nun also darin, das der Interrupt zu früh gesetzt wird. Warum?
@ Dirk: So, hier ist der aktuelle Code. Also wie ich gemerkt habe, funktioniert das SPI Interface einwandfrei (ohne Interrupts - dann kann der SPIF aber nicht mehr gelöscht werden), nur wird halt der SPIF schon nach 2 übertagenen Bits gesetzt. Das ist mein ganzes Problem. Und ich hab echt keine Ahnung was ich da machen soll.
SPIF wird gelöscht, sobald es 1 war und SPSR gelesen wurde.
>SPCR |= (1 << 4) | (1 << 3) | (1 << 7) | (1 << 6);
Lass das "|" weg und schreib statt der Ziffern lieber die Makro-Namen
für die Register-Bits hin (die stehen in der .h-Datei (Header-Datein)),
dann ist der Ausdruck lesbarer.
Dann solltest du´"/SS" erst zum Sendebeginn auf L-Pegel setzen, nicht
schon bei der initialisierung.
Manchmal ist es auch sinnvoller erst das PORT-Register zu beschreiben
und dann das Datadirection-Register.
Hallo! Ich habe den "Fehler" gefunden! Das SPI hat die ganze Zeit über schon korrekt gearbeitet. Da ich aber mit dem Software Simulator vom Studio habe ich immer wenn eine Bedingung in der Schleife war, nie gesehen das er beim abarbeiten der Befehle mit den entsprechenden Takten ja auch immer die Bits aus dem Datenregister rasuschiebt. Das habe ich aber wegen der zu schnellen Einstellung des Sendetaktes nicht gesehen. Tut mir leid - war mein Fehler. Aber danke trotzdem für eue Hilfe!
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.