SPI zwischen zwei AtMega8

OP #4938136
Lesenswert?

Hallo Liebe Forumgemeinde,

nachdem ich mich mit etlichen Tutorials und Infoblatt vom Atmel 
durchgeforstet habe versuche ich mal jetzt von euch ein wenig Hilfe zu 
bekommen.

Es geht wie im Betreff schon geschrieben um die Datenübertragung 
zwischen zweier ATMega8 anhand der Nutzung von SPI.

Ich erkläre erstmal was ich rausgefunden habe und falls es nicht richtig 
sein soll bitte ich um Korrektur.

Also SPI Kommunikation findet zwischen Master & Slave statt und dabei 
müssen die MISO, MOSI und SCK Pins miteinander verbunden werden?

MISO und MOSI sind die Datenkanäle.
Über SCK wird der Taktsignal übertragen und je nach eingestellem Modus 
wird erst bei eine steigende (auf HIGH) oder fallende (auf LOW) 
Taktflanke der Zustand vom MISO/MOSI beim Empfänger/Sender gelesen oder 
halt geschrieben.

Die Datenübertragung beginnt immer dann wenn SS von HIGH auf LOW gesetzt 
wird. Erst wenn SS auf LOW gezogen ist kann die Übertragung starten.

CPOL und CPHA sind Bits die ich setzen muss um die o.g. Modus 
einzustellen. Soweit ich das verstanden habe sieht es folgendermaßen 
aus.

CPOL = 0 , CPHA = 0 : Bit wird bei steigender Taktflanke übertragen
CPOL = 0 , CPHA = 1 : Bit wird bei fallender Taktflanke übertragen
CPOL = 1 , CPHA = 0 : Bit wird bei fallender Taktflanke übertragen
CPOL = 1 , CPHA = 1 : Bit wird bei steigender Taktflanke übertragen

Je nachdem ob es bei fallender oder steigender Taktflanke übertragen 
wird, wird das Bit bei gegensätziger Taktflanke geschoben (Shift). Ich 
habe mir darüber keine Gedanken gemacht, bei welcher Taktflanke gelesen 
oder geschoben wird...


Nun stellt sich für mich die Frage: Auf dem folgenden Atmel Datenblatt 
über SPI: 
http://www.atmel.com/Images/Atmel-2585-Setup-and-Use-of-the-SPI_ApplicationNote_AVR151.pdf

steht das weiter unten auch so geschrieben, wie ich es erklärt habe...

Weiter oben ist aber in der Zeichnung (Figure 1 - 1 Master and slave 
interface) Master und Slave so beschaltet, dass der Master sein SS PIN 
auf VCC und der Slave sein SS PIN auf GND schaltet.

Wie soll laut dieser Zeichnung der Master den SS Pin auf LOW setzen 
damit eine Übertragung beginnt?

Desweiteren stand im Datenblatt übersetzt: 'Master generiert nur dann 
Taktsignale wenn es Daten sendet. Dies bedeutet, dass der Master Daten 
an den Slave senden muss um Daten vom Slave zu bekommen.' Da musste ich 
kurz überlegen warum aber dachte mir okay, dann schicke ich den einfach 
lauter nullen, wenn nichts anliegt.

So hatte ich das vor:
1
            Master        Slave
2
SCK         OUTPUT        INPUT
3
MISO        INPUT         OUTPUT
4
MOSI        OUTPUT        INPUT
5
SS          OUTPUT        INPUT

Nachdem ich die beiden Mega8 mit den jeweiligen PINS aneinander 
angeschlossen habe (SCK - SCK , MISO - MISO, MOSI - MOSI, SS - SS) muss 
ich ja die Master und Slave Seite wie oben erklärt erstmal 
Konfigurieren:

MASTER:
1
 
2
void spiInitMaster(){
3
    DDRB |= ((1<<PB5)|(1<<PB3)|(1<<PB2)); //SCK, MOSI, SS als output
4
    DDRB &= ~(1<<PB4); // MISO als INPUT, wobei muss ich ja nicht mehr machen?
5
                       // da es schon standart so als INPUT ist oder?
6
    /* Enable SPI, Master, set clock rate fck/16 */
7
    SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<CPOL0)|(1<<CPOL1);
8

9
}
10

11
unsigned char SPI_MasterTransmit(char cData) {
12
    /* Start transmission */
13
    SPDR = cData;
14
    /* Wait for transmission complete */ 
15
    while(!(SPSR & (1<<SPIF))); 
16
    return SPDR;
17
}

SLAVE:
1
 
2
void spiInitSlave(){
3
    DDRB |= (1<<PB4); // MISO als OUTPUT rest kann ja standartmäßig so bleiben
4
    /* Enable SPI, Master, set clock rate fck/16 */
5
    SPCR = (1<<SPE);
6

7
}
8

9
unsigned char spiSlaveTransmit(char cData) {
10
    /* Start transmission */
11
    SPDR = cData;
12
    /* Wait for transmission complete */ 
13
    while(!(SPSR & (1<<SPIF))); 
14
    return SPDR;
15
}



Die Programmcodes die Ihr oben sieht habe ich aus dem kompletten 
Datenblatt der Mega8 (vllt. ein wenig optimiert).

Nun erkläre ich euch mal in PSEUDOCODE wie ich vorgehen wollte:
1
SOLANGE !WELTUNTERGANG :
2
MASTER & SLAVE rufen ihre spiInit... Methoden auf
3
SLAVE überwacht SS PIN und wartet auf ein LOW Signal
4
MASTER will senden
5
MASTER setzt SS PIN auf LOW
6
MASTER ruft SPI_MasterTransmit auf 
7
SLAVE bekommt den LOW Signal an SS PIN mit und ruft spiSlaveTransmit auf
8
MASTER & SLAVE Warten bis Datenübertragung zuende ist
9
MASTER setzt den SS PIN auf HIGH
10
MASTER & SLAVE können die empfangenen Daten verarbeiten


Ich bedanke mich bei allen, die alles durchgelesen haben und mir 
versuchen werden zu helfen :)
Gast #4939293
Lesenswert?

Sercan S. schrieb:
> Keiner Ideen?

Soweit uch das auf die Schnelle überblicke machst du alles
richtig bis auf:

Sercan S. schrieb:
> SLAVE bekommt den LOW Signal an SS PIN mit und ruft spiSlaveTransmit auf

