Forum: Mikrocontroller und Digitale Elektronik PIC24 mit SPI Problem


von langi (Gast)


Lesenswert?

Hallo Zusammen!
Ich bin schon total verzweifelt! Hänge schon seit über einer Woche an 
einem Problem und bekomm dieses einfach nicht gebacken.
Ich habe einen pic24fj128ga010. Diesen habe ich am SPI1 als Slave 
konfiguriert.
Ich springe nachdem ich die SS Leitung abgefragt habe in die Routine und 
will die Daten die über SPI gesendet werden in Variablen ablegen. Es 
werden immer 16 Byte geschickt.
Aber das Unterprogramm hängt immer an der folgenden Stelle:
   while (!SPI1STATbits.SPIRBF) set_bit(PORTA,0) ;
Led leuchtet ständig und bringt mein ganzes restliches Programm zum 
erliegen.

Anbei mal das Unterprogramm:


void SPI1Service(void){

unsigned char SPI1[16];

int i;

   unsigned char rbuf = SPI1BUF;                              //Clear 
receive buffer full bit
   for(i=0; i<16;i++){

      while (!SPI1STATbits.SPIRBF) set_bit(PORTA,0) ;      //setze led0
      clear_bit(PORTA,0);               //lösche led0
      SPI1 = SPI1BUF;
   }

   switch (SPI1[0])
   {
   case 0x80 :
      Jahr = SPI1[1];
      Monat = SPI1[2];
      Tag = SPI1[3];
      Wochentag = SPI1[4];
      Stunde = SPI1[5];
      Minute = SPI1[6];
      Sekunde = SPI1[7];
      break;
   case 0x81 :
      geobreit = (long)SPI1[1]<<24 | (long)SPI1[2]<<16 | 
(long)SPI1[3]<<8 | (long)SPI1[4];
      geolaeng = (long)SPI1[5]<<24 | (long)SPI1[6]<<16 | 
(long)SPI1[7]<<8 | (long)SPI1[8];
      break;
   case 0x82 :
      set_bit(PORTA,7);      //Referenzflag
      break;
         }

}

Habe mit dem Oszi das senden der 16 Daten Bytes überprüft und diese 
werden korrekt übertragen.

Danke für jede Hilfe!

lG
Daniel

von holger (Gast)


Lesenswert?

Ich kenn jetzt die PIC24 nicht, aber ganz banal:

1) Slave nicht richtig konfiguriert
2) Takt kommmt nicht beim Slave an (oder zu schnell ?)
3) Slave Select irgendwas falsch

Das wären so Möglichkeiten wo man suchen sollte.

Noch paar kleine Anmerkungen:

>   unsigned char rbuf = SPI1BUF;                              //Clear
>receive buffer full bit

Warum wirfst du das erste Byte weg?

>      SPI1 = SPI1BUF;

Sollte besser so aussehen

SPI1[i] = SPI1BUF;

von holger (Gast)


Lesenswert?

Hätte ich fast vergessen:
Zähl doch in der for() Schleife mal
mit ob überhaupt irgendwas ankommt.
Oder Osci an Porta0 anschliessen.

von langi (Gast)


Lesenswert?

Hallo Holger!

Vielen Danke für deine schnelle Antwort!
Ich bin mir eigentlich ziemlich sicher das ich den Slave Mode richtig 
konfiguriert habe.
Takt kommt beim Slave an und auch die 16 Bytes werden korrekt 
übertragen.
Der chip select eingang wird bei mir in der Endlosschleife in der main 
funktion ständig abgefragt und der Sprung an sich in das Unterprogramm 
klappt ja eigentlich.
Das mit dem Oszi in der For Schleife ist ne gute Idee! Kann ich aber 
leider erst morgen ausprobieren, da ich grade kein Oszi zur Hand habe.

Und du hast natürlich recht, das erste byte werfe ich weg. Frage mich 
auch gerade warum!! Ups! Vielleicht liegt es auch daran, kriegt ja dann 
keine 16 bytes mehr voll und hängt unter Umständen im letzten Durchlauf.

Vielen Dank nochmal!!!
Melde mich morgen wieder!

lg
daniel

von TommyS (Gast)


