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