SPI zwischen zwei ATMega8

OP #4317394
Lesenswert?

Hi Leute!
Ich wollte für meine Studenten ein kleines Labor aufziehen, in dem sie 
zwei ATMega8 per SPI verbinden und vom Master zum Slave Signale zum 
schalten von LEDs senden. Nur leider funktioniert das bei mir nicht so 
ganz, finde den Fehler einfach nicht.

Vorgehensweise:
SPI-Master und SPI-Slave initialisieren, vom Master per Timer-Interrupt 
jede Sekunde 0x00 bzw. 0xFF senden. Diese vom Slave empfangen, 
interpretieren und entsprechend LEDs schalten.

Laut Oszi kommt aus dem Master Takt, SS und Daten raus. Mein Slave 
scheint zumindest ein erstes Mal zu funktionieren, die zwei LEDs zur 
Anzeige leuchten. Nur leider schalten sie sich nicht wieder ab, obwohl 
der Master laut Kontroll-LED und Oszi 0x00 verschickt. Vielleicht kann 
mir einer von euch helfen, kann nicht so kompliziert sein SPI auf einem 
ATMega ans laufen zu bekommen ^^

Source Code liegt bei...
Angehängte Dateien:
#4317443
Lesenswert?

Marcel D. schrieb:
>> PORTB &= ~(1<<PB2);
> Wow, da war ich wohl Betriebsblind! Muss natürlich negierte Verundung
> sein.
> Dennoch kam laut Oszi ein vernünftiges Slave Select heraus, da muss noch
> was Anderes im argen liegen...

Da liegt nichts im Argen.
WIe weiter oben schon geschrieben. Der zweite Toggler funktioniert ja. 
Nur kommt der dann eben NACH der SPI Übertragung.

Kurz gesagt: du gibst dem anderen µC den Slave Select erst mal, nachdem 
alles vorbei ist. Dann überträgst du das nächste Datenbyte, welches auch 
wirklich übertragen wird. An dessen Ende toggelst du den Pin wieder, 
womit der Slave wieder abgeschaltet wird. DIe darauffolgende Übertragung 
geht wieder ins leere.

usw. usw. Dein Slave ist nur bei jedem 2.ten Byte selektiert. Und da du 
nur 2 verschiedene Bytes überträgst, kriegt der Slave immer dasselbe.

Das was mir jetzt noch auf der Zunge liegt, behalte ich erst mal für 
mich.
#4317455
Lesenswert?