bzw.
1
Sercan S. schrieb im Beitrag #4938136:
2
unsigned char spiSlaveTransmit(char cData) {
3
    /* Start transmission */
4
    SPDR = cData;
5
    /* Wait for transmission complete */
6
    while(!(SPSR & (1<<SPIF)));
7
    return SPDR;
8
}

Der Slave muss nicht explizit einen "Receive-Transmit" starten da
er vom Master selbständig die Daten hereingeclockt bekommt.
Im Slave musst du nur per Status-Flag abwarten (ich glaube es
kommt nur das Interrupt-Flag in Frage) bis das SPI-Datenregister
voll ist, dann kannst du es z.B. mit
1
value = SPDR;

einfach abholen.

Sercan S. schrieb:
> Weiter oben ist aber in der Zeichnung (Figure 1 - 1 Master and slave
> interface) Master und Slave so beschaltet, dass der Master sein SS PIN
> auf VCC und der Slave sein SS PIN auf GND schaltet.

Das ist wohl ein Irrtum vom Amt.
OP #4939347
Lesenswert?

Endlich eine Antwort, ich hatte schon langsam die Hoffnung aufgegeben 
und habe mir wahrscheinlich 1000 weitere Tutorials & Infos über SPI 
gelesen.

Was meinst du genau mit den Status-Flag abwarten. Also mir ist bewusst, 
dass es wie ein Schieberegister funktioniert und es 8-Bits 
'rübergeclockt' werden müssen. Aber wie gehe ich dabei vor? Wie Prüfe 
ich das? Muss ich die Taktflanken beim SCK zählen und bei 8 steigenden 
Taktflanken (8-Bits, kamen rein) versuchen zu lesen, weil dann genau ein 
Byte reingekommen ist?

Ich bin echt überfordert, da es alle in den Tutorials mit Ihren Arduinos 
ohne Probleme hinbekommen und bin echt Froh, dass da mal ein Antwort 
reingekommen ist... :)



SPISpezialist schrieb:
> Sercan S. schrieb:
>> Keiner Ideen?
>
> Soweit uch das auf die Schnelle überblicke machst du alles
> richtig bis auf:
>
> Sercan S. schrieb:
>> SLAVE bekommt den LOW Signal an SS PIN mit und ruft spiSlaveTransmit auf
>
> bzw.Sercan S. schrieb:
> unsigned char spiSlaveTransmit(char cData) {
>     /* Start transmission */
>     SPDR = cData;
>     /* Wait for transmission complete */
>     while(!(SPSR & (1<<SPIF)));
>     return SPDR;
> }
>
> Der Slave muss nicht explizit einen "Receive-Transmit" starten da
> er vom Master selbständig die Daten hereingeclockt bekommt.
> Im Slave musst du nur per Status-Flag abwarten (ich glaube es
> kommt nur das Interrupt-Flag in Frage) bis das SPI-Datenregister
> voll ist, dann kannst du es z.B. mit
> value = SPDR;
>
> einfach abholen.
>
> Sercan S. schrieb:
>> Weiter oben ist aber in der Zeichnung (Figure 1 - 1 Master and slave
>> interface) Master und Slave so beschaltet, dass der Master sein SS PIN
>> auf VCC und der Slave sein SS PIN auf GND schaltet.
>
> Das ist wohl ein Irrtum vom Amt.
Gast #4939362
Lesenswert?

Sercan S. schrieb:
> Was meinst du genau mit den Status-Flag abwarten.

Das SPI-Statusregister (SPSR) hat ein Interrupt-Flag (Bit 7)
welches (im Slave Mode) gesetzt wird wenn ein vollständiges
Byte vom Master hereingekommmen ist. Siehe Datenblatt Seite 130.

Du musst dafür keinen Global Interrupt Enable machen (sei()),
das Flag wird immer bei Gegebenheit gesetzt.
OP #4939372
Lesenswert?

> Das SPI-Statusregister (SPSR) hat ein Interrupt-Flag (Bit 7)
> welches (im Slave Mode) gesetzt wird wenn ein vollständiges
> Byte vom Master hereingekommmen ist. Siehe Datenblatt Seite 130.
>
> Du musst dafür keinen Global Interrupt Enable machen (sei()),
> das Flag wird immer bei Gegebenheit gesetzt.

Bevor du wieder verschwindest, sende ich am besten mal mein Code beider 
Seiten vielleicht entdeckst du ja etwas, was mir entgeht oder was ich 
komplett falsch mache.


Master-Vollständig
1
#define F_CPU 8000000UL
2
#include <asf.h>
3
#include <avr/io.h>
4
#include <util/delay.h>
5

6
char send = '1';
7
float increment = 0.0;
8
bool ledOn = false;
9
void SPI_MasterInit(void) {
10
  /* Set MOSI and SCK output, all others input */
11
  DDRB = (1<<PB5)|(1<<PB3) |(1<<PB2);
12
  PORTB |= (1<<PB2);
13
  /* Enable SPI, Master, set clock rate fck/16 */
14
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
15
}
16
void SPI_MasterTransmit(char cData) {
17
  /* Start transmission */
18
  PORTB &= (1<<PB2);
19
  SPDR = cData;
20
  /* Wait for transmission complete */ 
21
  while(!(SPSR & (1<<SPIF)))
22
  PORTB |= (1<<PB2);
23
; }
24

25
int main (void)
26
{
27
  /* Insert system clock initialization code here (sysclk_init()). */
28

29
  board_init();
30
  // Timer 0 konfigurieren
31
  TCCR0 = (1<<CS00);       // Start Timer 0 with prescaler 1024
32
  TIMSK |= (1<<TOIE0) /*| (1<<TOIE2)*/;               // Enable Timer 0 overflow interrupt
33
  sei();
34
  DDRD = (1<<PD0);
35
  //PORTD |= (1<<PD0);
36
  //SPI_MasterInit();
37

38
  while(1){
39
    
40
  }
41
  /* Insert application code here, after the board has been initialized. */
42
}
43

44
ISR(TIMER0_OVF_vect)
45
{
46
  
47
  increment += 0.0000255;
48
  
49
  if(increment>=2){
50
    PORTD |= (1<<PD0);
51
    SPI_MasterTransmit(send);
52
    
53
    increment -= 2;
54
    if(ledOn){
55
      PORTD &= ~(1<<PD0);
56
      ledOn = false;
57
    }else{
58
      PORTD |= (1<<PD0);
59
      ledOn = true;
60
    }
61
    
62
    
63
  }
64
}


