- 3D-Druck Einstieg und Tipps         
Seite 2 von 2 ErsteErste 12
Ergebnis 11 bis 16 von 16

Thema: SPI Interrupt wird ZU SPÄT ausgelöst nach Sendevorgang

  1. #11
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    14.04.2005
    Ort
    Freiberg
    Alter
    41
    Beiträge
    311
    Anzeige

    LiFePo4 Akku selber bauen - Video
    Hallo zusammen,

    interessante Diskussion, die hier losgebrochen ist.
    Aber zum Thema: Danke Siro für die Aufklärung. Den ASM-Code habe ich nun auch ausgeben und so halbwegs nachvollziehen können. Im nächsten Schritt wollte ich mich natürlich daran machen, einige Zeilen auszusparen, um zu schauen, auf welche er womöglich sogar verzichten könnte. So hatte ich versucht, Teile des C-Codes durch asm("...") zu ersetzen. Allerdings klappte das nicht so, da ich versucht hatte, es genauso anzuordnen, wie in der listing.disasm. Das bedeutet aber, dass Befehle zwischen void interrupt isr(void) und der "geschweiften Klammer auf" stehen. Das hat dem Compiler erstmal nicht so gefallen.
    Aber ich habe festgestellt, wenn die Befehle dann nach der geschweiften Klammer eingefügt sind, nimmt mein Zeitverzug (immernoch der provisorische INT0-Auslöser) von 11µs auf 25µs zu. Das scheint also schon alles Hand und Fuß zu haben.

    Das bringt mich natürlich dazu, das erstmal so zu akzeptieren und ich muss mal drüber nachdenken, wie ich es schaffe, damit umzugehen.
    Ursprünglich war mein Ziel, dass ich ein Address-Byte über SPI übertrage und der gleich anschließend eine Antwort (z.B. Wert einer Variable) übersendet. Bei einem SCLK-Takt von 1MHz und diesem verspäteten Interrupt, wo dann SSPBUF gleich den zu übertragenden Wert der Variable hätte rein bekommen sollen, klappt das natürlich nicht. Jetzt muss ich womöglich mehrere Variablen-Anfragen verschachteln. Also so in etwa:

    1. SS & SCLK aktiv, 1Byte-Adresse1 MOSI; MISO nichts
    <mehr oder weniger pause>
    2. SS & SCLK aktiv, 1Byte-Adresse2 MOSI; MISO Variable von Adresse 1
    <mehr oder weniger pause>
    3. SS & SCLK aktiv, 1Byte-Adresse3 MOSI; MISO Variable von Adresse 2
    <mehr oder weniger pause>
    ...
    <mehr oder weniger pause>
    N. SS & SCLK aktiv, 1Byte-AdresseN MOSI; MISO Variable von Adresse N-1
    <mehr oder weniger pause>
    N+1. SS & SCLK aktiv, 1Byte Dummy MOSI; MISO Variable von Adresse N

    Dieses Vorgehen wäre zwar möglich, ist aber genau dann unschön, wenn der Master auf Adressen schreiben möchte. Dann würde der µC es nicht schaffen nach der Bekanntgabe der Adresse rechtzeitig den SSPBUF leer zu machen, ehe dann auch gleich das Schreibbyte übertragen wird.

    Vielleicht wäre es hier geschickter, den Master anzufassen und (bei der Kommunikation mit dem PIC18 ) eine definierte Pause zwischen dem Adress-Byte und dem Read- oder Write-Byte zu machen.

    Grüß,
    NRicola
    Gurken schmecken mir nicht, wenn sie Pelz haben!

  2. #12
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    Ich muß gestehen dass ich auch noch keine Erfahrung mit dem "Slave Mode" habe.
    und stelle mir das auch etwas problematisch vor mit Bidirektionalen Betrieb.
    Wenn ich ein Kommando sende und unmittelbar eine Antwort haben möchte,
    bleibt dem Slave meiner Meinung nach ja keien Zeit das Kommando auszuwerten,
    bzw. müste das ja dann innerhalb eines Clockzyklus erledigt sein.
    Empfang auslesen auswerten und Ergenis Byte schnell genug ins Register zum Ausschieben packen.
    Hier würde ich, sofern das überhaupt möglich ist, nach dem Senden eines Kommandobytes
    entweder eine Pause einfügen oder einfach 1 oder mehr Dummy Bytes senden.
    Dann weis der Master, z.B. dass die ersten n Rückgabebytes ignoriert werden müssen.

    Vielleicht haben hier schon andere Erfahrungen mit gemacht
    und können dazu etwas Info geben. Wäre für mich auch mal interessant.

  3. #13
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    14.04.2005
    Ort
    Freiberg
    Alter
    41
    Beiträge
    311
    Ich habe gerade nochmal etwas ge-internet-sucht. Ich bin lediglich auf das hier gestoßen, wo ebenfalls der Master ausgebremst wird:
    https://www.ccsinfo.com/forum/viewtopic.php?t=39145
    Hier sind es 100µs Wartezeit. Das geht womöglich nur über Software-SPI. Aber schon ziemlich suboptimal. Zwar kann man mit der SCLK schön aufdrehen (bei meinen 1MHz sind die zwei Byte eigentlich binnen ca. 16,6µs durch) - aber wenn man jetzt nochmal >11µs oder gar bis 100µs warten muss, dann wird man schon ganz ordentlich ausgebremst.

    Sollte da jemand noch eine elegantere Lösung für PICs/µCs haben, wäre sie herzlich willkommen!
    Man kann die Frage auch andersherum stellen: hat jemand einen µC vor sich, der binnen (weit) weniger als 11µs bei 16MHz die Interrupt-Routine betreten hat?

    Grüß
    NRicola
    Gurken schmecken mir nicht, wenn sie Pelz haben!

  4. #14
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.03.2011
    Beiträge
    1.899
    Ich kenn mich mit den PIC18 nicht so wirklich aus, aber die neueren PIC16, die ich so verwende, bekommt man mit der PLL auf 32 MHz. Das halbiert die Zeit.

    Ich würd mal versuchen, mir vom SlaveSelect einen Interrupt auslösen zu lassen und ab dann alles im Interrupthandler per Pollig zu machen. Damit ist aber dies Problem nicht gelöst:
    Zitat Zitat von Siro Beitrag anzeigen
    Wenn ich ein Kommando sende und unmittelbar eine Antwort haben möchte, bleibt dem Slave meiner Meinung nach ja keien Zeit das Kommando auszuwerten, bzw. müste das ja dann innerhalb eines Clockzyklus erledigt sein. Empfang auslesen auswerten und Ergebnis Byte schnell genug ins Register zum Ausschieben packen.
    SPI-Flash im Fast-Modus erwarten ein Dummy-Byte nach der Adresse, bevor sie anfangen, Daten zu schicken. Die machen das intern aber rein in Hardware, Fast heißt da leicht 80MHz.

    Beim PCI-Bus kann der Slave mit NAK quittieren, und der Master muß bis zu vier mal das gleiche Kommando wiederholen. Da hat sich der Slave schon beim ersten Mal die Adresse gemerkt.

    Und bei I2C kommt erst ein Write mit dem Datenpointer, da kann der Slave schon mal den Adresszeiger aufsetzen, und dann der Read. Das könnte man auch mit SPI machen. Select low, ein Write Command, dann die Adresse. Select wieder High. Dann Select low, Read Command, der Slave hat das erste Byte schon parat und schickt es. Währen es geschickt wird, holt er das nächste, usw. bis Select wieder High wird.

    Das sind so Beispiele, die mir einfallen.

    MfG Klebwax
    Strom fließt auch durch krumme Drähte !

  5. #15
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    14.04.2005
    Ort
    Freiberg
    Alter
    41
    Beiträge
    311
    Hallo zusammen,

    ich möchte mal das Thema abrunden mit der folgenden Lösung, die ich nun umgesetzt habe und dem folgenden Fazit:
    An dem Zeitverzug zwischen <Interrupt wird angefordert> und <ich mache irgendwas in der ISR> von ca. 11,5µs bei 16MHz lässt sich wohl nichts rütteln.
    Deshalb muss beim SPI-Master eine Wartepause eingelegt werden, sodass der PIC18-Slave Zeit hat, das erste MOSI-Byte (=Adresse) zu verarbeiten.

    Um den Zeitverzug von 11,5µs dennoch hier nicht haben zu müssen, habe ich jetzt folgende Strategie angewandt:


    1. SPI kann keinen Interrupt mehr auslösen:
      Code:
      SPIE1bits.SSPIE = 0;
    2. das SS-Signal (PA5) wird gleichzeitig auf den INT0-Pin (RB0) gelegt
    3. INT0 aktivieren:
      Code:
      INTCONbits.INT0IE = 1;
      INTCON2bits.INTEDG0 = 0;    //interrupt on rising edge:=1 (Je nach SPI-Modus)
    4. ISR-Routine bereitet sich bei INT0 bereits vor und wartet den SPI-Interrupt-Flag ab:
      Code:
      void interrupt isr(void){
          if (INTCONbits.INT0IF==1){
              while(PIR1bits.SSPIF == 0);      // auf SPI-Interrupt warten
              spi_reg_addr=SSPBUF;
              SSPEN=0;
              //tu' noch irgendwas, z.B. einen Adress-Anfragen-Vergleich durchführen
              SSPEN=1;
              PIR1bits.SSPIF = 0;
              INTCONbits.INT0IF = 0;
          }
      }

    Damit habe ich nicht mehr die 11,5µs Zeitverzug abzuwarten, sondern nur noch ca. 3,3µs. damit könnte man womöglich noch ohne Warten des Masters bei einem SCLK von 100-200kHz hinkommen. Zumindest ist das besser als die 100µs Wartezeit von dem Forumsbeitrag von ccsinfo (siehe oben).

    Grüß
    NRicola
    Geändert von NRicola (13.06.2018 um 13:22 Uhr)
    Gurken schmecken mir nicht, wenn sie Pelz haben!

  6. #16
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    14.04.2005
    Ort
    Freiberg
    Alter
    41
    Beiträge
    311
    Hallo zusammen,

    noch zu den Timings: oben hat sich ein Fehler eingeschlichen. Die 3,3µs waren nicht korrekt. Sie kamen daher, dass ein Interrupt ca. 11,5µs benötigt, um einsatzfähig zu sein. Bei meinen 1MHz SCLK waren die 8 gesendeten Bits schon nach 8µs durch. Die Differenz waren die rund 3,3µs.

    Ich habe nun eine Zuordnung zu 8 Adressen (case-Struktur) gebaut und etwas mit den Timings rumgespielt.


    1. Ohne Pause zwischen Byte 1 (MOSI) und Byte 2 (MISO): SCLK darf nicht mehr als 125kHz betragen. Die Gesamtübertragungsdauer für beide Bytes beträgt dann 132µs
    2. Pause zwischen den beiden Bytes (also SCLK ausgesetzt) bei einem SCLK=1MHz: bei mir waren rund 9-10µs notwendig, damit der PIC18 genug Zeit hatte zu reagieren. Übertragungsdauer gesamt 25µs
    3. Pause zwischen beiden Bytes, wenn die Dauer des ersten übertragenen Bytes in etwa dem Interrupt Verzug von 11,5µs entspricht (SCLK=700kHz): etwa 6,5µs muss die Pause betragen. Übertragungsdauer ca. 28,8µs.


    Wie schon erwähnt, basieren die Werte auf einen 16MHz-Clock beim µC.

    Grüß
    NRicola
    Gurken schmecken mir nicht, wenn sie Pelz haben!

Seite 2 von 2 ErsteErste 12

Ähnliche Themen

  1. SPI Interrupt wird nicht ausgelöst nach Sendevorgang
    Von steckplatte im Forum PIC Controller
    Antworten: 4
    Letzter Beitrag: 25.04.2018, 21:08
  2. Interrupt wird nicht ausgelöst.
    Von DarkSoldier im Forum C - Programmierung (GCC u.a.)
    Antworten: 1
    Letzter Beitrag: 28.04.2013, 15:42
  3. Interrupt wird nicht ausgelöst
    Von Michael_am32 im Forum C - Programmierung (GCC u.a.)
    Antworten: 4
    Letzter Beitrag: 02.08.2010, 01:37
  4. Es wird kein Interrupt ausgelöst
    Von MrTaco im Forum C - Programmierung (GCC u.a.)
    Antworten: 9
    Letzter Beitrag: 19.07.2010, 17:48
  5. Wann wird ein Interrupt ausgelöst?
    Von CKroll im Forum PIC Controller
    Antworten: 2
    Letzter Beitrag: 08.09.2004, 09:16

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

12V Akku bauen