Lesenswert?

Hallo!

Du könntest auch noch überprüfen, ob die Bits in den CONFIG-Registern 
richtig gesetzt sind. Ich hatte vor einiger Zeit ein ähnliches Problem, 
das sich gelöst hat, als ich JTAG abgeschalten habe, da die SPI-Pins auf 
den JTAG-Pins lagen.

Das sieht bei mir jetzt so aus:
1
_CONFIG1(JTAGEN_OFF)

Grüße,
TommyS

von langi (Gast)


Lesenswert?

Hallo!
So habe jetzt mein Programm ein wenig geändert:

void SPI1Service(void){


unsigned char SPI1[16];

int i;

  SPI1[0] = SPI1BUF;    //Clear receive buffer full bit

  for(i=1; i<15;i++){
    //SPI1BUF=0x00;
    while (!SPI1STATbits.SPIRBF) set_bit(PORTA,0) ;    //setze led0
    clear_bit(PORTA,0);                  //lösche led0
    SPI1[i] = SPI1BUF;
  }

  switch (SPI1[0])
  {
  case 0x80 :
    RTCCSetBinYear(SPI1[1]);
    RTCCSetBinMonth(SPI1[2]);
    RTCCSetBinDay(SPI1[3]);
    RTCCSetBinHour(SPI1[5]);
    RTCCSetBinMin(SPI1[6]);
    RTCCSetBinSec(SPI1[7]);
    RTCCSet();
    break;
  case 0x81 :
    geobreit = (long)SPI1[1]<<24 | (long)SPI1[2]<<16 | (long)SPI1[3]<<8 
| (long)SPI1[4];
    geolaeng = (long)SPI1[5]<<24 | (long)SPI1[6]<<16 | (long)SPI1[7]<<8 
| (long)SPI1[8];
    break;
  case 0x82 :
    set_bit(PORTA,7);    //Referenzflag
    break;
  }
}

Jetzt verhält es sich so: Wenn ich Daten schicke bleibt er zu 90% 
trotzdem noch in der while schleife hängen und auf dem Oszi beim Messen 
des PortA.0 erscheint nur eine steigende Flanke (also nicht ein Byte 
wird korrekt abgelegt).
Allerdings kommt es jetzt vor, dass er es auch mal korrekt abarbeitet, 
zwar selten aber immerhin. Dann sind auch auf dem Oszi die einzelnen 
Bytes zu erkennen. Nur kann ich das so natürlich nicht lassen.
Denke mir, dass es vielleicht irgend ein Zeitproblem gibt,aber warum 
kann ich dann nicht wenigstens ein paar bytes korrekt ablegen?

Bin echt am Ende!! Hoffe ihr habt noch ne Idee was das sein!!!

lg Daniel

von Matthias (Gast)


Lesenswert?

- Errata durchgelesen?
- Wird das Collison Flag gesetzt?

von langi (Gast)


Lesenswert?

Hallo Matthias!
Hab das Errata durchgelesen, aber auch nichts weiter entdecken können.
Collision Flag wird nicht gesetzt!

Trotzdem danke für deine Antwort!!!

Hat jemand vielleicht noch einen Einfall?

lg
daniel

von holger (Gast)


Lesenswert?

Nochmal was zum nachdenken:

>  SPI1[0] = SPI1BUF;    //Clear receive buffer full bit

Woher weißt du das das erste Byte hier schon komplett
empfangen wurde? Du sagtest oben du fragst den
Slave Select Pin ab. Der sagt dir aber nicht ob
das Byte schon komplett übertragen wurde. Möglicherweise
stört dieses unkontrollierte Lesen von SPI1BUF
die Übertragung. Mach die Zeile weg und ändere die Schleife:

  for(i=0; i<16; i++){
    while (!SPI1STATbits.SPIRBF) set_bit(PORTA,0) ;    //setze led0
    clear_bit(PORTA,0);                  //lösche led0
    SPI1[i] = SPI1BUF;
  }

Da schaust du jetzt erst mal ob das so geht.

Ansonsten kann es aufgrund deines Hauptprogrammes
durchaus sein, das die Übertragung schon fast durch ist
bevor du überhaupt in SPI1Service() springst.

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.