Forum: Mikrocontroller und Digitale Elektronik SPI Slave antwortet unregelmäßig


von Matthias R. (maro0007)


Lesenswert?

Hallo,

Ich programmiere mit CoIDE einen LPC11C24(Master) und will über SPI mit 
einem Freescale MC33972(Slave) kommunizieren. An den MC33972 sind 
Schalter angeschlossen, von denen er ermittelt, ob sie offen oder 
geschlossen sind. Ich kann den MC33972 programmieren, indem ich ihm 24 
Bit über SPI sende und als Antwort ich müsste laut Datenblatt immer die 
Zustände der Schalter bekommen.
Ich habe das versenden in eine Funktion gepackt, die immer wieder 
aufgerufen wird. Mein Problem ist, dass ich sehr unregelmäßig Antworten 
bekommen(z.T. erst nach dem 15000 mal aufrufen der Funktion), und diese 
meist verschieden sind, obwohl sich an den Zuständen der Schalter nichts 
geändert hat. Hat jemand eine Idee, woran das liegen könnte??

Vielen Dank schon mal
Meine Funktion sieht so aus:
1
void SPI(void){ //Abfragen SPI Schnittstelle
2
 uint8_t a=1,Frame1=0, Frame2=0, Frame3=0;
3
 static int zaehler=0;
4
 zaehler++;
5
6
 //1.Byte
7
 while(((LPC_SSP1->SR&0x1F)&0x1C)){}//Testen, ob Transmit  Register leer 
8
                                    //ist
9
 LPC_SSP1->DR=a;     //schreiben Ins Transmit Register
10
 while(LPC_SSP1->SR&0x10){}   //Warten, bis senden abgeschlossen ist
11
 Frame1= LPC_SSP1->DR;   //Abfragen der erhaltenen Bits
12
13
 //2.Byte
14
 while(((LPC_SSP1->SR&0x1F)&0x1C)){}//Testen, ob DR Register leer ist
15
 LPC_SSP1->DR=Frame2;
16
 while(LPC_SSP1->SR&0x10){}
17
 Frame2= LPC_SSP1->DR;
18
19
 //3.Byte
20
 while(((LPC_SSP1->SR&0x1F)&0x1C)){}//Testen, ob DR Register leer ist
21
 LPC_SSP1->DR=Frame3;
22
 while(LPC_SSP1->SR&0x10){}
23
 Frame3 = LPC_SSP1->DR;
24
25
 if(Frame1||Frame2||Frame3) {//Testet,ob etwas anderes als Null
26
   ledinit();aus();    //zurück gesendet wurde
27
     //wait();
28
     //aus();
29
}
30
31
}

: Bearbeitet durch Moderator
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Matthias R. schrieb:
> Mein Problem ist, dass ich sehr unregelmäßig Antworten bekommen
Bei SPI bekommst du immer (und nur!) wenn du etwas sendest 
automatisch eine Antwort. Denn SPI sind nur gekoppelte 
Schieberegister. Warum ist das bei dir nicht der Fall?

> Hat jemand eine Idee, woran das liegen könnte??
Falscher SPI-Mode?
Hast du ein Oszi? Denn nur damit kannst du erkennen, ob das Timing 
deines uC zum Timing vom Slave passt.

> Meine Funktion sieht so aus:
1
  while(((LPC_SSP1->SR&0x1F)&0x1C))...
Was ist denn das? Was willst du damit bezwecken?

BTW: mach doch bitte das nächste Mal ein [ c ] und ein [ /c ] ohne die 
Leerzeichen um deinen Code. Das steht übrigens auch ein paar Zeilen über 
jedem Eingabefenster...

: Bearbeitet durch Moderator
von Stefan (Gast)


Lesenswert?

SPI-Clock zu schnell?

von ich (Gast)


Lesenswert?

Du sendest beim 2. und 3. byte gar nicht. Schreib
mal was ins Senderegister, damit der SPI loslaeuft.

Gruß