Slave Vollständig:
1
int digits[4] = {0,0,0,0};
2
int totalSum = 0;
3
int multiplexCount = 0;
4
int multiplexInterval = 2;
5
int digitOnTurn = 1;
6
float increment = 0.0;
7
bool dataReceived = false;
8
int digitSegments[10][7] = {  {1,1,1,1,1,1,0}, // 0
9
{0,1,1,0,0,0,0}, // 1
10
{1,1,0,1,1,0,1}, // 2
11
{1,1,1,1,0,0,1}, // 3
12
{0,1,1,0,0,1,1}, // 4
13
{1,0,1,1,0,1,1}, // 5
14
{1,0,1,1,1,1,1}, // 6
15
{1,1,1,0,0,0,0}, // 7
16
{1,1,1,1,1,1,1}, // 8
17
{1,1,1,1,0,1,1}  // 9
18
};
19
char test = 0;
20
void SPI_SlaveInit(void) {
21
  /* Set MISO output, all others input */
22
  DDRB = (1<<PB4);
23
  /* Enable SPI */
24
  SPCR = (1<<SPE);
25
}
26
char SPI_SlaveReceive(void) {
27
  /* Wait for reception complete */ 
28
  while(!(SPSR & (1<<SPIF)));
29
  /* Return data register */ 
30
  return SPDR;
31
}
32
void updateDigits(){
33
  
34
  //int sumInDigits = totalSum*100; TOTALSUM UND ALLE ANDEREN SUMMEN WERDEN ALS INTEGER OHNE KOMMA GESPEICHERT. DAHER KANN MAN TOTALSUM DIREKT NEHMEN
35
  
36
  digits[0] = (totalSum - (totalSum % 1000)) / 1000;
37
  digits[1] = (totalSum - (totalSum % 100) - digits[0] * 1000 ) / 100;
38
  digits[2] = (totalSum - (totalSum % 10) - digits[1] * 100 - digits[0] * 1000) / 10;
39
  digits[3] = totalSum % 10;
40
}
41

42
//{a,b,c,d,e,f,g}
43
void changeSegmentStatus(int segment[7]){
44
  PORTD &= ~((1<<PD0) | (1<<PD1) | (1<<PD2) | (1<<PD3) | (1<<PD4) | (1<<PD5) | (1<<PD6));
45
  if(segment[0] == 0){
46
    PORTD |= (1<<PD0);
47
    }if(segment[1] == 0){
48
    PORTD |= (1<<PD1);
49
    }if(segment[2] == 0){
50
    PORTD |= (1<<PD2);
51
    }if(segment[3] == 0){
52
    PORTD |= (1<<PD3);
53
    }if(segment[4] == 0){
54
    PORTD |= (1<<PD4);
55
    }if(segment[5] == 0){
56
    PORTD |= (1<<PD5);
57
    }if(segment[6] == 0){
58
    PORTD |= (1<<PD6);
59
  }
60
  
61
}
62
void changeDigitToOnAndOthersOff(int digit){
63
  if(digit == 1){
64
    PORTC |= (1<<PC0);
65
    PORTC &= ~((1<<PC1) | (1<<PC2) | (1<<PC3));
66
    }else if(digit == 2){
67
    PORTC |= (1<<PC1);
68
    PORTC &= ~((1<<PC0) | (1<<PC2) | (1<<PC3));
69
    }else if(digit == 3){
70
    PORTC |= (1<<PC2);
71
    PORTC &= ~((1<<PC0) | (1<<PC1) | (1<<PC3));
72
    }else if(digit == 4){
73
    PORTC |= (1<<PC3);
74
    PORTC &= ~((1<<PC0) | (1<<PC1) | (1<<PC2));
75
  }
76
}
77

78
void multiplexDigits(){
79
  
80
  if(multiplexCount>=multiplexInterval){
81
    changeDigitToOnAndOthersOff(digitOnTurn);
82
    changeSegmentStatus(digitSegments[digits[digitOnTurn-1]]);
83
    if(digitOnTurn==4){
84
      digitOnTurn = 1;
85
      }else{
86
      digitOnTurn++;
87
    }
88
    multiplexCount = 0;
89
  }
90
}
91

92
int main (void)
93
{
94
  /* Insert system clock initialization code here (sysclk_init()). */
95

96
  board_init();
97
  TCCR0 = (1<<CS00);       // Start Timer 0 with prescaler 1024
98
  TIMSK |= (1<<TOIE0) /*| (1<<TOIE2)*/;               // Enable Timer 0 overflow interrupt
99
  
100
  DDRC |= (1<<PC0) | (1<<PC1) | (1<<PC2) | (1<<PC3) | (1<<PC4); 
101
  DDRD |= (1<<PD0) | (1<<PD1) | (1<<PD2) | (1<<PD3) | (1<<PD4) | (1<<PD5) | (1<<PD6);
102
  sei();
103
  //changeDigitToOnAndOthersOff(4);
104
  //PORTC |= (1<<PC0);
105
  //PORTD |= (1<<PD0) | (1<<PD1) | (1<<PD2) | (1<<PD3) | (1<<PD4) | (1<<PD5) /*| (1<<PD6)*/;
106
  SPI_SlaveInit();
107
  
108
  while(1){
109
    //if(dataReceived){
110
      //changeDigitToOnAndOthersOff(1);
111
      //break;
112
      
113
    //}
114
    
115
  }
116

117
  /* Insert application code here, after the board has been initialized. */
118
}
119

120
ISR(TIMER0_OVF_vect)
121
{
122
  
123
  
124
  multiplexDigits();
125
  multiplexCount++;
126
  updateDigits();
127
  //SPI_SlaveReceive();
128
  //increment += 0.000255;
129
  //if(!dataReceived){
130
  //changeDigitToOnAndOthersOff(2);
131
  
132
  if(!(PINB & (1<<PB2))){
133
    
134
    SPI_SlaveReceive();
135
    totalSum = 1010;
136
    //changeDigitToOnAndOthersOff(3);
137
    dataReceived = true;
138
  }
139
  
140
}
OP #4939377
Lesenswert?

Wie du sehen kannst, schalte ich den PB2 also den SS Pin erst einmal 
wider auf LOW und möchte es hochschalten wenn ich mit der Übertragung 
fertig bin, damit der Slave es mitbekommt. Du hast eigentlich Recht, da 
ich nur ein Slave habe brauche ich das ja nicht zu prüfen. Um Ehrlich zu 
sagen, habe ich das aus purer Verzweiflung gemacht, weil es sonst ja 
nicht richtig geklappt hat.
Ich habe es in allen Varianten versucht, was im Internet so rumerzählt 
wird.
SS an SS, Master-SS an VCC & Slave-SS an GND und noch andersrum, Beide 
SS nicht beschaltet, Master allein auf VCC/GND, Slave allein auf 
VCC/GND. Nichts klappt.

