Forum: Mikrocontroller und Digitale Elektronik SPI Master Dataübertragung über MISO avr-mc(Atmega2560-Atega328u)


von hobbyflieger (Gast)


Angehängte Dateien:

Lesenswert?

hallo
Ich habe ein Problem mit SPI-Interface. Die Daten die von Slave gesendet 
wird, werden nicht richtig über MISO-Leitung Übertragen. Das Problem 
Wahrscheinlich mit SPDR-Register. Im Anhang ist ein Bild, das vergleicht 
die Data auf Slave und Master Seite. Die Daten auf Slave-Seite sind 
richtig, aber die auf Master-Seite sind verfälscht. Manchmal gibt 5 aus 
und 5 ist die Zahl die ich von Master zu Slave schicke. kann jemand mir 
schreiben, wie kann ich das Problem aufheben

Vielen Dank

mein Code:

Masterseite:

void KONF_SPI_MASTER() {
  DDRB = (1 << DDB0) | (1 << DDB1) | (1 << DDB2);
  DDRL |= (1 << DDL3); // SS(NANO) als Ausgang

  SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0);
  SPCR &= ~((1 << SPR1) | (1 << CPOL) | (1 << CPHA));
  SPSR = 1 << SPI2X;
  PORTB |= (1 << PORTB0); // SS (MCP3204)  HIGH setzen
  PORTL|=(1<<PORTL3);  //SS (NANO) High setzen
}

void READ_Data_NANO(uint8_t DW) {

  PORTL&=~(1<<PORTL3);  //SS (NANO) lows etzen

  SPDR = DW;
  while (!(SPSR & (1 << SPIF)));
  result_MISO[0]=SPDR;
  SPDR = DW;
  while (!(SPSR & (1 << SPIF)));// warten
 result_MISO[1]=SPDR;
 SPDR = DW;
  while (!(SPSR & (1 << SPIF))); // warten
 result_MISO[2]=SPDR;
 SPDR = DW;
 while (!(SPSR & (1 << SPIF))); // warten
 result_MISO[3]=SPDR;
 SPDR = DW;
 while (!(SPSR & (1 << SPIF))); // warten
 result_MISO[4]=SPDR;

}




SLAVE-Seite

  void Konf_SPI_SLAVE() {
    DDRB |= (1 << DDB4); // MISO als Ausgang
    SPCR |= (1 << SPE);
  }


  while (1) {

      while (!(SPSR & (1 << SPIF))); //warten
      SPDR = ADC_Ergebnisse[0];
      while (!(SPSR & (1 << SPIF))); //warten
      SPDR = ADC_Ergebnisse[1];
      while (!(SPSR & (1 << SPIF))); //warten
      SPDR = ADC_Ergebnisse[2];
      while (!(SPSR & (1 << SPIF))); //warten
      SPDR = ADC_Ergebnisse[3];
      while (!(SPSR & (1 << SPIF))); //warten
      SPDR = ADC_Ergebnisse[4];
}

von Joe F. (easylife)


Lesenswert?

CPOL und CPHA ist auf Slave Seite nicht explizit konfiguriert.
Der Defaultwert könnte anders sein, als beim Master eingestellt.

von hobbyflieger (Gast)


Lesenswert?

Vielen Dank aber hat leider nicht geholfen. er liest falsche Daten aus 
SPDR.