ich

von думлихер троль (Gast)


Lesenswert?

Offensichtlich SPI nicht verstanden.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

думлихер троль schrieb:
> Offensichtlich SPI nicht verstanden.
Das Bild da in der Mitte könnte helfen:
http://www.lothar-miller.de/s9y/archives/15-SPI.html

von Jojo S. (Gast)


Lesenswert?

wo wird denn das CS gemacht? Das wirst du für 24 Bit Transfers manuell 
machen müssen, im Datenblatt sehe ich jetzt nur max. 16 Bit. Wenn jetzt 
3x1 Byte Transfers laufen liefert dir der MC33972 vermutlich immer nur 
das 1.Byte weil ein CS Wechsel oft für den Reset der Sequenz benutzt 
wird.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Matthias R. schrieb:
> LPC11C24(Master) und will über SPI mit einem Freescale MC33972(Slave)
Ein Dejavu: https://www.mikrocontroller.net/search?query=MC33972
Wozu fängst du eigentlich laufend neue Threads zum selben Thema an?

Die Abfrage, ob eine Übertragung aktiv ist, wird von Anderen übrigens so 
gemacht:
1
  while ( LPC_SSP1->SR & SSPSR_BSY );
Das scheint mir irgendwie sinnvoller...

: Bearbeitet durch Moderator
von Matthias R. (maro0007)


Lesenswert?

Danke für die Antworten.
Ist das erste mal, das ich SPI programmiere.

Das ich nur was zurück bekomme,wenn ich etwas sende ist mir klar, aber 
ich bekomme meist nur Nullen zurück.

Warum wird das 2. und 3. Byte nicht gesendet, ich schreibe es genau wie 
das erste ins Senderegister.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Matthias R. schrieb:
> Warum wird das 2. und 3. Byte nicht gesendet, ich schreibe es genau wie
> das erste ins Senderegister.
Mach mal einfach ein 1ms-Delay nach dem Senden der jeweiligen Bytes. Ich 
zweifle wie gesagt immer noch am Sinn deiner Busy-Abfrage...

Und: hast du jetzt ein Oszi oder nicht?

von Matthias R. (maro0007)


Lesenswert?

Habe jetzt 1ms Wartezeit zwischen dem senden eingebaut und die 
Übertragungsrate stark zurückgesetzt. Jetzt bekomme ich immer eine 
Antwort, die nicht nur aus Nullen besteht. Oszilloskop habe ich leider 
keines.

Meine Funktion sieht jetzt so aus:
1
void SPI(void){ //Abfragen und programmieren der SPI Schnittstelle
2
 uint8_t a=1,Frame1=1, Frame2=0, Frame3=0;
3
 static int zaehler=0;
4
 zaehler++;
5
6
 LPC_GPIO2->DATA &=~0x01;//Slave select low
7
 //1.Byte
8
 LPC_SSP1->DR=Frame1;//schreiben Ins Transmit Register
9
 wait();
10
 Frame1= LPC_SSP1->DR;//Abfragen der erhaltenen Bits
11
12
 //2.Byte
13
 LPC_SSP1->DR=Frame2;
14
 wait();
15
 Frame2= LPC_SSP1->DR;
16
17
 //3.Byte
18
 LPC_SSP1->DR=Frame3;
19
 wait();
20
 Frame3 = LPC_SSP1->DR;
21
22
 LPC_GPIO2->DATA |=0x01;//Slave select high
23
24
 if(Frame1||Frame2||Frame3) {
25
   ledinit();aus();
26
27
}
28
29
}

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Matthias R. schrieb:
> Jetzt bekomme ich immer eine Antwort, die nicht nur aus Nullen besteht.
Ist die Antwort sinnvoll?

> Oszilloskop habe ich leider keines.
Das ist beim SPI besonders blöd, denn jetzt musst du dich sehr genau in 
die Doku beider Chips einarbeiten und den richtigen Modus herausfinden 
(CPOL, CPHA).