Ich muss auch hinzufügen: Ich habe gerade getestet ob der SCK überhaupt 
Taktsignale erzeugt, da ich kein gescheites Oszilloskop hier habe, habe 
ich einfach an den SCK PIN (mit Vorwiderstand natürlich), ein LED 
geschaltet und siehe da LED leuchtet nicht? Also werden dort dann ja 
auch keine Taktsignale erzeugt oder? Ich sende doch ununterbrochen, die 
gleichen Daten vom Master aus an den Slave?

Vielleicht kannst du ja mein Programm dort auf Fehler überprüfen und 
ggfls. etwas verändern wodurch das ganze hier ein Ende findet. Da die 
TXD/RXD PINs bereits durch Bluetooth benutzt werden, kamen diese leider 
nicht in Frage...

Ich hoffe ich schaffe das alles mal bald...
(Firma: Vescomp) #4939378
Lesenswert?

Sercan S. schrieb:
> Nun erkläre ich euch mal in PSEUDOCODE wie ich vorgehen wollte:
> SOLANGE !WELTUNTERGANG :
1
 MASTER & SLAVE rufen ihre spiInit... Methoden auf
2
  JA.
3

4
 SLAVE überwacht SS PIN und wartet auf ein LOW Signal
5
  NEIN. Falls mit ISR empfangen wird, macht der SLAVE das in der ISR,
6
  falls mit polling gearbeitet wird, macht der SLAVE folgendes:
7
     while (!(SPSR & (1<<SPIF)));
8

9
 MASTER will senden
10
 MASTER setzt SS PIN auf LOW
11
 MASTER ruft SPI_MasterTransmit auf
12
  JA.
13

14
 SLAVE bekommt den LOW Signal an SS PIN mit und ruft spiSlaveTransmit auf
15
  NEIN, siehe oben.
16

17
 MASTER & SLAVE Warten bis Datenübertragung zuende ist
18
 MASTER setzt den SS PIN auf HIGH
19
 MASTER & SLAVE können die empfangenen Daten verarbeiten
20
  JA.

 Jetzt muss der SLAVE nächstes Byte vorbereiten (falls nötig)
 und mit:
1
 SPDR = Antwort;
 dies auch reinschreiben.

 Beim nächsten Transmit vom MASTER kriegt der SLAVE ein neues Befehl
 und der MASTER kriegt die reingeschriebene Antwort.
(Firma: Vescomp) #4939393
Lesenswert?

Sercan S. schrieb:
> void SPI_MasterTransmit(char cData) {
>   /* Start transmission */
>   PORTB &= (1<<PB2);
>   SPDR = cData;
>   /* Wait for transmission complete */
>   while(!(SPSR & (1<<SPIF)))
>   PORTB |= (1<<PB2);
> ; }

 Erstens machst du es verkehrt, zweitens musst du nur einmal vorher
 SS Pin als Ausgang setzen, alles andere macht deine MEGA alleine.

 Lass SS Pin in Ruhe !!
Gast #4939395
Lesenswert?

Sercan S. schrieb:
> vielleicht entdeckst du ja etwas

Zuerst müsstest du dazu sagen was du von deinem Code erwartest.

Dann:

- board_init()  fehlt total, sowohl bei Master als auch bei Slave

Sercan S. schrieb:
> if(!(PINB & (1<<PB2))){

Du brauchst den SlaveSelect nicht abfragen, es reicht das SPI
Status Register zu fragen. Denn wenn SlaveSelect Low ist hast
du noch kein Byte empfangen. Das Status Register gibt zuverlässig
Auskunft darüber.
Gast #4939407
Lesenswert?

Sercan S. schrieb:
> ein LED
> geschaltet und siehe da LED leuchtet nicht? Also werden dort dann ja
> auch keine Taktsignale erzeugt oder?

Nein, nicht unbedingt. Das SPI Telegramm kann so kurz und schnell
sein dass du die LED nicht leuchten siehst.

SPISpezialist schrieb:
> - board_init()  fehlt total, sowohl bei Master als auch bei Slave

Ach so, kommt wohl vom ASF (das ich nicht benutze) ....
OP #4939412
Lesenswert?

Marc V. schrieb:
> Sercan S. schrieb:
>> void SPI_MasterTransmit(char cData) {
>>   /* Start transmission */
>>   PORTB &= (1<<PB2);
>>   SPDR = cData;
>>   /* Wait for transmission complete */
>>   while(!(SPSR & (1<<SPIF)))
>>   PORTB |= (1<<PB2);
>> ; }
>
>  Erstens machst du es verkehrt, zweitens musst du nur einmal vorher
>  SS Pin als Ausgang setzen, alles andere macht deine MEGA alleine.
>
>  Lass SS Pin in Ruhe !!

Ich würde gerne aber da alles nicht geklappt hat und ich es vorher ohne 
den SS PIN versucht habe, habe ich natürlich dort rumgefuscht. :D

>Sercan S. schrieb:
>> vielleicht entdeckst du ja etwas
>
>Zuerst müsstest du dazu sagen was du von deinem Code erwartest.
Als erstes will ich, dass es Problemfrei hinbekommt den einen Byte zu 
senden, den ich versuche zu senden. Also
1
char send = '1';

Was kommt eigentlich beim Empfänger an wenn ich
1
char send = '1';
oder
1
char send = 1;
 sende? Kommt da beim '1' die 49 (wegen ASCII) und bei 1 tatsächlich die 
1 an?

>
>Dann:
>
>- board_init()  fehlt total, sowohl bei Master als auch bei Slave
board_init() ist doch da :O ?

>
>Sercan S. schrieb:
>> if(!(PINB & (1<<PB2))){
>
>Du brauchst den SlaveSelect nicht abfragen, es reicht das SPI
>Status Register zu fragen. Denn wenn SlaveSelect Low ist hast
>du noch kein Byte empfangen. Das Status Register gibt zuverlässig
>Auskunft darüber.



also wie Marc Veseyl geschrieben hat muss ich einfach while(!(SPSR & 
(1<<SPIF))) aufrufen und warten bis dort was reingeschrieben wurden ist?
OP #4939419
Lesenswert?

>Marc V. schrieb:
>> Lass SS Pin in Ruhe !!
>
>Ich verspüre - wie in anderen Beiträgen auch - eine gewisse
>Agressivität im Ton.

Alles gut. Nicht streiten :D
>
>Auch höre ich zwischen den Zeilen dauernd:
>"du machst alles scheisse, mach das gefälligst besser!"
>
>SPISpezialist schrieb:
>> Sercan S. schrieb:
>>> also wie Marc Veseyl geschrieben hat muss ich einfach while(!(SPSR &
>>> (1<<SPIF))) aufrufen und warten bis dort was reingeschrieben wurden ist?
>>
>> Ja.

Und die PINS wirklich so lassen also (MOSI-MOSI, MISO-MISO, SCK-SCK, 
SS-SS)?
Gast #4939434
Lesenswert?

Noch ein Tip:

Mache ein neues Projekt auf und kopiere deine existierenden
Sourcen, reduziere alles auf das Minimum was du brauchst um
deine SPI-Übertragung erfolgreich durchzuführen. Wenn das
funktioniert kannst du ja dein übriges Programm drum herum
bauen.
OP #4939446
Lesenswert?

Also, ich habe das jetzt gerade so hingekriegt, dass die Totalsumme von 
1010 auf der Segmentanzeige angezeigt wurde sprich, ich kam beim Slave 
aus der while schleife raus, wo die Datenübertragung stattgefunden hat? 
Also habe ich ja Daten bekommen, sprich es hat geklappt? :O

Anschließend habe ich versucht, den totalSum statt mit 1010 
abzuspeichern mit den empfangenen Byte zu belegen. Aber wenn ich 
(totalSum ist ein int) totalSum += (int)SPI_SlaveReceive();
oder gar ohne den int-Cast versuche, klappt die Anzeige nicht... :hmmm:
#4939459
Lesenswert?

Das SPI des AVR ist nicht gerade das, was man als Slave haben will. Es 
ist ne Krücke.

Du mußt alle 4 Leitungen verbinden und das SS des Master muß vor dem 
SPI-Init als Ausgang gesetzt werden. Damit ist SS vom SPI abgekoppelt, 
d.h. ein ganz normaler Output-Pin.
Dann mußt Du als Master mit SS=0 dem Slave sagen, daß ein Byte beginnt, 
d.h. nur so wird der Slave Bit-synchron.
Sind alle Bytes übertragen, mußt Du SS=1 setzen.

Vorzugsweise nimmt man als Slave nicht den alten Mega8, sondern den 
Mega88 und setzt für SS den Pin-change Interrupt. Nur so kann man Anfang 
und Ende eines Paketes feststellen. Falls es der Mega8 sein muß, muß man 
eben den SS-Pin mit dem INT0/1-Pin verbinden.

Will der Master was lesen, muß er vor jedem Byte eine Pause lassen, 
damit der Slave in den Interrupt springen und das Byte in SPDR schreiben 
kann. Ich würde >=100µs Pause empfehlen.
OP #4939511
Lesenswert?

Peter D. schrieb:
> Das SPI des AVR ist nicht gerade das, was man als Slave haben will. Es
> ist ne Krücke.
>
> Du mußt alle 4 Leitungen verbinden und das SS des Master muß vor dem
> SPI-Init als Ausgang gesetzt werden. Damit ist SS vom SPI abgekoppelt,
> d.h. ein ganz normaler Output-Pin.
> Dann mußt Du als Master mit SS=0 dem Slave sagen, daß ein Byte beginnt,
> d.h. nur so wird der Slave Bit-synchron.
> Sind alle Bytes übertragen, mußt Du SS=1 setzen.
>
> Vorzugsweise nimmt man als Slave nicht den alten Mega8, sondern den
> Mega88 und setzt für SS den Pin-change Interrupt. Nur so kann man Anfang
> und Ende eines Paketes feststellen. Falls es der Mega8 sein muß, muß man
> eben den SS-Pin mit dem INT0/1-Pin verbinden.
>
> Will der Master was lesen, muß er vor jedem Byte eine Pause lassen,
> damit der Slave in den Interrupt springen und das Byte in SPDR schreiben
> kann. Ich würde >=100µs Pause empfehlen.

Jetzt kommts...
Nun soll ich den SS-PIN doch setzen und den vordem SPI-Init als Ausgang 
setzen und esklappt irgendwie vorne und hinten nicht.... Ich glaube SPI 
ist bisschen komplizierter als ich es mir gedacht habe.
Was haltet Ihr von I2C? Ich bin bei der Recherche auf I2C gestoßen und 
da meinte man, dass es einfacher und sicherer von statten ginge....
(Firma: Vescomp) #4939588
Lesenswert?

Sercan S. schrieb:
> Wo soll ich es denn sonst aufrufen, wenn nicht in ISR (TIMER0_OVF_vect)?

 Du hast in deinem Code Timer0 mit Vorteiler 1 laufen lassen, also
 mit 8MHz.

 Probiere das mal, nur zum Testen:
 Master
1
char send = '1';
2
volatile uint16_t increment = 0;
3
volatile uint8_t Flag = 0;
4

5
void SPI_MasterInit(void) {
6
  /* Set MOSI and SCK output, all others input */
7
  DDRB = (1<<PB5)|(1<<PB3) |(1<<PB2);
8
  PORTB |= (1<<PB2);
9
  /* Enable SPI, Master, set clock rate fck/16 */
10
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
11
}
12
void SPI_MasterTransmit(char cData) {
13
  /* Start transmission */
14
  PORTB &= (1<<PB2);
15
  SPDR = cData;
16
  /* Wait for transmission complete */ 
17
  while(!(SPSR & (1<<SPIF)))
18
  PORTB |= (1<<PB2);
19
; }
20

21
int main (void)
22
{
23
   board_init();
24
  // Timer 0 konfigurieren
25
  // Bei dir war es mit Prescaler 1, also 8 MHz !!!
26
  TCCR0 = (1<<CS00) | (1<<CS02);          // Start Timer 0 with prescaler 1024
27
  TIMSK |= (1<<TOIE0) /*| (1<<TOIE2)*/;               // Enable Timer 0 overflow interrupt
28
  sei();
29
  DDRD = (1<<PD0);
30
  //PORTD |= (1<<PD0);
31
  SPI_MasterInit();
32

33
  while(1){
34
    if (Flag==1) {
35
      Flag = 0;
36
      SPI_MasterTransmit(send++);
37
      if (send>0x39) send = 0x30;
38
    }
39
  }
40
}
41

42
ISR(TIMER0_OVF_vect)
43
{
44
  increment++;
45
  if(increment>=7812) {
46
    increment = 0;
47
    PORTD ^= 0x01;
48
    Flag = 1;   
49
  }
50
}

 Slave
1
char send = '1';
2

3
void SPI_SlaveInit(void) {
4
  /* Set MISO output, all others input */
5
  DDRB = (1<<PB4);
6
  /* Enable SPI */
7
  SPCR = (1<<SPE);
8
}
9
char SPI_SlaveReceive(void) {
10
  /* Wait for reception complete */ 
11
  while(!(SPSR & (1<<SPIF)));
12
  /* Return data register */ 
13
  return SPDR;
14
}
15

16
int main (void)
17
{
18
  /* Eine LED an PORTC.0  */
19
  DDRC |= (1<<PC0); 
20
  
21
  sei();
22
  SPI_SlaveInit();
23
  
24
  while(1){
25
    send = SPI_SlaveReceive();
26
  // Toggle LED 
27
       PORTC ^= 0x01;
28
  }
29
}
Gast #4939600
Lesenswert?

Fang doch mal ganz einfach an:

- Master SS offen lassen und auf Output setzen
- Slave SS fix auf GND
- MOSI-MOSI, SCK-SCK und MISO-MISO verbinden und so auf Output setzen, 
wie du es oben beschrieben hast (ich prüfe jetzt nicht, ob B5 und B3 
wirklich MOSI und SCK sind)
- Initialisierung nochmal überprüfen
- Taktrate so niedrig wie möglich (damit vielleicht du eine Chance hast, 
mit einer LED etwas zu sehen)

Wenn du jetzt auf dem Master folgendes ausführst...
1
while(true)
2
{
3
   SPDR = 0xaa;                   // Daten per SPI rausschicken
4
   while (! (SPSR & (1<<SPIF)) )  // solange Daten nicht vollständig verschickt...
5
     ;                            // nichts tun
6
}

...müsste permanent Gezappel an allen drei Pins zu beobachten sein (0xaa 
ist 0b10101010, also bei jedem Takt ein Flankenwechsel, alternativ 
kannst du auch 0xf0 = 0b11110000 probieren, dann sind die Flankenwechsel 
auf MOSI/MISO deutlich langsamer als auf SCK). Solange muss der Slave 
noch gar nichts tun...

Wenn das klappt, kannst du 0xaa mit 0x00 und 0xff ersetzen, schauen, ob 
MOSI und MISO jetzt dauerhaft low bzw. high bleiben

Dann packst du statt dieser Spieldaten mal etwas sinnvolles (1 oder '1') 
in die Daten und packst in den Slave sowas wie...
1
while(true)
2
{
3
   if (SPSR & (1<<SPIF))           // ist ein Byte angekommen?
4
   {
5
      unsigned char data = SPDR;   // Byte aus dem SPI-Register holen
6
      output (data);               // irgendwie ausgeben
7
   }
8
}

Jetzt wirst du feststellen, dass nicht die Daten ankommen, die du 
erwartest. Das liegt daran, dass der Slave nicht weiß, wo das Datenbyte 
beginnt. Und genau dafür kannst du den SS-Pin nutzen, jetzt also wieder 
Master und Slave SS-Pins verbinden und in Pseudocode:

Master: Setze SS auf low
Master: Warte, bis sicher ist, dass das Signal beim Slave angekommen ist 
(zum Testen gerne mal 1s probieren, dann kannst du das mit deiner LED 
nachverfolgen, später wirst du vermutlich ein paar µs brauchen)
Master: Sende Daten (SPDR = '1'; while ( !(SPSR & (1<<SPIF)) ) ;)
Master: Warte, bis sicher ist, dass das letzte Bit beim Slave angekommen 
ist
Master: Setze SS auf high

Am Slave-Code änderst du nichts.

MfG, Arno

P.S: Einen Bug sehe ich in deiner SPI_MasterTransmit...
1
while(!(SPSR & (1<<SPIF)))
2
  PORTB |= (1<<PB2);
...damit setzt du SS wieder auf High, bevor das Byte durchgetaktet 
wurde. Du willst vermutlich:
1
while(!(SPSR & (1<<SPIF)))
2
  ;
3
PORTB |= (1<<PB2);
OP #4941684
Lesenswert?

Marc V. schrieb:
> Sercan S. schrieb:
>> Wo soll ich es denn sonst aufrufen, wenn nicht in ISR (TIMER0_OVF_vect)?
>
>  Du hast in deinem Code Timer0 mit Vorteiler 1 laufen lassen, also
>  mit 8MHz.
>
>  Probiere das mal, nur zum Testen:
>..........

Also ich bin jetzt heute erst dazugekommen und habe diese Testweise 
raufgespielt und diese wie von mir beschrieben angeschlossen und muss 
feststellen, dass es irgendwie nicht klappt. Irgendwas muss da ja falsch 
sein, die LED schaltet sich einfach nicht an. LED habe ich getestet und 
ohne den
1
send = SPI_SlaveReceive();
 geht die LED auch an (toggelt). Also liegt es wirklich an der 
Übertragung...
Gast #4941741
Lesenswert?

Dann gibt es drei Möglichkeiten:

1) Der Slave bekommt keine oder zu schnelle SCK-Signale
2) Der Slave bekommt kein SS-Signal bzw. eins mit falschem Timing (SS 
muss auf low bleiben, bis acht SCK-Pulse durch sind, sonst erkennt der 
Slave nie ein vollständig übertragenes Byte)
3) An der Slave-Initialisierung stimmt irgendwas nicht

