Hallo, ich prgrammiere gerade ein Testprogramm für eine Single-Master-SPI-Verbindung und bekomme dabei Schwierigkeiten mit dem WCOL-Interrupt. Er blockiert ab einer bestimmten Stelle permanent den Ablauf meines Programmes. Daher meine Frage: Wie kann ich den SPI-Datenpuffer (SPI0DAT) löschen? Muß ich dies? --> Denn ich denke hier führt mein Problem hin. ----------------- Habe mein Programm an folgende Programmbeispiele angelehnt: - F32x_SPI0_Master.c von SilLabs - Testbsp. vom Hersteller (ACAM) für den verwendeten TDC, der angesprochen werden soll, auch in C. (Allgm. gehalten für einen 8Bit-8051-uC --> siehe PPT-Doku zum Projekt) Unterschiede der Programmbeispiele bzgl. meiner Frage: - Das ACAM-Testprogramm liest nach jedem Senden den Inhalt des SPIDAT um ihn zu "Löschen". Beim SilLab-Bsptext ist mir dies nicht aufgefallen. L> Ich habe bei meinem Testprogramm schon beides ausprobiert. ----------------- Was soll mein Programm machen: - Es soll ein Register eines TDCs zur Konfiguration füllen (also Schreibbefehl an TDC + 3 weitere Datenbyte) - Danach geht ein spezieller Test-Lesebefehl an den TDC, welcher dann mit dem Inhalt des höchsten Datenbytes (aus der voran erwähnten TDC-Register) antworten soll. Realisierung der SPI-Verbindung: - Schreiben per Polling, alle Interrupts ausgeschaltet - Lesen auch per Polling bei eingeschalteten Interrupts - Mein Programm ist in Assembler gehalten. In C bin ich nicht so sicher, doch die Beispiele konnte ich verstehen. Hintergrund: - Habe meinen momentanen Projektstand angehängt, soweit es hier geht. Ich hoffe mein Fragetext erschlägt Euch nicht. Vielen Dank im Vorraus!
> ...Schwierigkeiten mit dem WCOL-Interrupt. Er blockiert ab einer > bestimmten Stelle permanent den Ablauf meines Programmes. > Daher meine Frage: > Wie kann ich den SPI-Datenpuffer (SPI0DAT) löschen? Muß ich dies? --> > Denn ich denke hier führt mein Problem hin. Ne, musst du nicht, denn wenn es wirklich der WCOL-Interrupt ist, dann hast du m.E. ein Verständnisproblem :) Auszug aus Datenblatt: WCOL: Write Collision Flag. This bit is set to logic 1 by hardware (and generates a SPI0 interrupt) to indicate that a write to the SPI0 data register was attempted while the transmit buffer already contained data. It must be cleared by software. Hier stecken zwei Aussagen drin: 1. Schreibe nicht SPI0DAT, solange noch gesendet wird -> SPIF muss den Interrupt auslösen -> aktuelles Byte gesendet -> SPIF via Software löschen 2. WCOL muss ebenfalls durch Software gelöscht werden. Ohne in deinen Code geschaut zu haben bleibt also grad die Frage, ob du irgendwo aus Versehen Daten ins Senderegister butterst, bevor der Transfer fertig ist, und ob du evtl. dann vergessen hast, die entsprechenden Flags zu löschen, da ja dann angeblich blockiert wird. Ralf
Hallo Ralf, Du meinst also, daß ich nur die Flags zurücksetzen muss, nicht aber das SPI0DAT lesen, um den Grund für WCOL=1 zu beseitigen, richtig? Oder kann es auch sein, daß ich mich um den SPI-Takt kümmern muß und dies das eigentliche Problem ist? Denn im SPI0DAT sehe ich nie mehr als 00 oder FF, obwohl alle Übergabeadressen einwandfrei funktionieren. Bisher bin ich davon ausgegangen, daß der Takt egal ist. Wann ist für mich der SPI-Takt interessant? Vielen Dank für die Antwort! Boris
Vielleicht dazu noch eine Frage zu WCOL, TXBMT und SPIF: Betrachte ich nur den Schreibevorgang, so verbergen sich hinter dem SPI0DAT 2 Register (siehe Doku C8051F320: Figure 18.1. SPI Block Diagram). Ein Shift-Register, der eigentliche Ein- und Ausgang und ein Sende-Übergansregister (in Figure 18.1 "Transmit Data Buffer" genannt). Sind meine Vermutungen so richtig?: TXBMT = 0 wenn in Sende-Übergangsregister etwas reingeschrieben wird = 1 wenn an Shiftregister weitergegeben, (8Bit) innerhalb eines Taktes SPIF = bezieht sich immer auf das Shiftregister, also 1 wenn letztes Bit gesendet (1 beim 9.Bit) WCOL = 1 wenn im Shiftregister noch etwas steht und wieder etwas hineingeschrieben wird. - Für mich ist das WCOL der in der Doku am ungeschicktesten beschriebene Punkt.
> Du meinst also, daß ich nur die Flags zurücksetzen muss, nicht aber > das SPI0DAT lesen, um den Grund für WCOL=1 zu beseitigen, richtig? Nicht ganz. Den Grund beseitigst du damit nicht, aber WCOL gehört zu den Flags, die den Controller veranlassen, die SPI-ISR anzuspringen. Löschst du generell die Interrupt-Flags nicht, welche IRQs auslösen können, wird nach Verlassen der Interrupt-Routine ein Befehl des Hauptprogramms (oder einer unterbrochenen, niedriger priorisierten Interrupt-Routine) ausgeführt, und sofort wieder in die Interrupt-Routine gesprungen. Den Grund muss man rausfinden, denn eigentlich sollte WCOL bei korrekter Implementierung der SPI-Routinen gar nicht gesetzt werden. > Oder kann es auch sein, daß ich mich um den SPI-Takt kümmern muß und > dies das eigentliche Problem ist? Natürlich musst du dich "kümmern". Die Antwort ist genauso wachsweich wie die Frage :) Du kannst beispielsweise nicht mit 20MHz rauspusten, wenn dein Slave nur maximal 5MHz kann. > Denn im SPI0DAT sehe ich nie mehr als 00 oder FF, obwohl alle > Übergabeadressen einwandfrei funktionieren. SPI0DAT zu lesen gibt dir das Empfangsregister, Schreiben in SPI0DAT verwendet ein anderes Register! > Bisher bin ich davon ausgegangen, daß der Takt egal ist. Wann ist für > mich der SPI-Takt interessant? Siehe oben, ist u.a. davon abhängig, wie schnell der F320 getaktet ist, ob er Master/Slave und wie schnell dein Slave ist. Hinzu kommt noch, ob du 3- oder 4-Wire implementierst etc. Die o.g. empfangenen 0x00/0xFF können auf verschiedene Sachen hindeuten. Entweder sendet dein Slave nichts bzw. er bekommt die Takte nicht richtig mit, oder SPI0 ist noch nicht richtig konfiguriert -> Hast du das Interface in der CrossBar richtig eingestellt bzw. kannst du prüfen, ob MOSI/MISO/SCK/SS an den richtigen Pins rauskommen? Wenn die CrossBar falsch konfiguriert bzw. generell nicht aktiviert(!) ist, kommt auch nirgends was an. Was das SPI0DAT macht, wenn SPI0 in der CrossBar nicht konfiguriert ist, weiss ich nicht. > Vielleicht dazu noch eine Frage zu WCOL, TXBMT und SPIF: Nur zu... :) > Betrachte ich nur den Schreibevorgang, so verbergen sich hinter dem > SPI0DAT 2 Register (siehe Doku C8051F320: Figure 18.1. SPI Block > Diagram). Ein Shift-Register, der eigentliche Ein- und Ausgang und ein > Sende-Übergansregister (in Figure 18.1 "Transmit Data Buffer" genannt). > Sind meine Vermutungen so richtig?: > TXBMT = 0 wenn in Sende-Übergangsregister etwas reingeschrieben wird > = 1 wenn an Shiftregister weitergegeben, (8Bit) innerhalb eines Taktes Wenn TXBMT gesetzt ist, kannst du neue Daten in SPI0DAT schreiben > SPIF = bezieht sich immer auf das Shiftregister, also 1 wenn letztes Bit > gesendet (1 beim 9.Bit) Wieso 9.Bit? SPIF wird gesetzt, wenn ein Byte rausgepustet bzw. empfangen wurde. Muss bei zugelassenem Interrupt in der ISR gelöscht werden. > WCOL = 1 wenn im Shiftregister noch etwas steht und wieder etwas > hineingeschrieben wird. Nein, es ist gesetzt, wenn im Sendebuffer Daten stehen, die noch nicht ans Shiftregister gegeben wurden. > - Für mich ist das WCOL der in der Doku am ungeschicktesten beschriebene > Punkt. Nja, wie man's nimmt. Ich hab auch schon schlimmere Datenblätter gesehen (Atmel, Philips) grins Aber generell gehören die SiLabs Datenblätter m.E. zu den detailiertesten. Fazit: Poste doch bitte mal deinen Code für die CrossBar/Port- sowie SPI-Initialisierung, für den System- und SPI-Takt sowie die SPI-ISR und evtl. die Routinen, die die SPI-Daten verarbeiten. Sofern sich da nichts zum o.g. ZIP-File geändert hat, kann ich nachher mal dort reingucken, wenn das ZIP-File komplett ist. Aber jetzt geh ich erstmal kurz was essen :) Ralf P.S: Heisst du jetzt eigentlich Uwe oder Boris?
Ach ja, vor der Vorspeise noch folgende Bitte: Lies doch bitte mal SPI0CFG und SPI0CN im Fehlerfall aus und sag mir was drinsteht. Ralf
Hallo Ralf, im Internet wechseln meine Namen ständig. Die Konfiguration steckt bereits im beigelegten Kode des Zip-Files drin. Doch ich habe die neueste Version Programmversion plus Wizard-File angehängt. Phase und Polarisierung sollten so wie sie im Wizard-File beschrieben sind stimmen. Denke im Programmtext sind sie noch anders, weil ich heute daran herum probiert hatte. Ich halte es für sehr unwahrscheinlich, daß die Pins im Layout verwechselt wurden. Aber ich werde es morgen nochmal prüfen. Ich bin vielmehr auf eine weitere wahrscheinlichere Fehlerquelle gestoßen: Ich habe den TDC (Slave) mit 6MHz per uC getaktet. Laut TDC wurden 2...8MHz gewünscht. Heute jedoch habe ich gelesen, daß der geforderte SPI-Takt weit darüber liegt (25MHz), kann das stimmen?? Denn so wie ich den uC verstehe kann er für den SPI nur einen Takt verwenden der langsamer ist, als der Sysclock und in jedem Fall unterhalb 25MHz. Im Allgemeinen kann ich nur vom SPI0DAT lesen, was vom Slave geschickt wurde, also nicht das was der Master dort selbst rein getan hat. Ist das richtig? SPI0DAT SPI0CFG SPI0CN PC Text 00 6B 0B 151 mov A,R2 ; R2 = Schreibinhalt 00 6B 0B 152 mov SPI0DAT,A 00 6B 09 154 00 6B 0B 154 jnb TXBMT,$ 00 EB 0B 157 mov A,SPI0DAT 00 EB 0B 159 mov R7,A ; R7 = Dummyregister 00 EB 0B 15A clr WCOL ; heute zu Testzwecken eingefügt ... FF 6B 8B 142 call SPI_SENDEN FF 6B 8B 151 mov A,R2 ...ISR Hoffe es haben sich beim Schreiben (hier) keine Fehler eingeschlichen, aber so müßte der momentane Verlauf sein. Vielen Dank, nochmal, für Deine Mitarbeit, Ralf!
> Ich halte es für sehr unwahrscheinlich, daß die Pins im Layout verwechselt > wurden. Aber ich halte es für mindestens möglich, dass die Konfiguration der CrossBar evtl. falsch ist. Wer sich zum ersten Mal mit SiLabs-MCU beschäftigt, braucht ne Weile, bis er versteht, dass er die Pinbelegung mit leichten Einschränkungen frei wählen kann. Daher ist das eine beliebte Fehlerquelle :) > Ich habe den TDC (Slave) mit 6MHz per uC getaktet. Hast du nicht. Nach meiner Rechnung pustest du 3MHz raus.
1 | mov OSCICN, #081h |
IFCN1 = 0 und IFCN1 = 1 ergibt für SYSCLK interner Oszillator 12MHz mit Vorteiler durch 4 => Ergibt nach meiner Rechnung 3MHz SYSCLK Passt aber immer noch in den erlaubten Bereich. > Heute jedoch habe ich gelesen, daß der geforderte SPI-Takt weit darüber > liegt (25MHz), ... Erstens: Lass mich beim nächsten Mal bitte nicht nach dem Datenblatt suchen ;) > ...kann das stimmen?? Zweitens: Nö, wenn du die Tabelle nochmal anguckst und genau liest, wirst du feststellen, dass sie dir sagt, dass du bei 2.0V Versorgungsspannung mit maximal 10MHz SPI-Takt fahren darfst, bei 2.5V mit maximal 20MHz und bei 3.3V mit maximal 25MHz. Wenn der geforderte Takt mindestens 25MHz sein müsste, würde nicht MAX in der Tabelle stehen, sondern... ? Richtig, MIN. Datenblätterlesen/verstehen ist etwas, was man lernen muss :) Ist je nach Hersteller gar nicht so einfach. > Im Allgemeinen kann ich nur vom SPI0DAT lesen, was vom Slave geschickt > wurde, also nicht das was der Master dort selbst rein getan hat. Ist das > richtig? Zumindest würde ich so das Blockbild der SPI-Schnittstelle interpretieren. Ist ja auch nicht nötig, zu lesen, was der Master (= du selbst) geschrieben hat, er weiss das ja :) Was deinen Sourcecode an sich angeht, wen muss ich da eigentlich nun klopfen? oO Deinen Professor oder dich? Erstens: ISRs müssen mit RETI beendet werden, nicht mit RET! Zweitens: Warum bedienst du die SPI-Schnittstelle gleichzeitig im Polling- UND im Interrupt-Betrieb? Da kannst du ja nur sche*sse rausbekommen. Orientiert sich dein Code am SiLabs Beispielcode für SPI? Jedenfalls solltest du im normalen Code keine Flags beeinflussen, die den IRQ steuern oder beeinflussen können. Entscheide dich für Interrupt oder Polling, aber nicht beides gleichzeitig :) Interrupt ist etwas komplexer, aber dafür musst du nicht wie bei Polling auf irgendwas warten. Drittens: Was um Gottes willen macht dein SPI-IRQ?
1 | jnb SPIF,ISR_SPI_SPIF |
Sollte wohl eher JB anstatt JNB heissen, oder? Das gleiche für die Zeile
drunter. Abgesehen davon, mit dem ganzen Konstrukt musst du die ISR
zweimal durchlaufen, wenn beide Flags gesetzt sind.
> Vielen Dank, nochmal, für Deine Mitarbeit
Bitte, wir haben ja beide was davon.
Ralf
Hallo Ralf, habe 6MHz wieder eingestellt, jb statt jnb in der ISR korrigiert, keine Interrupts außerhalb der ISR mehr rückgesetzt, ISR wurden bei mir bereits richtig mit reti beendet - s.oben bei den ORG-Befehlen, Datenblatt wollte ich nicht angängen, weil schon auf JPG... hingewiesen wurde... ...gleiches Problem. :S Doch ich habe den Grund gefunden. Und ich wollte es nicht glauben!!! Die Pinbelegung wurde im Layout vertauscht. SCK (uC) liegt auf SO (TDC) und MISO (uC) liegt auf SCK (TDC). Ich lerne daraus wieder einmal, daß man alles selbst kontrollieren muss. Vielen Dank Ralf. PS: Sollte die Geschichte weitergehen hänge ich das Datenblatt zum TDC-GP2 mit an.
Hi, > Doch ich habe den Grund gefunden. Und ich wollte es nicht glauben!!! > Die Pinbelegung wurde im Layout vertauscht. grins Siehst du, genau deswegen habe ich auch diesen möglichen Fehlerfall erwähnt :) Bei fix vergebenen Pinfunktionen ist es schwierig, etwas falsch zu machen, aber ein Layouter, der nicht weiss, dass sich die Pinfunktionen verschieben können, fällt dann schon mal auf die Nase. Das ggw. Software-Design mag zwar funktionieren, ist aber m.E. fehleranfällig bzw. -behaftet. Wenn du die Zeit übrig hast, solltest du das Schritt für Schritt überarbeiten. Ralf
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.