, K0= 10, K1= 23, K2= 13, K3= 168, K4= 93
, K0= 8, K1= 21, K2= 13, K3= 167, K4= 93
, K0= 9, K1= 21, K2= 12, K3= 167, K4= 93
, K0= 9, K1= 22, K2= 13, K3= 167, K4= 93
, K0= 10, K1= 21, K2= 12, K3= 167, K4= 93
, K0= 10, K1= 20, K2= 13, K3= 5, K4= 5
, K0= 166, K1= 93, K2= 5, K3= 5, K4= 5
, K0= 9, K1= 20, K2= 13, K3= 167, K4= 93
, K0= 10, K1= 20, K2= 13, K3= 166, K4= 93
, K0= 8, K1= 21, K2= 13, K3= 167, K4= 93
, K0= 9, K1= 20, K2= 13, K3= 167, K4= 93
, K0= 9, K1= 21, K2= 13, K3= 168, K4= 93
, K0= 8, K1= 18, K2= 13, K3= 166, K4= 93
, K0= 9, K1= 19, K2= 12, K3= 166, K4= 93
, K0= 9, K1= 18, K2= 12, K3= 167, K4= 93
, K0= 7, K1= 5, K2= 5, K3= 5, K4= 5
, K0= 21, K1= 5, K2= 5, K3= 5, K4= 168
, K0= 93, K1= 8, K2= 20, K3= 12, K4= 166
, K0= 93, K1= 8, K2= 20, K3= 12, K4= 167
, K0= 93, K1= 8, K2= 20, K3= 12, K4= 166

von Joe F. (easylife)


Lesenswert?

Ja, ich habe auch gerade gesehen, dass die Einstellung gleich ist. Beim 
Master löscht du die Bits explizit, beim Slave werden sie nicht gesetzt.
Allerdings sind auch die Clock-Rate Einstellungen unterschiedlich.
Mit welchen Frequenzen arbeiten Master und Slave jeweils (Oscillator)?
SCK Master ist auf fosc/8 eingestellt, SCK Slave auf fosc/4

Und: wie sieht die Verbindung der beiden Seiten aus? Langes Kabel? Wenn 
ja, wie lang?

: Bearbeitet durch User
von hobbyflieger (Gast)


Lesenswert?

die CLOCK-Einstellung wird lediglich bestimmt durch den 
Master-Teilnehmer. Über SCK-Pin kann ein Slave Teilnehmer. Ich verstehe 
nicht warum du denkst, dass die beide unterschiedliche Frequenzen oder 
Clock-Einstellung haben.

Wenn SCK-Einstellung mit fosc/8 ist, dann wird für beide gleich.

von hobbyflieger (Gast)


Lesenswert?

Kabel ist ungefähr 15 cm

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

hobbyflieger schrieb:
> und 5 ist die Zahl die ich von Master zu Slave schicke. kann jemand mir
> schreiben, wie kann ich das Problem aufheben

 DaBla lesen ?
SS Pin Functionality
1
If SS is configured as an input, it must be held high to ensure Master SPI operation. If the SS pin
2
is driven low by peripheral circuitry when the SPI is configured as a Master with the SS pin

 When du PB.0 schon nicht als SS Pin benutzt, dann wenigstens als
 Ausgang definieren oder Eingang mit Pullup.

: Bearbeitet durch User
von Joe F. (easylife)


Lesenswert?

hobbyflieger schrieb:
> die CLOCK-Einstellung wird lediglich bestimmt durch den
> Master-Teilnehmer. Über SCK-Pin kann ein Slave Teilnehmer. Ich verstehe
> nicht warum du denkst, dass die beide unterschiedliche Frequenzen oder
> Clock-Einstellung haben.

Jein. Der Master gibt natürlich die Clock vor. Ich weiss aber nicht, wie 
SPI bei deinem Prozessor genau implementiert ist. Wenn man dem Slave 
sagt, du hast mit max. 500 KHz zu rechnen, und jetzt kommt eine 1 MHz 
Clock, kann es sein, dass die SPI Implementierung damit nicht klar 
kommt.

Ich würde mal versuchen, die Clock so weit runter zu drehen wie möglich 
(auf Master Seite).

z.B. auf fosc/128
1
SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0) | (1 << SPR1);
2
SPCR &= ~((1 << CPOL) | (1 << CPHA));
3
SPSR &= ~(1 << SPI2X); // SPI2X = 0

von hobbyflieger (Gast)


Lesenswert?

was meinst du, ich verstehe dich nicht. ich habe oben SS als Ausgang 
definiert, dass bei Datenübertragung SS auf LOW und danach wieder auf 
HIGH setzen. PORTL|=(1<<PORTL3); habe ich auch in meiner Code nach der 
SPI-Funktion.

von hobbyflieger (Gast)


Angehängte Dateien:

Lesenswert?

weniger Fehler aber nicht vollständig weg(siehe Anhang)

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

hobbyflieger schrieb:
> was meinst du, ich verstehe dich nicht. ich habe oben SS als Ausgang
> definiert, dass bei Datenübertragung SS auf LOW und danach wieder auf
> HIGH setzen. PORTL|=(1<<PORTL3); habe ich auch in meiner Code nach der
> SPI-Funktion.

 Sorry, übersehen.
 Aber du kannst trotzdem beim Master MSTR bit in SPCR checken.

 Ansonsten wirklich vorerst so langsam wie nur möglich und ohne
 2x probieren.

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

Ändert sich etwas, wenn am Ende von READ_Data_NANO /SS zurückgesetzt 
wird?

von hobbyflieger (Gast)


Lesenswert?

ich habe gerade mit einem anderen Arduino probiert. das Problem kann 
nicht von Hardware sein. Master gibt immer 5 aus ?????


SPCR:1010011, SPSR:10000000, K0= 9, K1= 20, K2= 5, K3= 166, K4= 93
SPCR:1010011, SPSR:10000000, K0= 8, K1= 21, K2= 5, K3= 168, K4= 93
SPCR:1010011, SPSR:10000000, K0= 9, K1= 22, K2= 13, K3= 168, K4= 93
SPCR:1010011, SPSR:10000000, K0= 9, K1= 21, K2= 12, K3= 166, K4= 5
SPCR:1010011, SPSR:10000000, K0= 8, K1= 23, K2= 14, K3= 168, K4= 93
SPCR:1010011, SPSR:10000000, K0= 8, K1= 22, K2= 13, K3= 5, K4= 93
SPCR:1010011, SPSR:10000000, K0= 8, K1= 19, K2= 11, K3= 165, K4= 93
SPCR:1010011, SPSR:10000000, K0= 7, K1= 21, K2= 13, K3= 167, K4= 93
SPCR:1010011, SPSR:10000000, K0= 7, K1= 22, K2= 5, K3= 168, K4= 93
SPCR:1010011, SPSR:10000000, K0= 8, K1= 20, K2= 12, K3= 166, K4= 93
SPCR:1010011, SPSR:10000000, K0= 8, K1= 21, K2= 12, K3= 167, K4= 93
SPCR:1010011, SPSR:10000000, K0= 8, K1= 5, K2= 12, K3= 167, K4= 5
SPCR:1010011, SPSR:10000000, K0= 9, K1= 20, K2= 13, K3= 166, K4= 5
SPCR:1010011, SPSR:10000000, K0= 8, K1= 22, K2= 13, K3= 168, K4= 93
SPCR:1010011, SPSR:10000000, K0= 8, K1= 20, K2= 12, K3= 166, K4= 93
SPCR:1010011, SPSR:10000000, K0= 8, K1= 20, K2= 12, K3= 166, K4= 93
SPCR:1010011, SPSR:10000000, K0= 7, K1= 20, K2= 5, K3= 166, K4= 93
SPCR:1010011, SPSR:10000000, K0= 9, K1= 22, K2= 5, K3= 169, K4= 93

von hobbyflieger (Gast)


Angehängte Dateien:

Lesenswert?

so sieht die Übertragung auf Leitungen. Grün: SCK, Gelb:MISO

von Joe F. (easylife)


Lesenswert?

Gutes Scope.
Man kann bei deiner Aufnahme leider weder die Spannungsskalierung noch 
die Zeiteinstellung erkennen.
Erkennbar sind aber deutliche Überschwinger.
Setze mal 100 Ohm in die CLK und Datenleitungen (Serienterminierung).
Arbeiten beide Systeme mit der gleichen Versorgungspannung (5V 
vermutlich), oder ist eines davon ein 3.3V System und das andere auf 5V?

Die Terminierungswiderstände immer auf der "sendenden" Seite einbauen.
Also CLK und MOSI auf der Master-Seite, MISO auf der Slave Seite.

: Bearbeitet durch User
von hobbyflieger (Gast)


Angehängte Dateien:

Lesenswert?

so sieht aus mit 100ohm widerstand. das Problem ist aber nicht weg.

von S. Landolt (Gast)


Lesenswert?

Sähe man die kompletten Programme, ließe sich vielleicht mehr sagen.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

hobbyflieger schrieb:
> so sieht die Übertragung auf Leitungen. Grün: SCK, Gelb:MISO

 Da werden aber 6 Bytes übertragen ?

 Und zwar 0x08, 0x16, 0x0E, 0xA8, 0x5D, 0x05

von hobbyflieger (Gast)


Lesenswert?

hier ist meine Code:

--------------------------MASTER: Arduino 
ATMEGA2560----------------------

 while (1) {
    //  dataoutbuff[0] = CHECKSTATE;
    PORTL &= ~(1 << PORTL3);
    READ_Data_NANO (0x10);
    PORTL |= (1 << PORTL3);
    delay(0.1);
  }

void KONF_SPI_MASTER() {
  DDRB |= (1 << DDB0) | (1 << DDB1) | (1 << DDB2);//MISO,SS(MCP3204) 
und SCK als Ausgang
  DDRL |= (1 << DDL3); // SS(NANO) als Ausgang

  SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0) | (1 << SPR1);
  SPCR &= ~((1 << CPOL) | (1 << CPHA));
  SPSR &= ~(1 << SPI2X); // SPI2X = 0

  PORTB |= (1 << PORTB0); // SS auf HIGH setzen

}

void READ_Data_NANO(uint8_t DW) {

  SPDR = DW;    // auf MOSI-Leitung erstes Byte zu MCP3204 senden (start 
Bit,D2-Bit gesendet)
  while (!(SPSR & (1 << SPIF))); // warten bis Übertragung fertig ist
  result_MISO[0] = SPDR;
  SPDR = DW;   // zweites Byte senden(D1-Bit und D0-Bit wird ebenfalls 
gesendet) Kanal auswählen
  while (!(SPSR & (1 << SPIF)));// warten
  result_MISO[1] = SPDR;
  SPDR = DW;  // Leers Datenwort auf MOSI-Leitung gesendet
  while (!(SPSR & (1 << SPIF))); // warten
  result_MISO[2] = SPDR;
  SPDR = DW;  // Leers Datenwort auf MOSI-Leitung gesendet
  while (!(SPSR & (1 << SPIF))); // warten
  result_MISO[3] = SPDR;
  SPDR = DW;  // Leers Datenwort auf MOSI-Leitung gesendet
  while (!(SPSR & (1 << SPIF))); // warten
  result_MISO[4] = SPDR;

}


----------------------------------SLAVE:Arduino 
NANO--------------------------------
  while (1) {

      while (!(SPSR & (1 << SPIF)));
      SPDR = ADC_Ergebnisse[0];
      while (!(SPSR & (1 << SPIF))); //warten
      SPDR = ADC_Ergebnisse[1];
      while (!(SPSR & (1 << SPIF)));
      SPDR = ADC_Ergebnisse[2];
      while (!(SPSR & (1 << SPIF))); //warten
      SPDR = ADC_Ergebnisse[3];
      while (!(SPSR & (1 << SPIF)));
      SPDR = ADC_Ergebnisse[4];

}

void Konf_SPI_SLAVE() {
    DDRB |= (1 << DDB4); // MISO als Ausgang
    SPCR |= (1 << SPE);
  }

von S. Landolt (Gast)


Lesenswert?

Das heißt, diese ADC_Ergebnisse[] stehen auf Null?

von hobbyflieger (Gast)


Lesenswert?

wenn du meinst, das erste Bild, habe die Korrektur gemacht, dass SPI nur 
5 Bytes sendet. ich hatte (while (!(SPSR & (1 << SPIF))); ) nach BYTE 5 
, so hat SPI ein 6.BYTE gesendet. Das zweite Bild zeigt die Übertragung 
mit 5 Bytes, aber das Problem ist trotzdem noch da.

von hobbyflieger (Gast)


Lesenswert?

ich habe 4 AD-Wandler(10Bit). Ich speichere jeweils die Daten in 
ADC_ergebnisse[i](nur 8 Bit), die restliche 2 Bits für den jeweiligen 
AD-Wandler wird in ADC_ergebnisse[4] gespeichert

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

