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]; }
CPOL und CPHA ist auf Slave Seite nicht explizit konfiguriert. Der Defaultwert könnte anders sein, als beim Master eingestellt.
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
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
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.
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
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 |
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.
weniger Fehler aber nicht vollständig weg(siehe Anhang)
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
Ändert sich etwas, wenn am Ende von READ_Data_NANO /SS zurückgesetzt wird?
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
so sieht die Übertragung auf Leitungen. Grün: SCK, Gelb:MISO
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
so sieht aus mit 100ohm widerstand. das Problem ist aber nicht weg.
Sähe man die kompletten Programme, ließe sich vielleicht mehr sagen.
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
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); }
Das heißt, diese ADC_Ergebnisse[] stehen auf Null?
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.
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
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.
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."
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); }
ich schicke dir doch meine ganze Code und auch Bilder. Dunkel ist also nicht :)
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.
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...
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); }
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
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.