Forum: Mikrocontroller und Digitale Elektronik Probleme mit SPI bei AVR-µC


von Ali A. (undertaker_bayern)


Angehängte Dateien:

Lesenswert?

Seit 5 Tage bin ich auf der Suche nach einem Fehler, aber vergeblich 
ohne Erfolg. Kann jemand schreiben, warum Slave falsche Informationen 
sendet. der Slave muss 5 Bytes(1,3,7,15,31) senden. er sendet aber nicht 
die Daten in die richtige Reihenfolge. Außerdem er sendet manchmal die 
Zahl 4, die vom Master zu Slave über MOSI-Leitung geschickt wurde.

es scheint dass die Daten falsch in SPDR-Register gespeichert werden. Im 
Anhang schicke ich die Ergebnisse, die ich über die MISO-Leitung und auf 
der Masterseite bekomme.

Danke

mein Code:

-------------------------Master: Arduino Mega 
---------------------------
1
uint8_t result_MISO[5];
2
3
void setup() {
4
  Serial.begin(9600);
5
  KONF_SPI_MASTER() ;
6
}
7
void loop() {
8
  
9
  PORTL &= ~(1 << PORTL3);
10
  READ_Data_NANO (0x4);
11
  PORTL |= (1 << PORTL3);
12
  
13
  for (uint8_t i = 0; i < 5; i++) {
14
    Serial.print(",");
15
    Serial.print(result_MISO[i]);
16
  }
17
  Serial.println("");
18
}
19
20
21
void KONF_SPI_MASTER() {
22
  DDRB |= (1 << DDB0) | (1 << DDB1) | (1 << DDB2);
23
  DDRL |= (1 << DDL3); // SS(NANO) als Ausgang
24
  SPCR |= (1 << SPE) | (1 << MSTR);
25
  SPCR &= ~((1 << CPOL) | (1 << CPHA));
26
  //SPSR|=(1<<SPR0);
27
  //SPSR |= (1 << SPI2X); // SPI2X = 0
28
  PORTB |= (1 << PORTB0); // SS auf HIGH setzen
29
}
30
31
void READ_Data_NANO(uint8_t DW) {
32
  for (uint8_t i = 0; i < 5; i++) {
33
    SPDR = DW;
34
    while ((SPSR & (1 << SPIF))==0);
35
    result_MISO[i] = SPDR;
36
  }
37
}

//--------------------------SLAVE: Arduino 
NANO----------------------------
1
void Konf_SPI_SLAVE();
2
uint8_t probe[5];
3
uint8_t data_in; 
4
5
void setup() {
6
Konf_SPI_SLAVE();
7
 probe[0]= 1;
8
  probe[1]= 3;
9
   probe[2]= 7;
10
    probe[3]= 15;
11
     probe[4]= 31;
12
}
13
void loop(){
14
  
15
    for (uint8_t i = 0; i < 5; i++) {
16
      while ((SPSR & (1 << SPIF))==0);
17
      SPDR= probe[i];
18
      data_in= SPDR;            
19
  }
20
}
21
void Konf_SPI_SLAVE() {
22
  DDRB |= (1 << DDB4); // MISO als Ausgang
23
  SPCR |= (1 << SPE);
24
}
--------------------------------------------------------------------

von Kara Ben Nemsi (Gast)


Lesenswert?

Salem aleikum Ali,

steht vielleicht das Data Order bit im SPCR falsch?!

von Ali A. (undertaker_bayern)


Lesenswert?

ich denke nicht, dass das Problem mit dem Bit DORD zu tun

so ist die Beide Register bei mir definiert.

SPCR=1010000, SPSR=0
SPCR=1010000, SPSR=0
SPCR=1010000, SPSR=0
SPCR=1010000, SPSR=0
SPCR=1010000, SPSR=0
SPCR=1010000, SPSR=0
SPCR=1010000, SPSR=0
SPCR=1010000, SPSR=0
SPCR=1010000, SPSR=0
SPCR=1010000, SPSR=0
SPCR=1010000, SPSR=0

von S. Landolt (Gast)


Lesenswert?

an Hobbyflieger

Joe Easylife hat einen nach meiner Meinung guten Tipp gegeben, nämlich 
floatende und/oder übersprechende SPI-Leitungen. Also erstmal diese 
überprüfen, am besten direkt von uC-Pin zu uC-Pin messen.

von mario eduardo (Gast)


Lesenswert?

Ich hatte mal Zoff beim SPI weil die Spannungsversorgung mieserabelst 
war.
Oszi nehmen und Vcc ansehen!

lg Mario

von S. Landolt (Gast)


Lesenswert?

>      while ((SPSR & (1 << SPIF))==0);
>      SPDR= probe[i];
>      data_in= SPDR;
Und auch hier hatte Joe schon angemerkt, dass im Slave das Laden von 
SPDR natürlich vor dem Transfer stattfinden muss, also
1
      SPDR= probe[i];
2
      while ((SPSR & (1 << SPIF))==0);