Das ist auch Quatsch
1
void init_master()
2
{
3
...
4
  SPCR = (1<<7) | (1<<6) | (1<<4);      //Aktiviere SPI,SPI Interrupt und SPI Master
5

6
...
7

8
void master_transmit (uint8_t spi_data) {
9
....
10
  SPDR = spi_data;            //Schreiben der Daten
11

12
   while(!(SPSR & (1<<SPIF)));    // Warte auf verschicken des 
13
Bytes
14
....
15

16
ISR(SPI_STC_vect)
17
{  spi_flags = SPSR;      //Clear Register
18
}

wenn du die Interrupt Behandlung frei gibst, dann musst du alles über 
den Interrupt abwickeln. Mischen geht dann nicht mehr. Das folgt ganz 
klar daraus, wie Interrupts auf einem AVR funktionieren und das das 
jeweilige Interrupt aufgetreten Flag bei fast allen Interrupts mit dem 
Eintritt in die ISR automatisch gelöscht wird.


Was sagtest du? Für deine Studenten?
Wie wärs wenn du selbst erst mal die Grundlagen lernst
(Sorry, aber spätestens jetzt kann ich mich nicht mehr zurückhalten)
#4317645
Lesenswert?

A. K. schrieb:
> Mathias O. schrieb:
>> Innerhalb von Nullen, Nullen zu schieben ist schon seltsam.
>
> Kann zwecks Dokumentation sinnvoll sein:
>
1
> UCSRA = 1<<TXC | 0<<U2X | 0<<MPCM;
2
> UCSRB = 0<<RXCIE | 0<<TXCIE | 0<<UDRIE | 0<<RXEN | 1<<TXEN | 0<<UCSZ2;
3
> UCSRC = 1<<URSEL | 0<<UMSEL | 1<<UPM1 | 0<<UPM0 | 0<<USBS | 1<<UCSZ1 | 
4
> 1<<UCSZ0 | 0<<UCPOL;
5
>
Dafür gibts Kommentare.
Und ich kann es irgendwie nicht glauben, dass du es so z.B. machst.
#4317888
Lesenswert?

A. K. schrieb:
> Mathias O. schrieb:
>> Dafür gibts Kommentare.
>
> Das sind gewissermassen Kommentare. Aber warum sollte ich hier Nullen
> und Einsen händisch sortieren, die Guten ins Töpfchen, die schlechten
> ins Kröpfchen?
>
>> Und ich kann es irgendwie nicht glauben, dass du es so z.B. machst.
>
> Was spricht konkret dagegen?

Es spricht dagegen dass hier suggeriert wird, ein Bit werde auf 0 
gesetzt. Aber so ist es ja nicht. Es passiert gar nichts. Man verlässt 
sich also darauf dass das Bit bereits 0 ist. Genau DAS wird aber eben 
nicht deutlich. Fasse ich das Bit gar nicht an, so ist klar, das Bit hat 
nach wie vor den Defaultwert. Hier sieht es auf den ersten Blick aber so 
aus, als werde mit dem Bit etwas getan. Das ist ein ganz klarer Verstoß 
gegen jede wie auch immer geartete Clean-Code Regel.
#4317901
Lesenswert?

S. Landolt schrieb:
>> Es spricht dagegen dass hier suggeriert wird...
> Aber doch nur dem unbedarften Anfänger.

Nein, die 0 könnte jeder übersehen und stattdessen eine echte 
Schiebeoperation vermuten. Es geht ja darum Code schnell in seiner 
Funktion erfassen zu können. Diese Schreibweise macht das Gegenteil.
Manche finden es ja cool unleserlichen oder unverständlichen Code zu 
schreiben. Das Ziel sollte aber eben übersichtlicher und sauberer Code 
sein.
Aber ich glaube auch, wer keinerlei Verständnis für Clean-Code Konzepte 
hat, dem kann man es auch nur schwer erklären.
#4318093
Lesenswert?

Justus S. schrieb:
> Cyblord -. schrieb:
>> Man verlässt
>> sich also darauf dass das Bit bereits 0 ist.
>
> nein tut man nicht, und es ist auch völlig egal, was das Bit vorher
> ist/war...

Warum das? Wenn das Bit seinen Zustand nicht verändert musst du den 
vorherigen Zustand wissen um den aktuellen Zustand zu erfahren.
Wird ein Bit dagegen wirklich auf 1 oder 0 gesetzt sieht man das im Code 
und der vorherige Zustand ist irrelevant.

Was also wird mit dieser 0 Schieberei dem Leser jetzt genau 
dokumentiert? Was darf man daraus schließen wenn man das liest?
#4318701
Lesenswert?

A. K. schrieb:
> Cyblord -. schrieb:
>> Es spricht dagegen dass hier suggeriert wird, ein Bit werde auf 0
>> gesetzt. Aber so ist es ja nicht. Es passiert gar nichts.
>
> Bei
>   UCSRA = 1<<TXC | 0<<U2X | 0<<MPCM;
> werden keine Nullen geschrieben? Dann solltest du dein Exemplar
> auswechseln, es ist kaputt.

Ja ist ja gut. Bei einer einfachen Zuweisung mag das stimmen. Aber 
sobald jemand
1
UCSRA |= 1<<TXC | 0<<U2X | 0<<MPCM;

schreibt trifft das nicht mehr zu. Das ganze Konzept ist einfach 
gefährlich uneindeutig.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren