Forum: Mikrocontroller und Digitale Elektronik spi zwischen zwei AVRs überträgt nur wenige Bytes


von Meiermann (Gast)


Lesenswert?

Hallo allerseits,

ich möchte gerne Daten übertragen zwischen einem Mega16 und einem Mega88 
per SPI.

Um die Übertragung robust zu halten, packe ich nur 4 Datenbits je 
übertragenem Byte und die vorderen Bits enthalten eine um 4 Bit 
verschobene Adressierung der Nibbles. Das merke ich nur mal an, für den 
Fall dass jemand den Beispielcode zu seltsam findet, ist eigentlich auch 
nicht relevant.

In der Hauptschleife prüfe ich im (MasterSPI)AVR-Programm, ob die 
Übertragung fertig ist, wenn nicht mache ich andere Sachen und komme 
beim nächsten Durchlauf wieder.

Da ich noch eine UART-Verbindung zum PC habe, schreibe ich zu 
DEBUG-Zwecken  noch Bytes in den Ausgabe-Buffer (Antwort[11] - [15] habe 
ich dafür noch frei).
1
Antwort[11] = spi_pointer;
2
Antwort[15]++;
3
if (! (SPSR & (1<<SPIF)) )
4
  {
5
  Antwort[14] = SPSR;
6
  Antwort[12] ++;
7
  
8
  PORTB |= (1<<PB4);
9
  uint8_t data = 0;
10
  switch(spi_pointer)
11
    {case 0:
12
      data = TranferDaten[ TransferBank ][ 0 ] & 0x0f;
13
      break;
14
    case 1 :
15
      data = (1 << 4) + ((TranferDaten[ TransferBank ][ 1 ] << 4) & 0x0f);
16
      break;
17
    case 2 :
18
      data = (2 << 4) + (TranferDaten[ TransferBank ][ 1 ] & 0x0f);
19
      break;
20
    case 3 :
21
      data = (3 << 4) + ((TranferDaten[ TransferBank ][ 2 ] << 4) & 0x0f);
22
      break;
23
    case 4 :
24
      data = (4 << 4) + (TranferDaten[ TransferBank ][ 2 ] & 0x0f);
25
      break;
26
    case 5 :
27
      data = (5 << 4) + ((TranferDaten[ TransferBank ][ 3 ] << 4) & 0x0f);
28
      break;
29
    case 6 :
30
      data = (6 << 4) + (TranferDaten[ TransferBank ][ 3 ] & 0x0f);
31
      break;
32
    case 7 :
33
      data = (7 << 4) + ((TranferDaten[ TransferBank ][ 4 ] << 4) & 0x0f);
34
      break;
35
    case 8 :
36
      data = (8 << 4) + (TranferDaten[ TransferBank ][ 4 ] & 0x0f);
37
      break;
38
    default :
39
      break;
40
    }
41
  PORTB &= ~(1<<PB4);
42
  SPDR = data;
43
  
44
  Antwort[14] = data;
45
46
  spi_pointer++;
47
  if (spi_pointer > 8)
48
    {TransferBank = 1 - TransferBank;
49
50
    Antwort[13]++;
51
52
    spi_pointer = 0;
53
    }
54
  }

Der SPI wird initialisiert mit:
1
DDRB = (1<<PB4)|(1<<PB5)|(1<<PB7);    // MOSI,SCK,/SS
2
PORTB = 0;    // /SS löschen => SPI im Slave einschalten
3
// set 'Enable SPI', set Master, set SPI clock rate fck/64
4
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR1);

Mit der Geschwindigkeit bin ich schon auf fck/64 runter von fck/16.
Nun lasse ich mir die Ausgabe am PC vom UART ausdrucken, da sieht man 
dann als Hex-Wert:
1
00 09 01 80 xx
 xx = fortlaufend.
Also steht der spi_pointer auf 0, es sind 9 Bytes übertragen, einmal 
wurde spi_pointer zurückgesetzt, 128(0x80) kam als letztes Byte aus dem 
SPI(mir egal), das letzte Byte zählt ständig hoch, natürlich schneller 
als der UART das ausgeben kann.

Es kann auch schon mal vorkommen, dass spi-pointer bei 1 stehen bleibt, 
entsprechend wurden dann 10 Bytes gesendet.

MISO,MOSI,SCK und SS sind jeweils mit 1kOhm mit dem jeweiligen Port am 
anderen AVR verbunden, SS ist am SPI-Master ein Ausgang, und ich schalte 
ihn extra vor jeder Übertragung auf 0 um den SPI auf Slave-Seite 
anzuschalten.

Sonderbar auch, dass ich mit
1
if (! (SPSR & (1<<SPIF)) )
 auf die Negation hin prüfe, eigentlich müsste ich ja auf ein gesetztes 
SPIF weitersenden können !?! Wenn ich die Negation weglasse überträgt 
das Programm garnichts.

Ich habe keine Ahnung, warum das Programm mit der Übertragung aufhört.

Sieht jemand den Fehler?

Gruß,
Olaf

von Stefan E. (sternst)


Lesenswert?

Meiermann schrieb:
> Sonderbar auch, dass ich mit
1
if (! (SPSR & (1<<SPIF)) )
> auf die Negation hin prüfe, eigentlich müsste ich ja auf ein gesetztes
> SPIF weitersenden können !?!

Richtig, und das dürfte auch die Ursache deines Problems sein.

Meiermann schrieb:
> Wenn ich die Negation weglasse überträgt
> das Programm garnichts.

Ja, weil du erst mal was übertragen musst, bevor das Flag das erste Mal 
gesetzt wird.

von Meiermann (Gast)


Lesenswert?

Stimmt.

Ein SPDR = 0; vor der Hauptschleife löst das Probelm.
Dabei dachte ich, diese Möglichkeit hätte ich schon durchprobiert, aber 
wohl nur mit Negation statt nun ohne - perfekter Programmlauf.

Danke dafür.

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.