www.mikrocontroller.net

Forum: Compiler & IDEs SPI hängt beim Warten auf Ende der Übertragung


Autor: P. Waldmann (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

kurz vorweg: die Forensuche habe ich benutzt und eine Vielzahl an Themen 
gefunden, die allerdings mein Problem nicht lösen konnten.

Ich versuche seit einiger Zeit verzweifelt, SPI zum Laufen zu bringen, 
allerdings bleibt das Ganze beim Senden vom ersten Byte hängen.
Es sollen zwei ATMEGA328P miteinander verbunden werden, der Eine "roh", 
der Andere in einem 7-Segment-Anzeige-Breakout-Board (COM-09764 [1]).

Um genauer zu seien, ist dies hier die Zeile, in der das Ganze hängen 
bleibt meiner Vermutung nach (erkennbar durch die eingeschaltene 
Debug-LED):
while(!(SPSR & (1<<SPIF)));

Die Pin-Konfiguration:
PORTB = (1<<PINB3)|(1<<PINB5);
SPCR = ((1<<SPE)|(1<<MSTR)|(1<<SPR0)|(0<<CPOL)|(0<<CPHA));

Im Datenblatt vom COM-09764 steht, CPOL und CPHA werden als 0 benötigt.
Angeschlossen wurde das ganze wie folgt:
Hauptchip        Breakout-Board
SCK              SCK
MISO             SI
SS               CSN
VCC              VCC
GND              GND

Beim Programmieren werden vom Breakout-Board anscheinend Signale 
empfangen, da es sich wild verändert. Das Bauteil scheint also noch zu 
funktionieren. Allerdings wird beim Schreiben des ersten Bytes nichts 
verändert.

Im Anhang ist der komplette C-Code, größtenteils aus dem ATMEGA328 
Datenblatt entnommen.

Verwende SPI zum ersten Mal, also lasst bitte Gnade walten. ;-)
Wäre schön wenn jemandem einfällt, woran es liegen könnte!

[1] http://www.sparkfun.com/products/9764

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es fehlt das komplette SS-Handling.

Autor: P. Waldmann (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Danke für den Hinweis, Stefan.

Habe im Forum einen Beitrag gefunden, der mich weitergebracht hat. [1]

Ich bin mir noch nicht ganz sicher wie das Konzept von 
SlaveSelect(SS)/ChipSelect(CS) funktioniert, aber es scheint ja nicht so 
sonderlich kompliziert zu sein:
SS low sagt dem angeschlossenen Gerät sich bereitzumachen, Daten zu 
empfangen. SS high dementsprechend das Gegenteil.

Bin aber noch verwirrt von PINB2 (SS mit Dach). Eigentlich ist die 
besondere Funktion nur interessant, wenn man den Chip als Slave benutzen 
will und Daten empfangen/sich aus dem Sleep-Zustand wecken zu lassen, 
oder?
Habe im Datenblatt vom Chip zu dem SS-Pin den erklärenden Text gefunden:

> SS: Slave Select input. When the SPI is enabled as a Slave, this pin is
> configured as an input regardless of the setting of DDB2. As a Slave, the
> SPI is activated when this pin is driven low.
> When the SPI is enabled as a Master, the data direction of this pin is
> controlled by DDB2. When the pin is forced by the SPI to be an input, the
> pull-up can still be controlled by the PORTB2 bit.

D.h. ich kann einen beliebigen digitalen I/O-Pin (z.B. PINC5) nehmen, um 
damit speziell einen Slave auszuwählen?

Habe das versucht in C umzusetzen, allerdings schein ich noch einen 
Fehler drin zu haben. Der Code ist im Anhang.
Leider kommt kein Signal zurück von dem Gerät, ob ich SS low oder high 
eingestellt habe (Zeile 44).

Danke schonmal für die Hilfe. :-)



[1] Beitrag "SPI Verständnisproblem"

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
P. Waldmann schrieb:
> D.h. ich kann einen beliebigen digitalen I/O-Pin (z.B. PINC5) nehmen, um
> damit speziell einen Slave auszuwählen?

Ja, aber es ist für die Funktion als Master wichtig, dass der SS-Pin 
(PB2) auf Ausgang steht. Wenn es ein Eingang ist und er geht auf Low 
(was bei einem floatenden Eingang auch schnell von alleine passiert), 
wechselt der Master sofort in den Slave-Modus (auch mitten in der 
Übertragung).