von Matthias R. (maro0007)


Lesenswert?

Nein leider nicht sinnvoll, immer andere Werte, aber sie müssten immer 
gleich sein, weil ich an den Schalterzuständen nichts ändere.

Ich kenn jemanden, der ein Oszi hat, zu dem fahr ich jetzt dann mal.

Mein Code sieht jezt so aus:
1
void SPI(void){ //Abfragen und programmieren der SPI Schnittstelle
2
 uint8_t a=1,Frame1=127, Frame2=127, Frame3=127;
3
 static int zaehler=0;
4
 zaehler++;
5
6
 LPC_GPIO2->DATA &=~0x01;//Slave select low
7
 //1.Byte
8
 LPC_SSP1->DR=Frame1;//schreiben Ins Transmit Register
9
 wait();
10
 Frame1= LPC_SSP1->DR;//Abfragen der erhaltenen Bits
11
12
 //2.Byte
13
 LPC_SSP1->DR=Frame2;
14
 wait();
15
 Frame2= LPC_SSP1->DR;
16
17
 //3.Byte
18
 LPC_SSP1->DR=Frame3;
19
 wait();
20
 Frame3 = LPC_SSP1->DR;
21
22
 LPC_GPIO2->DATA |=0x01;//Slave select high
23
24
 if(Frame1||Frame2||Frame3) {
25
   ledinit();aus();
26
27
}
28
29
}

von Matthias R. (maro0007)


Lesenswert?

Ich probier jetzt mal SPI Softwaremässig zu realisieren

von Matthias R. (maro0007)


Lesenswert?

Ich versuch jetzt das ganze Software mässig in den Griff zu bekommen. 
Allerdings bekomme ich immer noch keine sinnvollen Daten zurück, aber 
immerhin immer die gleichen. Was haltet ihr von dem Code ? Hat jemand 
Erfahrungen mit dem MC33972?

1
int SPI( int send){
2
  //Grundeinstellungen
3
  //Sysclock ist soll nullsein, wenn nichts passiert
4
    //SSl ist High wenn nichts passiert
5
  int i=0;
6
  int b=0,zaehler=0;
7
  //Beginn senden
8
  //SSL fallend
9
10
  LPC_GPIO2->DATA &=~0x02; //SCKL LOW
11
  LPC_GPIO2->DATA &=~ 0x01; //SSl LOW
12
13
  int data = 0;
14
15
   // Höchstes Bit muss zuerst gesendet werden
16
    for( i =23;i>=0;i--){
17
18
    if( send & (1<<i)) {// wählt aus , ob MOSI 0 oder 1 als Zustand hat
19
       LPC_GPIO2->DATA |= 0x01;//MOSI = 1
20
    }
21
22
    else {LPC_GPIO2->DATA &=~0x01;//MOSI = 0
23
    }
24
25
       high;//SCKL High
26
27
       b = LPC_GPIO2->DATA &0x04;//Liest Zustand des MISO Pins aus 
28
29
       if(b)//Speichert Bit in Datenstring ab
30
       {data |=(1<<i);}
31
       low;//SCKL low
32
    }
33
   LPC_GPIO2->DATA |=0x01; //SSl High
34
35
return data & 0xFFFFFF;//Nur Bits, die kleine als Numm er 24 sind nehmen
36
}

von Daniel C. (cecky)


Lesenswert?

Ich hab zwar keine Erfahrung mit dem MC33972, aber das hier scheint 
irgendwie nicht richtig:

Matthias R. schrieb:
> LPC_GPIO2->DATA &=~ 0x01; //SSl LOW

Matthias R. schrieb:
> LPC_GPIO2->DATA |= 0x01;//MOSI = 1

es erschließt sich mir nicht wie ein Bit einmal SS1(ChipSelect) und 
einmal MOSI sein kann, oder ist das bei einem MC33972 gängige Praxis?
Und wo sind "low" und "high" definiert?

: Bearbeitet durch User
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.