Hast du Marcs Code in SPI_MasterTransmit schon um die beiden Fehler (die 
er von dir kopiert hat) korrigiert, die Martin und ich beschrieben 
haben? Die sorgen nämlich für gar kein ("Martins" Bug) bzw. ein viel zu 
kurzes ("mein" Bug) SS-Signal, also Punkt 2 oben auf der Liste, damit 
kann es also auch gar nicht gehen.

Alternativ nimm die SS-Verbindung weg und leg den Slave-SS fest auf 
Masse, dann hast du Fehlerquelle 2 schonmal ausgeschlossen. Wenn es dann 
immer noch nicht geht, nimm auch die SCK-Verbindung weg und halte einen 
Draht von Slave-SCK abwechselnd an GND und VCC bis die LED toggelt. Ja, 
SPI ist so einfach und kann beliebig langsam laufen.

MfG, Arno
OP #4941748
Lesenswert?

Ich muss mal euch nun ein Update geben...

Also ausprobiert habe ich o.g. Code wie folgt angeschlossen:
1
SCK    <->    SCK
2
MISO   <->    MISO
3
MOSI   <->    MOSI
4
SS     <->    SS

Klappt nicht.


Wenn ich es allerdings so anschließe, wie im Atmel Datenblatt 
beschrieben:
1
SCK           <->    SCK
2
MISO          <->    MISO
3
MOSI          <->    MOSI
4