3
      data_in= SPDR;

von Ali A. (undertaker_bayern)


Lesenswert?

Damals hat er einen Tipp gegeben, dass ich die SS-Leitung prüfen soll 
und das habe ich gemacht. es war soweit alles in Ordnung.
Ich weiß es  ob ich damals die Leitung richtig geprüft habe, da ich kein 
elektrotechniker bin und das macht alles schwierger.   Kannst du 
vielleicht  erklären, wie ich sicher sein kann, dass die Leitungen nicht 
uebersprechend oder floatend sind   Danke

von Ali A. (undertaker_bayern)


Lesenswert?

Ich habe auch so mal probiert.  Es war noch schlechter( siehe Bild)

von Pandur S. (jetztnicht)


Lesenswert?

Allenfalls stimmt das timing auch nicht. Wir wissen leider nicht um 
welches Device es geht. Gewisse Hersteller, wie Analog Devices erwarten 
dass man jedes Wort des Datenblattes gelesen und verstanden hat. 
Ploetzlich muss der CS waehrend des Pulses weg, und nicht erst nachher.

also mit dem Oszilloskop jedes Bit inkl. Timing nachpruefen und mit dem 
Datenblatt vergleichen.

: Bearbeitet durch User
von Jim M. (turboj)


Lesenswert?

Konfiguriere mal den Master langsamer:
1
 SPCR = (1 << SPE) | (1 << MSTR) | ( 1<<SPR1) | (1<<SPR0);

Könnte nämlich sein dass Du den Slave einfach überfährst.

von S. Landolt (Gast)


Lesenswert?

an Hobbyflieger

Außer dem, was ich bereits schrieb, fällt mir nichts weiter ein, 
Ausnahme: an dem großen 2560 sind sicher noch einige Pins frei, da würde 
ich probeweise mal das /SS auf einen anderen Port legen, also weg von L.

von SPI Übertrager (Gast)


Lesenswert?

Hi,

läuft es inzwischen?

Es gab ja schon den konstruktiven Hinweis

>Und auch hier hatte Joe schon angemerkt, dass im Slave das Laden von
>SPDR natürlich vor dem Transfer stattfinden muss, also ...

Das ist natürlich richtig. Wenn es aber nur das wäre, dann hätte der 
Master ja folgendes protokollieren müssen:

 ,x,1,3,7,15
,31,1,3,7,15
,31,1,3,7,15   usw.

Er hat aber
,4,15,31,1,3
,7,15,31,1,3
,7,15,31,1,3 usw protokolliert.
Damit am Master die 15 kommen kann, muss die Schleife beim Slave schon 
bis i=3 gelaufen sein.

Das bedeutet, Master und Slave laufen nicht synchron. Damit die 
Übertragung  fehlerfrei startet, muss der Slave schon im ersten 
Durchlauf der for-Schleife innerhalb der while Schleife warten (vorher 
sollte er schon den ersten Wert in das SPDR Register geschrieben haben), 
wenn auf dem Master das SPDR-Register beschrieben wird.

Da die 15 als 2. Wert zu sehen ist, muss das SPIF-Bit auf dem Slave 
schon 4 mal als high erkannt worden sein. Also ist zu vermuten, dass der 
Start nicht synchronisiert wird.

Während des weiteren Ablaufs protokolliert der Master dann auch noch 
einige Male die 4. Das deutet ebenfalls darauf hin, dass vom Slave kein 
Wert bereitgestellt wurde. Da das gezeigte Programm ja nicht vollständig 
ist, weiß man nicht, was der Slave sonst noch so treibt.

Also 1. Maßnahme: prüfen, mit welchem Takt der Slave wirklich läuft, ob 
dort also auch die Bedingung Takt<=F_CPU/4 eingehalten ist. 2. Maßnahme: 
die richtigen Anfangsbedingungen schaffen.

Dann gab es noch den Hinweise auf den für SS verwendeten Port. Habe ich 
zwar nicht verstanden, aber wenn es nur einen Master und einen Slave 
gibt, dann hätte ich beim Master auch den SS-Port genommen. Das ist hier 
PORB0. Dieser Pin wird zwar richtig auf Ausgang gestellt und dann 
unnötig mit High belegt. Aber das sollte so funktionieren und kann 
nichts mit dem Problem zu tun haben. Man sieht ja auch an dem Output des 
Masters, dass die SPI-Übertragung funktioniert, aber immer mal wieder 
nicht wirklich synchron läuft.

Damit die 5 Werte fehlerfrei übertragen werden, muss der Slave den 1. 
Wert schon im ersten Durchlauf der Schleife im SPDR Register 
bereitgestellt haben und auf das SPIF High warten, wenn der Master den 
Dummy Wert (DW) in sein SPDR schreibt und damit die Übertragung startet. 
Wenn der Master-Takt nicht zu schnell für den Slave ist und der Slave 
nicht zu lange durch Interrupt unterbrochen wird, sollte dieses Beispiel 
eigentlich auch funktionieren.

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.