mikrocontroller.net

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


Autor: Michel Niemetz (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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!

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Michel Niemetz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Lokko (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Michel Niemetz (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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!

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: A.K. (Gast)
Datum:

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

Autor: Michel Niemetz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Michel Niemetz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

zeig nochmal dein aktuellen Code bitte.

Gruß,

Dirk

Autor: Michel Niemetz (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Michel Niemetz (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.