Forum: Compiler & IDEs SPI am ATmega128


von Lukas S. (irre)


Angehängte Dateien:

Lesenswert?

Hallo Zusammen,

ich kämpfe mal wieder mit der SPI-Schnittstelle.
Mein Ziel ist es, zwei MCU miteinander zu verbinden. Einer läuft als 
Master, einer als Slave. Beim Master läuft soweit alles gut. Nur beim 
Slave gibt es merkwürdige Probleme:

Zur Fehleranalyse lasse ich immer eine LED aufleuchten und verschiebe 
diese Routine zum aufleuchten lassen immer im Code umher, bis ich die 
kritische Stelle gefunden habe.
Es scheint, als würde sich der µC immer am Ende der SPI_SlaveInit() 
aufhängen. Das seltsame ist jedoch, dass wenn ich die Testroutine am 
Ende von SPI_SlaveInit() ansetze, die LED aufleuchtet, doch wenn ich sie 
im MAIN-Code direkt hinter dem Aufruf von SPI_SlaveInit() ansetze, die 
LED eben nicht aufleuchtet. Klingt irgendwie nach nem Interrupt der 
ausgelöst wird und den µC zum Reset zwingt, aber Interrupts hab ich 
nicht aktiviert.

Hoffe ihr könnt mir weiterhelfen.

LG
Lukas

von J.-u. G. (juwe)


Lesenswert?

Lukas S. schrieb:
> doch wenn ich sie
> im MAIN-Code direkt hinter dem Aufruf von SPI_SlaveInit() ansetze, die
> LED eben nicht aufleuchtet.

Ich sehe in Deinem Code keine Anweisung zum Anschalten einer LED, d.h. 
keine Anweisung, irgendeinen Portpin auf "High" zu schalten.

Das hier:
1
DDRA|=1<<2;
setzt lediglich den Portpin PA2 auf Ausgang.

Das Kommando um diesen auf "High" zu schalten lautet:
1
PORTA |= (1<<PA2);

von Lukas S. (irre)


Lesenswert?

J.-u. G. schrieb:
> Ich sehe in Deinem Code keine Anweisung zum Anschalten einer LED, d.h.
> keine Anweisung, irgendeinen Portpin auf "High" zu schalten.

Die LEDs sind so geschaltet, dass sie genau dann leuchten, wenn ihr PIN 
auf Low ist. Da alle PINS nach einem PowerUp auf Low sind, kann ich mir 
folgende Codesequenz sparen.
1
PORTA&=~_BV(PA2);

von Stefan E. (sternst)


Lesenswert?

Lukas S. schrieb:
> Es scheint, als würde sich der µC immer am Ende der SPI_SlaveInit()
> aufhängen. Das seltsame ist jedoch, dass wenn ich die Testroutine am
> Ende von SPI_SlaveInit() ansetze, die LED aufleuchtet, doch wenn ich sie
> im MAIN-Code direkt hinter dem Aufruf von SPI_SlaveInit() ansetze, die
> LED eben nicht aufleuchtet.

M103C Fuse noch aktiv?

von MWS (Gast)


Lesenswert?

Hmm, auf gesetztes SPIF testen und nur wenn gesetzt die 
Flaglöschensequenz ausführen ?

von Lukas S. (irre)


Lesenswert?

Stefan Ernst schrieb:
> M103C Fuse noch aktiv?

Wieder was gelernt. Jip war noch aktiv. Danke

MWS schrieb:
> Hmm, auf gesetztes SPIF testen und nur wenn gesetzt die
> Flaglöschensequenz ausführen ?

hab das mal folgendermaßen umgesetzt:
1
void SPI_SlaveInit()
2
{
3
  // set MISO output, all other input
4
  DDR_SPI=(1<<DD_MISO);
5
  // enable SPI
6
  SPCR=(1<<SPE);
7
  // clear SPI Interrupt Flag by reading SPSR and SPDR
8
  if (SPSR&(1<<SPIF))
9
  {
10
    uint8_t c=SPSR;
11
    c=SPDR;
12
    DDRA|=1<<2;
13
  }
14
}

