SPI anfällig für Störungen?

Gast #1663584
Lesenswert?

Hallo Leute,

ich habe in letzter Zeit einige SPI-Busse verwendet, um AVRs 
kommunizieren zu lassen. Manchmal gabs da überhaupt keine Probleme, 
manchmal war der Bus total unstabil, sodass ich einfach nur die Leitung 
etwas knicken musste, und schon traten haufenweise Fehler auf, 
unabhängig von der Sendegeschwindigkeit (immer unter 2MHz). Im Moment 
habe ich auch keine größeren Quellen von elektromagn. Strahlung (z.B. 
Motoren) laufen... nur ein Netzgerät, womit ich alles betreibe.
Mache ich vielleicht was falsch? Was sollte man generell beachten?

Gruß, Yaro
Gast #1663606
Lesenswert?

> Den richtigen SPI-Modus verwenden.
Das mache ich... Sonst würde ja überhaupt nix sinvolles übertragen 
werden.

>Was für eine Leitung?
15cm Flachband-Kabel.

>Hast du Serienterminierungswiderstände eingebaut?
Nein, sollte ich das? Wie groß sollen sie bemessen sein?

Gruß, Yaro
#1663642
Lesenswert?

Flachbandkabel sind der EMV-tot Deiner Schaltung ... da kann sich alles 
mögliche einkoppeln.


Wenn Du da mehrere kHz überträgst, kommst schon in den kritischen 
Bereich. Da kann Abhilfe durch mehrere Mittel geschaffen werden:
- differential pairs (redundante Pegelübertragung und Auswertung der 
Differenz als Nutzsignal siehe RS485)
- 1 Masseleitung parallel zu jeder Signalleitung im Flachbandkabel, 
sodass die Signale immer einen Masse-Bezug "sehen"
- galv. Trennung
- je nach dP/dt (Laständerung über der Zeit) kann es nötig sein, den 
Schaltungsteil hinter dem Flachbandkabel niederohmiger anzubinden, da 
die Ausgleichströme für Spannungsabfall über deinen Versorungsleitungen 
sorgen können. Das kann wiederum zu Fehlinterpretation Deiner 
digital-Pegel führen.

Terminierung
Je nach Bustopologie könntest Deine SPI-Leitungen auch noch terminieren. 
Dazu empfiehlt sich, die Leitungen so auszuprägen, dass überhaupt eine 
richtige Impedanz da ist (Massfläche, Leiterbreite, Leiterabstand zu 
Fläche, ...). Dann kannst beim Leitungstreiber einen Serienwiderstand 
einbauen, um eine Anpassung an die Impedanz zu erreichen. Der Empfänger 
ist hochohmig und sollte daher gegen eine Versorgungsspannung mit einem 
Pullup/Down abgerschlossen sein - jenachdem, welcher der Ruhepegel ist.

Gruß,

Kay
Gast #1663682
Lesenswert?

Yaro schrieb:
> unabhängig von der Sendegeschwindigkeit (immer unter 2MHz).


Die Übertragungsrate ist irrelevant !!
Die AVR senden immer mit der gleichen steilen Flanke.
Ab 15cm Leitungslänge wird es hier kritisch.

Bei SPI würde ich die AC Terminierung vorschlagen.
Siehe Wiki.
Flachbandkabel hat es gerne, wenn Du es mit GND, Signal, GND, Signal, 
GND... belegst.
#1663705
Lesenswert?

Falk Brunner schrieb:
> Ist schon komisch, dass Millionen von
> Festplatten seit Jahrzehnten mit Flachbandkabeln super funktionieren.

Für die jüngeren, die das vielleicht schon alles nicht mehr kennen 
(;-)): SCSI-3 (Ultra-SCSI) dürfte da im wesentlichen die Spitze dessen 
gewesen sein, wo noch ganz normale Flachbandkabel (ohne die "Tricks" wie 
jede zweite Ader Masse etc.) verwendet wurden. Das waren 20MHz Bustakt 
bei bis zu 3m Kabellänge. Saubere (aktive) Terminierung war da dann 
natürlich Pflicht! Bei SCSI-1/2 (5 MHz bzw. 10 MHz) mit kurzem Kabel 
(<50cm) lief es ggf. auch schonmal ohne Terminierung (sogar im Prinzip 
stabil, man durfte nur nichts am Rechner verändern ;-).

PATA hat es bis UDMA33 mit normalen Flachbandkabeln gebracht, das waren 
dann 8 MHz Bustakt (mit DDR).

Andreas
#1663731
Lesenswert?

Yaro schrieb:
> Dann werde ich zuerst jede zweite Leitung GND legen, wenns noch
> Störungen gibt, dann Terminierung.

Nein, umgekehrt. Erstmal um die Terminierung kümmern. GND-Leitungen mit 
der Giesskanne verteilen hilft genau garnicht gegen Signalreflektionen.

Andreas

PS: Naja, vielleicht ein bisschen, wegen erhöhter Kapazität und damit 
Abflachung der Flanken. Trotzdem bleibt's dabei, erstmal Terminierung, 
wenn das nicht reicht, kann man weiterschauen.
Gast #1663859
Lesenswert?

> > Den richtigen SPI-Modus verwenden.
Das mache ich... Sonst würde ja überhaupt nix sinvolles übertragen
werden.

Das würde ich so pauschal nicht behaupten. Je nach Setup- oder Hold-Time 
der Eingänge KANN es auch bei falschen Modus laufen- MUSS aber nicht. 
Wenn dann noch Signalverzerrungen und/oder Laufzeiten dazu kommen, 
geht's halt schief.
#1663873
Lesenswert?

@ Falk Brunner (falk)
Ich geb Dir schon Recht ... bestehende Platinen funktionieren oft schon 
sehr lange. Auf neuere Platinen kommen jedoch auch neuere Bauteile mit 
steileren Flanken, sie werden in raueren Umgebungen eingesetzt und auf 
vielen alten Platinen sind gar keine uCs  Netzteile  etc. verbaut...
Die EMV-Betrachtung hat durchaus ihre Berechtigung, was man leidvoll 
erkennt, wenn man mal die erste EMV-Optimierung eines Produktes 
durchlebt hat. Man erkennt es auch, wenn das liebevoll erstellte Produkt 
plötzlich bei diesem einen Kunden an dieser einen Stelle in der Anlage 
immer wieder ausfällt.

@  Andreas Ferber (aferber)
Wenn ich mich recht entsinne, gab es da in der Übertragungs-Schicht auch 
großzügige Hemmingdistanzen und selbstheilende Datenkodierung mit 
reichlich Redundanz ;)

@  Yaro (Gast)
wie Andreas Ferber (aferber) schon schreibt ... versuch mal die 
Impedanzanpassung. Du könntest es zunächst mit 100R bei den 
Treiber-Ausgängen versuchen. Das ist mal ein Versuchswert - vielleicht 
ist er bei Dir auch höher.

Sender                                           Empfaenger
-------+                                         +--------+
       |                                         |        |
       O--100R-----------Leitung----------+------O        |
       |                                  |      |        |
---O---+                              C   ==     +---O----+
   |                                      |          |
   |                                      R          |
   |                                      |          |
  GND                                    GND        GND
#1663904
Lesenswert?

Kay Imperator schrieb:
> Wenn ich mich recht entsinne, gab es da in der Übertragungs-Schicht auch
> großzügige Hemmingdistanzen und selbstheilende Datenkodierung mit
> reichlich Redundanz ;)

Bei SCSI? Nö. Die einzige Absicherung gegen Übertragungsfehler war ein 
Parity-Bit. Selbst ein simpler CRC kam erst sehr viel später mit 
Ultra-160-SCSI, das war aber dann auch schon LVD. Im Highend-Umfeld 
(Grossrechner etc.) hat SCSI aber auch von Anfang an mit differentieller 
Übertragung gearbeitet (damals noch High Voltage Differential), alleine 
schon, weil damit längere Kabel (bis 25m) möglich waren.

ATA hatte dagegen nichtmal Parity. Erst mit Ultra-ATA/33 im UDMA2-Modus 
kam dann ein CRC dazu.

Eine Fehlerkorrektur kennen beide nicht (nur Recovery - der Host sendet 
halt die Daten noch einmal), wäre aber IMO in diesem Fall auch 
überflüssiger Aufwand, solange Fehler nicht allzu häufig auftreten.

Andreas
Gast #1664066
Lesenswert?

Ich werde es dann zuerst mit Serienterminierung versuchen, einen 
Kondensator gegen GND werde ich nur dann drauf machen, wenns nicht 
anders geht.
Ansonsten eben noch jede zweite Leitung GND, ist ja auch eine kleine 
Erhöhung der Kapazität.

Danke für eure Hilfe!

Gruß, Yaro
Moderator (Firma: Titel) Persönliche Seite #1664079
Lesenswert?

>> Den richtigen SPI-Modus verwenden.
> Das mache ich...
> Sonst würde ja überhaupt nix sinvolles übertragen werden.
Ja, da kann man sich aber arg täuschen...
Ich behaupte dass genau so was wie du es beschreibst passieren kann, 
wenn du den falschen SPI-Modus verwendest. Denn wenn Sample- und 
Shift-Flanke vertauscht sind, hilft dir nur noch eine geringfügig 
unterschiedliche Laufzeit....  :-o
Gast #1664100
Lesenswert?

Die beschriebenen Probleme treten z.T. auch auf, wenn ich zwei ATmegas 
verwende, und genau gleich initialisiere (nur eben ein Master und ein 
Slave).
Sample und Shift-Flanken sind dann eindeutig gleich gesetzt.

