Forum: Mikrocontroller und Digitale Elektronik SPI gibt lediglich 4 Bits aus!


von Michel Niemetz (Gast)


Angehängte Dateien:

Lesenswert?

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!

von Simon K. (simon) Benutzerseite


Lesenswert?

"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

von Michel Niemetz (Gast)


Lesenswert?

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?

von A.K. (Gast)


Lesenswert?

"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.

von Lokko (Gast)


Lesenswert?

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.

von Michel Niemetz (Gast)


Angehängte Dateien:

Lesenswert?

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!

von A.K. (Gast)


Lesenswert?

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.

von A.K. (Gast)


Lesenswert?

Es empfiehlt sich generell, erst die Kiste samt I/O zu initialisieren,
und danach die Interrupts einzuschalten.

von Michel Niemetz (Gast)


Lesenswert?

@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

von A.K. (Gast)


Lesenswert?

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.

von Rahul (Gast)


Lesenswert?

Ü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...

von Michel Niemetz (Gast)


Lesenswert?

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?

von Dirk (Gast)


Lesenswert?

Hi,

zeig nochmal dein aktuellen Code bitte.

Gruß,

Dirk

von Michel Niemetz (Gast)


Angehängte Dateien:

Lesenswert?

@ 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.

von Rahul (Gast)


Lesenswert?

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.

von Michel Niemetz (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.