Autor: SVD71 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ist Hauptchip im Multislave mode (Master.SS verwendet nicnt, aber 
als SS geht andere PC7), soll PB5(SS) als imput anschalten und mit VCC 
verbinden (such mal ein PDF auf atmel.com mit Suchwort "SPI").
Dazu braucht noch manipulation SPCR.MSTR.

void SPI_MasterTransmit(char cData) {

  /* Start transmission */
  SPDR = cData;

  /* Wait for transmission complete */
        SPCR &= ~(1<<MSTR);
        SPCR |= (1<<MSTR);
        SS_P &= ~(1<<SS);
  while(!(SPSR & (1<<SPIF)));
}

Autor: ich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Versuch mal MOSI(MasterOutSlavIn) mit MISO(MasterInSlaveOut) zu 
verbinden....

Autor: SVD71 (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Jetzt bin ich zuhause :-)
AVR-SPI-doc2585.pdf  - erklärung für Atmel SPI master u. Slave.
spi.c - file aus mein FrameWork. Da gibt es wichtigsten funktionen 
spi_init_mas(), spi_exch_mulslv().
spi_test_m.c - ein Beispiel, wie master schicken soll.

wichtigste noch - Verbindung ywischen Maste u. Slave:
Master.MISO - Slave.MISO
Master.MOSI - Slave.MOSI
Master.SCK  - Slave.SCK
Master. Pin als slave CS - Slave.SS
Master.SS auf VCC.


DDRB muss haben:
    Master    Slave  PIN
  MOSI  egal    input  3
  MISO  input    egal  4
  SCK  egal    input  5
  SS  egal    input  2
  -------------------------------
  Wert  0x2F    0x13

MfG

Autor: P. Waldmann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die vielen Antworten! Jetzt hab ich SPI endlich verstanden und 
es scheint teils zu funktionieren.

Die 7-Segment Anzeige scheint Signale entgegenzunehmen, da sie sich bei 
fast jedem Signal verändert. Irgendwie ist das ganze allerdings noch ein 
bisschen komisch, weil ich es nicht richtig kontrollieren kann.

Im Datenblatt vom COM-09764 [1] steht, dass man Sonderbefehle in 
2-Byte-Paketen verschicken soll, Zeichen hingegen in 4-Byte-Paketen.

Ich versuche also 4 Mal hintereinander über SPI Pakete etwas zu 
verschicken:
SPI_MasterTransmit(0x01);
SPI_MasterTransmit(0x01);
SPI_MasterTransmit(0x01);
SPI_MasterTransmit(0x01);
_delay_ms(3000);

SPI_MasterTransmit(0x02);
SPI_MasterTransmit(0x02);
SPI_MasterTransmit(0x02);
SPI_MasterTransmit(0x02);
_delay_ms(3000);

Allerdings gibt das eine komische Kombination:
0111
2221
1121
2122
2111
2221
1121
2122
2111
...

Habe bei verschiedenen Kombinationen immer noch nichts herausgekriegt 
und werde daraus auch nicht schlau. Wenn ich z.b. bei beiden Parts (vor 
den Pausen) jeweils 0x01, 0x02, 0x03, 0x04 verschicke bekomm ich 
folgendes Muster:
0244
2444
4442
4424
4244
...

Könnte das eventuell mit der BAUD-Rate oder anderen Sachen, die mit 
Timing und Kommunikation zu tun haben zusammenhängen?

[1] 
http://www.sparkfun.com/datasheets/Components/LED/...

Autor: SVD71 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hi,
"The maximum speed of the SPI clock input is 250kHz.
The display is configured to use SPI mode 0 (CPOL =
0, CPHA = 0), so the clock line should idle low and
data is sampled on the rising edge."

Schau mal Datenblatt für dein Hauptkontroller. Da gibt es Information 
über SPSR u. SPCR register. Im SPSR gibt es paar Bits welche 
Haupkontrollertaktfrequez für SCK dividieren kann.

Autor: P. Waldmann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke, SVD71, das war mein Fehler.

Habe nun (1<<SPR0) geändert auf (1<<SPR1) also SCK-Frequenz von F_osc/16 
auf F_osc/64 geändert.

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.