Habe aber grade gemerkt, dass es (in meinen jetzigen Aufbauten) nur 
Probleme gibt, wenn ich unterschiedlich getaktete Controller miteinander 
Kommunizieren lasse. Ist es so, dass schneller getaktete ATmegas auch 
steilere Flanken machen? Oder ist das nur vom internen Treiber abhängig?

Gruß, Yaro
Gast #1664111
Lesenswert?

Noch was... Die Probleme, die auftreten sind, dass Bytes z.t. nicht 
zuendegeshiftet werden. Reflektionen (auf der SCK-Leitung) würden aber 
doch genau zum Gegenteil führen... es würde zu viel geshiftet!
Langsamerer prescaler hilft wie gesagt auch nicht.

Gruß, Yaro
Gast #1664134
Lesenswert?

Nein, nicht double Speed.

Das, wo es vorkommt, ist z.B. ein LCD-Debug-Board. Habe ein Board, auf 
dem ich ein LCD-Display drauf habe, was ich mit I2C und SPI ansteuern 
kann.

Ansteuerroutinen (Ausschnitt):
1
void lcdSPIInit(uint8_t operation){ //1: save SPI-settings, Init lcd SPI; 0: restore SPI
2
  static uint8_t spcr, spiDDR, csDDR;
3

4
  if(operation == 1){
5
    spcr = SPCR;
6
    spiDDR = SPI_DDR;
7
    csDDR = CHIPSELECT_DDR;
8

9
    CHIPSELECT_DDR |= (1<<CHIPSELECT_PIN);
10

11
    SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR0);
12
    SPI_DDR |= (1<<MOSI_PIN) | (1<<SCK_PIN);
13
//    SPI_DDR &= ~(1<<MISO_PIN);
14
    CHIPSELECT_PORT &= ~(1<<CHIPSELECT_PIN);
15
  }else if(operation == 0){
16
    CHIPSELECT_PORT |= (1<<CHIPSELECT_PIN);
17
    _delay_us(1);
18
 //   CHIPSELECT_DDR = csDDR;
19
    SPI_DDR = spiDDR;
20
    SPCR = spcr;
21
  }
22

23
}
24

25

26
void lcdSPI_string(char *data){    //Char-Array ausgeben
27
  lcdSPIInit(1);
28
  while(*data){
29
    SPDR = *data;
30
    while(!SPI_READY);
31
    CHIPSELECT_PORT |= (1<<CHIPSELECT_PIN);
32
    _delay_us(10);
33
    CHIPSELECT_PORT &= ~(1<<CHIPSELECT_PIN);
34
    data++;
35
  }
36
  SPDR = '\0';
37
  while(!SPI_READY);
38
  CHIPSELECT_PORT |= (1<<CHIPSELECT_PIN);
39
  _delay_us(10);
40
  CHIPSELECT_PORT &= ~(1<<CHIPSELECT_PIN);
41
  SPDR = 2;        //Steuerzeichen
42
  while(!SPI_READY);
43
  lcdSPIInit(0);
44
  _delay_ms(5);
45
}

Empfängerroutinen (Ausschnitt):
1
void SPIInit(void){
2
  DDRB &= ~0x2C;  //SCK,MOSI,SS is Input
3
  //DDRB |= 0x10;   //MISO Output
4

5
  SPCR = (1<<SPIE) | (1<<SPE);
6
}
7

8

9
ISR(SPI_STC_vect){
10
  extern uint8_t data, bufpos;
11
  extern char buf[17];
12

13
  data = SPDR;
14

15
  if(data <= 31 && data != 0){
16
    switch(data){
17
      case 1:
18
        lcd_data(buf[0]);
19
      break;
20
      case 2:
21
        lcd_string(buf);
22
      break;
23
      case 3:
24
        lcd_clear();
25
      break;
26
      case 4:
27
        lcd_set_cursor(buf[0]-40, buf[1]-40);
28
      break;
29
      case 5:
30
        PORTC |= 0x08;  //Hintergrundbeleuchtung an
31
      break;
32
      case 6:
33
        PORTC &= ~0x08;  //Hintergrundbeleuchtung aus
34
      break;
35
      default: lcd_string("SPI-ERROR!!");
36
    }
37
    bufpos = 0;
38
  }else if(bufpos < 16){
39
      buf[bufpos++] = data;
40
  }
41
}

Wenn ich die Kabel knicke, oder mit trockenen Fingern die Pins 
überbrücke, kommt es z.T. öfter zu Störungen. Manchmal gibt es auch 
überhaupt keine Störungen.
Hängt auch ein Bisschen von den Platinen ab, von denen aus ich sende 
(bei gleichem Controller)

Gruß, Yaro

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