5
MASTER_SS     <->    VCC
6
SLAVE_SS      <->    GND

Klappt! WARUM? :O

Ich muss allerdings nachprüfen, ob auch das richtige ankommt, aber 
irgendetwas kommt schonmal an sonst würde es doch nicht toggeln...

EDIT: Es kommt auch das richtige an! Also es fängt von 49 an und springt 
bei nach 57 auf 48 und geht wieder von vorne los. Ich habe Testweise 
beide SS_PINS freigelassen und es klappt auch ohne es in VCC/GND zu 
beschalten...
Gast #4941901
Lesenswert?

Arno schrieb:
> Hast du Marcs Code in SPI_MasterTransmit schon um die beiden Fehler (die
> er von dir kopiert hat) korrigiert, die Martin und ich beschrieben
> haben? Die sorgen nämlich für gar kein ("Martins" Bug) bzw. ein viel zu
> kurzes ("mein" Bug) SS-Signal, also Punkt 2 oben auf der Liste, damit
> kann es also auch gar nicht gehen.

MfG, Arno
Gast #4941904
Lesenswert?

Arno schrieb:
> Master und Slave SS-Pins verbinden und in Pseudocode:
>
> Master: Setze SS auf low
> Master: Warte, bis sicher ist, dass das Signal beim Slave angekommen ist
> (zum Testen gerne mal 1s probieren, dann kannst du das mit deiner LED
> nachverfolgen, später wirst du vermutlich ein paar µs brauchen)
> Master: Sende Daten (SPDR = '1'; while ( !(SPSR & (1<<SPIF)) ) ;)
> Master: Warte, bis sicher ist, dass das letzte Bit beim Slave angekommen
> ist
> Master: Setze SS auf high

MfG, Arno
Gast #4941906
Lesenswert?

Arno schrieb:
> P.S: Einen Bug sehe ich in deiner SPI_MasterTransmit...
>
1
> while(!(SPSR & (1<<SPIF)))
2
>   PORTB |= (1<<PB2);
3
>
> ...damit setzt du SS wieder auf High, bevor das Byte durchgetaktet
> wurde. Du willst vermutlich:
>
1
> while(!(SPSR & (1<<SPIF)))
2
>   ;
3
> PORTB |= (1<<PB2);
4
>

MfG, Arno
Gast #4941915
Lesenswert?

Martin B. schrieb:
> und möglichst noch das
>
>  PORTB &= (1<<PB2);
>
> in
>
>  PORTB &= ~(1<<PB2);
>
> ändern.

So, nochmal in kleinen Häppchen zusammengesucht, warum es mit der 
Verbindung der beiden SS-Pins nicht geht. Steht alles schon oben, 
teilweise mehrfach - entweder du hast es nicht verstanden (das ist keine 
Schande, dann frag bitte nach) oder du hast es nicht gelesen (dann hör 
auf, herumzuprobieren, bis du alles gelesen hast, sonst ist es sehr 
anstrengend, irgendwie sinnvoll auf deine Fragen zu antworten).

Danke und viele Grüße,
Arno
Gast #4941928
Lesenswert?

Ergänzung (vielleicht sollte ich mich doch mal registrieren, dass ich 
meine Beiträge bearbeiten kann...):
- Es ist gefährlich, wenn du den Master-SS-Pin auf VCC legst und ihn 
gleichzeitig als Ausgang definierst. Damit kannst du dir ganz schnell 
den Ausgang kaputtmachen, oder sogar den ganzen Controller, wenn du ihn 
aus Versehen umschaltest.
- Es ist Zufall, dass es mit offenem Slave-SS-Pin funktioniert. Je 
nachdem, was gerade an elektromagnetischem Dreck in der Luft ist, kann 
der Slave auch Highlevel am SS-Pin sehen, und dann funktioniert es nicht 
mehr.
- Es ist Zufall, dass es ohne verbundene SS-Pins richtig funktioniert. 
Es kommen immer Daten an, aber dass es die richtigen sind, hängt davon 
ab, in welcher Reihenfolge du Master und Slave einschaltest, welcher 
Controller wie schnell durch seine Initialisierung läuft... Wenn der 
Master ein kleines bisschen schneller ist als der Slave, wird er schon 
ein paar Bits auf die SPI gesendet haben, bevor der Slave bereit ist, 
sie zu empfangen. Der Master schickt also zum Beispiel Bits 1-3, dann 
empfängt der Slave Bit 4-8 und interpretiert das als Bits 1-5, dann 
sendet der Master das nächste Byte, Bit 1-3 landen beim Slave als Bits 
6-8, der Slave erkennt das erste vollständige Byte, setzt SPIF, empfängt 
weiter Bits 4-8 vom zweiten Byte und speichert sie als Bits 1-5 in 
seinem zweiten Byte. Der SS-Pin sorgt dafür, dass der Slave genau weiß, 
wann ein Byte beginnt - wenn man ihn richtig beschaltet.

MfG, Arno
(Firma: Vescomp) #4941947
Lesenswert?

Arno schrieb:
> - Es ist Zufall, dass es mit offenem Slave-SS-Pin funktioniert. Je
> - Es ist Zufall, dass es ohne verbundene SS-Pins richtig funktioniert.

 Kann mich dem nur anschliessen.


Sercan S. schrieb:
> Klappt! WARUM? :O

 Warum nicht ?

 Dein SLAVE ist selektiert ( SLAVE_SS auf GND ), bei MASTER ist SS auf
 HIGH - MASTER sendet, SLAVE empfängt - für die beiden ist ALLES in
 bester Ordnung...

 P.S.
 Nur nicht jetzt zufällig MASTER_SS auf 0 setzen.
OP #4942052
Lesenswert?

Hallo,