hobbyflieger schrieb:
> wenn du meinst, das erste Bild, habe die Korrektur gemacht, dass SPI nur
> 5 Bytes sendet. ich hatte (while (!(SPSR & (1 << SPIF))); ) nach BYTE 5

 Ok, wieso ist dann beim zweiten Bild result_MISO[3] == 0  ?
 Dieser Wert taucht doch nirgends auf in deinen Tabellen.
 Slave soll doch definierte Werte senden, so weisst du wenigstens was
 der Master kriegen soll.

 So ist es nur rumrätseln - in deiner Tabelle stehen ganz andere Werte
 als auf dem Oszi...

 Lass doch ADC vorerst raus.

von S. Landolt (Gast)


Lesenswert?

Also ich weiß nicht, unter 'komplette Programme' verstehe ich etwas 
anderes.


Manche kennen vielleicht diese Geschichte von Paul Watzlawick noch 
nicht, ihnen zur Unterhaltung:
  Um Mitternacht kriecht ein Betrunkener suchend auf allen Vieren unter 
einer Straßenlaterne herum. Kommt ein Polizist vorbei: "Sie! Was machen 
Sie denn da?" "Ich suche meinen Hausschlüssel." Jetzt suchen beide. Nach 
erfolglosen zehn Minuten fragt der Polizist: "Sagen Sie mal, sind Sie 
sicher, dass Sie Ihren Schlüssel hier verloren haben?" Kommt als 
Antwort: "Nein, nicht hier, sondern dort drüben. Aber dort ist es viel 
zu dunkel zum Suchen."

von hobbyflieger (Gast)


Angehängte Dateien:

Lesenswert?

er soll nur 51 senden über MISO-Leitung und 4
 über MOSI-Leitung.

Hier sind die Ergebnisse auf MISO-Leitung, sind mit 4 verseucht
SPCR:1010011, SPSR:0, K0= 51, K1= 51, K2= 51, K3= 51, K4= 51
SPCR:1010011, SPSR:0, K0= 51, K1= 51, K2= 51, K3= 51, K4= 51
SPCR:1010011, SPSR:0, K0= 51, K1= 51, K2= 51, K3= 4, K4= 51
SPCR:1010011, SPSR:0, K0= 51, K1= 51, K2= 51, K3= 51, K4= 51
SPCR:1010011, SPSR:0, K0= 51, K1= 51, K2= 51, K3= 51, K4= 51
SPCR:1010011, SPSR:0, K0= 51, K1= 51, K2= 4, K3= 51, K4= 51


das Problem dass Slave falsche Ergebnisse sendet (siehe Anhang Grün: 
MOSI , Gelb: MISO)

Code von Slave:
//------------------------SLAVE-------------------------------------
Konf_SPI_SLAVE();
while (1) {

    for (uint8_t i = 0; i < 5; i++) {
      while (!(SPSR & (1 << SPIF)));
      uint8_t data_in= SPDR;
      SPDR=51;
    }
  }

void Konf_SPI_SLAVE() {
  DDRB |= (1 << DDB4); // MISO als Ausgang
  SPCR |= (1 << SPE);
}


//------------------------------Master--------------------

void KONF_SPI_MASTER() {
  DDRB |= (1 << DDB0) | (1 << DDB1) | (1 << DDB2);//MISO,SS(MCP3204) 
und SCK als Ausgang
  DDRL |= (1 << DDL3); // SS(NANO) als Ausgang

  SPCR |= (1 << SPE) | (1 << MSTR) | (1 << SPR0) | (1 << SPR1);
  SPCR &= ~((1 << CPOL) | (1 << CPHA));
  SPSR &= ~(1 << SPI2X); // SPI2X = 0

  PORTB |= (1 << PORTB0); // SS auf HIGH setzen

}

void READ_Data_NANO(uint8_t DW) {

  for (uint8_t i = 0; i < 5; i++) {
    SPDR = DW;
    while (!(SPSR & (1 << SPIF)));
    result_MISO[i] = SPDR;
  }
}


