Forum: Mikrocontroller und Digitale Elektronik RPi & Atmega88PA als SPI-Slave Datenübertragungsfehler


von kobold254 (Gast)


Lesenswert?

Hallo liebe Forenmitglieder,

ich möchte eine Kommunikation zwischen einem RPi und Atmega 88 PA über 
SPI herstellen. Der RPi ist dabei Master (Atmega dementsprechend Slave) 
und ich komme bei der Kommunikation nicht weiter.
Es tritt ein sehr merkwürdiges Verhalten auf:
-eine einmalige Datenübertragen funktioniert nie
-eine doppelte Datenübertragung funktioniert zu 99%
-die gesendeten Daten sind in verkehrter Reihenfolge

Ich habe schon versucht:
-CPOL zu ändern
-Soft-SPI auf dem RPi / Hardware SPI RPi
Und ich sehe mit dem Logikanalysator, dass die Daten richtig am Atmega 
landen, daher liegt der Fehler vermutlich dort in der Programmierung
(Spannungspegel passen)

Noch als Info: Der Atmega steuert ein paar WS2812 an, über den SPI Bus 
möchte ich die Farben übertragen (später auch Effekt); die 
WS2812-Ansteuerng funktioniert 1A

Hier die notwendigen Codeausschnitte, wobei der Code teilweise 
merkwürdig aussieht, da ich schon endlos viel ausprobiert habe...
1
//GLOBAL:
2
struct farbe24bit{
3
  uint8_t rot;/**<8 Bit Rotanteil*/
4
  uint8_t gruen;/**<8 Bit Grünanteil*/
5
  uint8_t blau;/**<8 Bit Blauanteil*/
6
};
7
8
uint8_t aktion;
9
uint8_t bytecnt,spistart;
10
struct farbe24bit spicolor;
11
12
13
void spi_init_slave (void)
14
{
15
  DDRB |=(1<<PINB4);               //MISO as OUTPUT
16
  //SPDR=0; //teilweise im Netz ?! macht keinen Unterschied...
17
  SPCR = (1<<SPE)|(1<<CPOL)|(1<<SPIE);
18
}
19
20
uint8_t SPI_SlaveReceive(void)
21
{
22
  uint8_t data;
23
  /* Wait for reception complete */
24
  while (!(SPSR & (1<<SPIF)))   ;
25
  data = SPDR;
26
  /* Return data register */
27
  //SPDR = 0; im Netz gefunden, macht keinen Unterschied...
28
  return    data;
29
}
30
31
ISR(SPI_STC_vect)
32
{
33
  uint8_t y = SPI_SlaveReceive();
34
  if (y==0x81 && spistart==0)
35
  {
36
    spistart = 1;
37
    bytecnt = 1;
38
  }
39
  else if (spistart==1)
40
  {
41
    if (bytecnt==1)
42
    {
43
      spicolor.rot = y;
44
      bytecnt=2; //inkrementieren macht keinen Unterschied...
45
    }
46
    else if (bytecnt==2)
47
    {
48
      spicolor.gruen = y;
49
      bytecnt=3;
50
    }
51
    else if (bytecnt==3)
52
    {
53
      spicolor.blau = y;
54
      bytecnt=4;
55
    }
56
    else if (bytecnt==4)
57
    {
58
      spistart=0;
59
      bytecnt=0;
60
      aktion = 1;
61
    }
62
  }
63
}
64
65
main...
66
67
DDRB = 0x01;
68
PORTB = 0x00;
69
70
spistart=0;
71
bytecnt=0;
72
aktion =0;
73
74
spi_init_slave();
75
sei();
76
77
78
79
while(1)
80
{    
81
  _delay_ms(200);
82
  if (aktion==0)
83
  {
84
    
85
  }
86
  else
87
  {
88
    //Daten an WS2812 senden
89
    setfullcolor(spicolor,lightdata);
90
    transmit2leds(lightdata);
91
    aktion = 0;
92
  }
93
}

Zum Timing: Atmega @16MHz mit Oszillator, RPi SPI-Timing habe ich alles 
ausprobiert...von MHz bis nur wenige Hz

gesendete Daten vom RPi:
spi.writebytes([0x81,1,2,3,4])

der Atmega lässt an die WS2812 folgendes Raus:
0x81 zur identifikation
1 steuert den blauanteil
2 ist leer (keine Farbansteuerung)
3 entspricht dem Rotanteil
4 entspricht dem Grünanteil

Ohne SPI passt die Farbzuordnung (wenn im Code fest definiert)

Würde mich echt freuen, falls jemand einen Ansatzpunkt hat... :)

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.