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


von P. Waldmann (Gast)


Angehängte Dateien:

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):
1
while(!(SPSR & (1<<SPIF)));

Die Pin-Konfiguration:
1
PORTB = (1<<PINB3)|(1<<PINB5);
2
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:
1
Hauptchip        Breakout-Board
2
SCK              SCK
3
MISO             SI
4
SS               CSN
5
VCC              VCC
6
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

von Stefan E. (sternst)


Lesenswert?

Es fehlt das komplette SS-Handling.

von P. Waldmann (Gast)


Angehängte Dateien:

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"

von Stefan E. (sternst)


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

von SVD71 (Gast)


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)));
}

von ich (Gast)


Lesenswert?

Versuch mal MOSI(MasterOutSlavIn) mit MISO(MasterInSlaveOut) zu 
verbinden....

von SVD71 (Gast)


Angehängte Dateien:

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

von P. Waldmann (Gast)


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:
1
SPI_MasterTransmit(0x01);
2
SPI_MasterTransmit(0x01);
3
SPI_MasterTransmit(0x01);
4
SPI_MasterTransmit(0x01);
5
_delay_ms(3000);
6
7
SPI_MasterTransmit(0x02);
8
SPI_MasterTransmit(0x02);
9
SPI_MasterTransmit(0x02);
10
SPI_MasterTransmit(0x02);
11
_delay_ms(3000);

Allerdings gibt das eine komische Kombination:
1
0111
2
2221
3
1121
4
2122
5
2111
6
2221
7
1121
8
2122
9
2111
10
...

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:
1
0244
2
2444
3
4442
4
4424
5
4244
6
...

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/7-Segment/SFE-0012-DS-7segmentSerial-v41.pdf

von SVD71 (Gast)


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.

von P. Waldmann (Gast)


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.

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.