KONF_SPI_MASTER() ;
  while (1) {

    PORTL &= ~(1 << PORTL3);
    READ_Data_NANO (0x4);
    PORTL |= (1 << PORTL3);
}

von hobbyflieger (Gast)


Lesenswert?

ich schicke dir doch meine ganze Code und auch Bilder. Dunkel ist also 
nicht :)

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

hobbyflieger schrieb:
> er soll nur 51 senden über MISO-Leitung und 4
>  über MOSI-Leitung.

 Nein.
 Master sendet ständig z.B. 4 definierte Werte.
 Slave sendet diese vorerst nur zurück - nicht mehr und nicht weniger.

 Wenn das ohne Fehler abgeht, kann man weiter sehen.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

hobbyflieger schrieb:
> das Problem dass Slave falsche Ergebnisse sendet (siehe Anhang Grün:
> MOSI , Gelb: MISO)

 Ich sehe da 13 x OK, 1 x Fehler, 13 x OK, 1 x Fehler...

von hobbyflieger (Gast)


Angehängte Dateien:

Lesenswert?

ich verstehe nicht was du meinst aber ich habe heute alles mögliche 
versucht.

ich habe nochmal die SPI-Code rauskopiert und neu hochladen.
Im Anhang sieht man dass das Problem noch da ist.

meine komplette Code lautet.


//-------------------------------Masterseite:ATMEGA2560----------------- 
---

 uint8_t result_MISO;

void setup() {
  KONF_SPI_MASTER() ;
}


void loop() {

    PORTL &= ~(1 << PORTL3);
    READ_Data_NANO (0x4);
    PORTL |= (1 << PORTL3);
}


void KONF_SPI_MASTER() {

  DDRB |= (1 << DDB0) | (1 << DDB1) | (1 << DDB2);
  DDRL |= (1 << DDL3); // SS(NANO) als Ausgang
  SPCR |= (1 << SPE) | (1 << MSTR) | (1 << SPR0) | (1 << SPR1);
  SPCR &= ~((1 << CPOL) | (1 << CPHA));
  SPSR &= ~(1 << SPI2X); // SPI2X = 0
  PORTB |= (1 << PORTB0); // SS auf HIGH setzen

}

void READ_Data_NANO(uint8_t DW) {
  for (uint8_t i = 0; i < 5; i++) {
    SPDR = DW;
    while (!(SPSR & (1 << SPIF)));
   result_MISO = SPDR;
  }
}

//------------------------SLAVE_NANO------------------------------------ 
-

void Konf_SPI_SLAVE();
void setup() {

Konf_SPI_SLAVE();
}
void loop(){


    for (uint8_t i = 0; i < 5; i++) {
      while (!(SPSR & (1 << SPIF)));
      uint8_t data_in= SPDR;
      SPDR=51;

  }
}

void Konf_SPI_SLAVE() {
  DDRB |= (1 << DDB4); // MISO als Ausgang
  SPCR |= (1 << SPE);
}

von Joe F. (easylife)


Lesenswert?

Tja, weist schon relativ eindeutig auf ein Problem des Slaves hin.

Vielleicht mal so probieren:
1
for (uint8_t i = 0; i < 5; i++) {
2
  SPDR = 51;
3
  while (!(SPSR & (1 << SPIF)));
4
  uint8_t data_in = SPDR;
5
}

http://www.avrfreaks.net/forum/spif-flag-spi-interface

: Bearbeitet durch User
von HobbyFlieger (Gast)


Lesenswert?

Vielen Dank für deine Hilfe.

das Problem vielleicht von Arduino NANO. Mit Arduino UNO sind die Fehler 
weniger 1 Fehler/300 Byte.

wenn ich schreibe, wie du mir vorgeschlagen hast sind die Fehler 30 
Fehler/300Byte.

es scheint mir aus, dass die Fehlübertragung nicht vollständig beseitigt 
werden kann.

von Joe F. (easylife)


Lesenswert?

Wie ist den die SS Leitung des Slaves angeschlossen? Vielleicht floatet 
die ja in der Gegend rum und stört die Kommunikation...?

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.