Aber nach erfolgter Übertragung sollte ja das SPIF gesetzt werden... 
scheint aber nicht zu erfolgen...
Bin ja jetzt nach Deaktivieren des M103C paar Steps weiter.. jetzt hängt 
es hier:
1
uint8_t SPI_SlaveReceive(void)
2
{
3
  // wait for reception complete
4
  while (!(SPSR&(1<<SPIF)))
5
    ;  
6
  return SPDR;
7
}

also beim pollen. Die Übertragung findet aber sinngemäß statt, hab das 
mit nem LogicAnalyzer überprüft...

Habt ihr ne Idee wo hier das Problem sein könnte?

Danke schonmal!

von Karl H. (kbuchegg)


Lesenswert?

Lukas S. schrieb:

> void SPI_SlaveInit()
> {
>   // set MISO output, all other input
>   DDR_SPI=(1<<DD_MISO);
>   // enable SPI
>   SPCR=(1<<SPE);
>   // clear SPI Interrupt Flag by reading SPSR and SPDR
>   if (SPSR&(1<<SPIF))
>   {
>     uint8_t c=SPSR;
>     c=SPDR;
>     DDRA|=1<<2;
>   }
> }[/c]
>
> Aber nach erfolgter Übertragung sollte ja das SPIF gesetzt werden...
> scheint aber nicht zu erfolgen...

Du sagst es.
Aber nach der Initialisierung wurde ja noch nichts übertragen. Daher ist 
in diesem Fall das SPIF nicht gesetzt.

(Ja ich weiß. Man kommt leicht in Versuchung das SPIF Bit als eine Art: 
die SPI ist jetzt frei und benutzbar anzusehen. Nur stimmt diese Sicht 
leider nicht. Nachdem SPI eingeschaltet wurde, ist sie frei und 
benutzbar, aber trotzdem ist SPIF nicht gesetzt. Das wird dann erst nach 
der ersten Übertragung gesetzt.

von Lukas S. (irre)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Du sagst es.
> Aber nach der Initialisierung wurde ja noch nichts übertragen.

Die Daten kommen von einer anderen MCU, welche mit der auskommentierten 
Codesequenz aus der Main-Routine bespielt ist. Die Übertragung 
funktioniert nach Vorschrift.

von Gerhard G. (g_g)


Lesenswert?

Hallo,

ich habe meine zwei Atmega128 auch über SPI verbunden.

SPSR = 0x00; //Status-Register einfach beim Init einmal überschreiben !


void SPI_SlaveInit(void)
{

DDRB |= (1 << SPI_MISO)  ; //MISO Ausgang
SPCR = (1 << SPE)  ; // Slave enable

SPSR = 0x00; // Status-Register einfach einmal überschreiben !!!!

}

dann sollte es funktionieren.

von Lukas S. (irre)


Angehängte Dateien:

Lesenswert?

Danke für die Antwort, ich habs ausprobiert und es zeigt sich leider 
keine Veränderung. Hab im Anhang mal nen Bild vom LogicAnalyzer.

Das Programm des Slaves fragt ab, ob eine 0x73 gesendet wurde und soll 
dann eigentlich eine LED aufleuchten lassen.

Im Bild sieht man, dass der Ringspeicher bereits die 0x73 erfolgreich 
eingelesen hat, nachdem ich den Befehl mehrmals übermittelt habe. Doch 
besteht weiterhin das Problem, dass SPIF nicht gesetzt wird und ich 
somit aus dem Pollen nicht rauskomme und im SPI_SlaveReceive() 
hängenbleibe... =/

Hab bereits die MCU ausgetauscht(M103C Fuse deaktiviert), aber das hat 
auch keine Veränderung hervorgerufen...

von Gerhard G. (g_g)


Angehängte Dateien:

Lesenswert?

Hallo,

schau dir mal meinen Code im Anhang an.

Verwende AVR Studio 6


Gruß G.G.

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.