ja ich habe die Zeile verbessert :)
Wenn ich nun die SS am SS verbinde, wie gehe ich dabei vor?
Master zieht den PB2 (SS) auf LOW und nach der While-Schleife (nach der 
Übertragung) wird es ja wieder auf HIGH gezogen.

Ich müsste ja logischerweise auf Seiten der Slave nun:
1
if(!(PINB & (1<<PB2))){
2
  send = SPI_SlaveReceive();
3
}

Also Überprüfen ob PB2 auf LOW gezogen wurde und dann lesen oder?
Gast #4942058
Lesenswert?

Sercan S. schrieb:
> Also Überprüfen ob PB2 auf LOW gezogen wurde und dann lesen oder?

Mann oh Mann, du hast schon noch überhaupt nichts kapiert.

SPISpezialist schrieb:
> Du brauchst den SlaveSelect nicht abfragen, es reicht das SPI
> Status Register zu fragen. Denn wenn SlaveSelect Low ist hast
> du noch kein Byte empfangen. Das Status Register gibt zuverlässig
> Auskunft darüber.
OP #4942112
Lesenswert?

SPISpezialist schrieb:
> Sercan S. schrieb:
>> Also Überprüfen ob PB2 auf LOW gezogen wurde und dann lesen oder?
>
> Mann oh Mann, du hast schon noch überhaupt nichts kapiert.
>
> SPISpezialist schrieb:
>> Du brauchst den SlaveSelect nicht abfragen, es reicht das SPI
>> Status Register zu fragen. Denn wenn SlaveSelect Low ist hast
>> du noch kein Byte empfangen. Das Status Register gibt zuverlässig
>> Auskunft darüber.

Ich habe es schon verstanden, dass der Status Register darüber 
zuverlässig Informationen darüber gibt.

Ich möchte ja in meinem Programm auch noch andere Sachen machen und da 
dachte ich mir, da ich sowieso den SS auf LOW und anschließend auf HIGH 
ziehe, kann ich ja dann SPDR abholen. Weil ich sende ja nicht ständig 
irgendwelche Daten rüber, aber falls mal was da ist möchte ich das 
mitbekommen und da schien es mir logisch einfach den SS-LOW-HIGH zu 
prüfen um dann die angekommene Daten abzulesen.

EDIT: Da ich den letzten SPDR speichere könnte ich ja auch einfach 
vergleichen ob die jetzige Daten in SPDR verschieden sind, dann könnte 
ich somit auch Bescheid wissen, dass da was neues ist. Ich möchte mit 
der While-Schleife halt nicht warten, bis es verändert wurden ist, somit 
stoppe ich ja mein ganzen Programmlauf.
#4942132
Lesenswert?

Sercan S. schrieb:
> Weil ich sende ja nicht ständig
> irgendwelche Daten rüber, aber falls mal was da ist möchte ich das
> mitbekommen und da schien es mir logisch einfach den SS-LOW-HIGH zu
> prüfen um dann die angekommene Daten abzulesen.

Auf dem Slave?
Wenn man da nicht mit Interrupts oder DMA arbeitet, wird es mit SPI nix.

Bei SPI möchte man den Takt am Master normalerweise nicht so weit runter 
drehen - weil der ja auch vermutlich auch noch was anderes zu tun hat 
als auf den Slave zu warten.

Bessere Lösung: SPI Interrupt + FIFOs für Transmit und Receive. Atmega8 
hat ja leider kein DMA.

Die Hauptschleife muss sich dann nur noch um die FIFOs kümmern.
Gast #4942197
Lesenswert?

Sercan S. schrieb:
> ja ich habe die Zeile verbessert :)

Beide Zeilen? Martins und meine?

> Wenn ich nun die SS am SS verbinde, wie gehe ich dabei vor?
> Master zieht den PB2 (SS) auf LOW und nach der While-Schleife (nach der
> Übertragung) wird es ja wieder auf HIGH gezogen.

Genau (aber nur, wenn du die while-Schleife korrigiert hast, die macht 
nämlich im Moment noch was anderes, wie ich oben schon geschrieben 
habe). Ich würde da noch jeweils ein paar µs delay einbauen, um sicher 
zu gehen, dass dir unterschiedliche Signallaufzeiten nicht den Plan 
kaputt machen, aber es müsste auch ohne funktionieren.

> Ich müsste ja logischerweise auf Seiten der Slave nun:
>
1
> if(!(PINB & (1<<PB2))){
2
>   send = SPI_SlaveReceive();
3
> }
4
>
>
> Also Überprüfen ob PB2 auf LOW gezogen wurde und dann lesen oder?

Nein. Das macht die SPI-Hardware im Slave von ganz alleine. Du musst nur 
noch prüfen, ob die SPI ein komplettes Byte empfangen hat:
[c]
if(SPSR & (1<<SPIF))
  {
    unsigned char data = SPDR;
    //mach irgendwas mit data
  }
[c]

Sercan S. schrieb:
> Ich habe es schon verstanden, dass der Status Register darüber
> zuverlässig Informationen darüber gibt.

Dann nutz es doch. Wenn du oft genug SPIF abfragst, bekommst du das mit, 
noch sicherer, wenn du einen SPI-Interrupt nutzt. Besser als den SS-Pin 
abzufragen, denn ein SPI-Master kann auch direkt ein zweites Byte 
hinterher schicken, ohne SS zwischendurch auf High zu ziehen. Und selbst 
bei deinem Master kann SS sehr sehr kurz auf High und gleich wieder auf 
Low gehen.

> Ich möchte ja in meinem Programm auch noch andere Sachen machen und da
> dachte ich mir, da ich sowieso den SS auf LOW und anschließend auf HIGH
> ziehe,

SS fasst du auf dem Slave mit deinem Code doch nach der Initialisierung 
gar nicht an?

> Ich möchte mit
> der While-Schleife halt nicht warten, bis es verändert wurden ist, somit
> stoppe ich ja mein ganzen Programmlauf.

Deswegen solltest du keine while-Schleife verwenden, sondern eine 
if-Abfrage, die wird übersprungen, wenn das SPIF-Bit noch nicht gesetzt 
ist. Muss nur oft genug aufgerufen werden, damit der Master nicht schon 
ein komplettes zweites Byte geschickt hat. Während der Master das zweite 
Byte sendet, ist OK, solange hat SPDR noch den alten Wert, aber sobald 
das zweite Byte komplett ist, wird SPDR auf den neuen Wert aktualisiert.

MfG, Arno

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