SPI Master Dataübertragung über MISO avr-mc(Atmega2560-Atega328u)

Gast #4889844
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];
}
Angehängte Dateien:
Gast #4889868
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
#4889872
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?
Gast #4889882
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.
(Firma: Vescomp) #4889891
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.
#4889914
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
Gast #4889916
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.
(Firma: Vescomp) #4889945
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.
Gast #4889974
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
#4890013
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.
Gast #4890045
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);
  }
Gast #4890057
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.
(Firma: Vescomp) #4890063
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.
Gast #4890091
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."
Gast #4890130
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);
}
Angehängte Dateien:
Gast #4890155
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);
}
Angehängte Dateien:
Gast #4890343
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.

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