Hallo,
Ich bräuchte wieder mal eure Hilfe. Ich versuche ein RFM12B Modul an der
SSP0 Schnittstelle des LPC1768 zu verwenden.
Leider scheitere ich schon am aktivieren der der SPI Schnittstelle.
Soweit ich alles richtig verstanden habe, kann ja SSP im SPI Modus
betrieben werden, mit welchen das RFM12B Modul arbeitet. Die
Schnittstelle am LPC1768 habe ich mit folgenden Code aktiviert (ein
eigner RTOS Task):
1 | Chip_IOCON_PinMuxSet(LPC_IOCON, 1, 20, IOCON_MODE_INACT | IOCON_FUNC3);
| 2 | Chip_IOCON_PinMuxSet(LPC_IOCON, 1, 21, IOCON_MODE_INACT | IOCON_FUNC3);
| 3 | Chip_IOCON_PinMuxSet(LPC_IOCON, 1, 23, IOCON_MODE_INACT | IOCON_FUNC3);
| 4 | Chip_IOCON_PinMuxSet(LPC_IOCON, 1, 24, IOCON_MODE_INACT | IOCON_FUNC3);
| 5 |
| 6 | Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SSP0);
| 7 | Chip_SSP_Set_Mode(LPC_SSP0, SSP_MODE_MASTER);
| 8 | Chip_SSP_SetFormat(LPC_SSP0, 16, SSP_FRAMEFORMAT_SPI , SSP_CLOCK_CPHA0_CPOL0);
| 9 | Chip_SSP_SetBitRate(LPC_SSP0, 1000000);
| 10 | Chip_SSP_Int_Disable(LPC_SSP0);
| 11 | Chip_SSP_Enable(LPC_SSP0);
| 12 |
| 13 | // Test - RFM12B CLKOUT abschalten:
| 14 | while(true)
| 15 | {
| 16 | Chip_SSP_SendFrame(LPC_SSP0, 0x8209);
| 17 | vTaskDelay(configTICK_RATE_HZ/100);
| 18 | }
|
Rein um zu testen, ob ich via SPI erfolgreich Daten an das Modul senden
kann, wollte ich mal CLKOUT des RFM12B deaktivieren - das läßt sich
recht leicht mit dem Oszi kontrollieren. Leider funktioniert das nicht -
CLKOUT des RFM12B bleibt immer aktiv.
Was nach obigen Code passiert ist nur folgendes:
Port 1.20 (CLKOUT): am Oszi sehe ich jeweils 17 Takte (sieht korrekt
aus)
Port 1.21 (SSEL): ist immer high; dazu muss man wissen, dass auf dem
Demoboard (MiniDK 2) dieser Pin mit einem 10K PullUp ausgestattet ist.
Ich wäre jetzt einmal davon ausgegangen, dass der LPC1768 'stark' genug
ist, diesen PullUp nach unten zu ziehen (ist er das?).
Port 1.23 (MISO): immer low (ist vermutlich OK, da das RFM12B ja nichts
zu senden hat)
Port 1.24 (MOSI): immer low (hier ist wohl etwas falsch; da müssten ja
eigentlich ständig die die Bits von 0x8209 übertragen werden)
Seht ihr hier einen Fehler von mir? Hab ich die SSP Schnittstelle
korrekt (als SPI) initialisiert? Übertrage ich die Daten korrekt? Bin
wie imemr für jeden Hinweis dankbar!
vG Alram
Alram Lechner schrieb:
> Bin wie imemr für jeden Hinweis dankbar!
Einen konkreten Hinweis kann ich Dir jetzt nicht geben, habe aber
festgestellt, dass bei mir Hardware-SPI nicht funktioniert hatte.
siehe evtl. auch
Beitrag "Einfaches Testprogramm für RFM12BP-868MHz"
danke wolleg! Habs soeben selber herausgefunden - manchmal sollte man
einfach abschalten und später nochmal probieren. ;)
diese Zeile ... 1 | Chip_SSP_SetFormat(LPC_SSP0, 16, SSP_FRAMEFORMAT_SPI , SSP_CLOCK_CPHA0_CPOL0);
|
... sollte eigentlich so aussehen: 1 | Chip_SSP_SetFormat(LPC_SSP0, SSP_BITS_16, SSP_FRAMEFORMAT_SPI , SSP_CLOCK_CPHA0_CPOL0);
|
Und schon fügt sich der RFM12B dem CLKOUT-Aus Befehl.
vG Alram
hallo,
Jetzt ist irgendwie eine neue Frage aufgetaucht. Ich kann zwar
grundsätzlich das RFM12B Modul via SSP0 ansprechen; Aber mir ist nicht
ganz klar, wie ich den SSP Controller vom LPC1768 hier sinnvoll
einsetze.
Das RFM12B wird (vorerst) nur als Empfänger verwendet. Der Ablauf dazu
sollte ja so sein:
a) RFM12B initialisieren & receiver aktivieren
b) auf INT des RFM12B warten
c) Statusregister auslesen und wenn Bit #16 gesetzt ist, liegt ein Byte
im Fifo
d) wenn ja: Fifo auslesen
Soweit hätte ich das nun auch implementiert, allerdings mit Krücken.
Unschön ist, dass ich nach dem Senden des "Statusregister lesen" Befehl
ja warten muss, bis der SSP Controller die 16 Bit übertragen hat und ich
die Antwort aus dem Fifo abholen kann. Dies mache ich derzeit einfach
so: 1 | while(Chip_SSP_GetStatus(LPC_SSP0, SSP_STAT_BSY) == SET)
| 2 | {};
|
Das wäre ja OK, wenn dies nicht in einem Task vom FreeRTOS wäre. So ist
das ja nicht sonderlich performant ...
Meine Idee wäre nun gewesen die SSP Interrupts zu verwenden. Nur
verstehe ich nicht, wie mir diese signalisieren, dass ein EINZELNER
Frame übertragen wurde.
Im Datenblatt finde ich nur folgenede Interrupts:
0 RORIM
Software should set this bit to enable interrupt when a Receive Overrun
occurs, that is, when the Rx FIFO is full and another frame is
completely received. The ARM spec implies that the preceding frame data
is overwritten by the new frame data when this occurs.
1 RTIM
Software should set this bit to enable interrupt when a Receive Time-out
condition occurs. A Receive Time-out occurs when the Rx FIFO is not
empty, and no has not been read for a "time-out period".
2 RXIM
Software should set this bit to enable interrupt when the Rx FIFO is at
least half full.
3 TXIM
Software should set this bit to enable interrupt when the Tx FIFO is at
least half empty.
Da sowohl Empfangs- als auch Sende-Fifo 8 Frames gross sind, würden die
letzten beiden Interrupts ja sofort aktiviert werden - nicht NACH der
Übertragung des einzig anstehenden Frames.
Damit kann ich die Interrupts nicht vernünftig nutzen ... oder?
ausprobiert hätte ich folgendes: 1 | while(Chip_SSP_GetStatus(LPC_SSP0, SSP_STAT_BSY) == SET)
| 2 | vTaskDelay(1);
|
Damit bekomme ich aber Overflow Fehler vom RFM12B. Einen RTOS Tick zu
warten, dürfte zu lange dauern und damit die Bytes aus dem RFM12B Fifo
zu langsam abholen.
Wie sollte das denn funktionieren? Irgendwie muss das doch mit den
Interrupts möglich sein ...
Danke für eure Hilfe!
vG Alram
Alram Lechner schrieb:
> Meine Idee wäre nun gewesen die SSP Interrupts zu verwenden. Nur
> verstehe ich nicht, wie mir diese signalisieren, dass ein EINZELNER
> Frame übertragen wurde.
Im Master Mode ist das einfach: Einen einzelnen Frame via SSPxDR senden,
und mit dem RTRIS Bit einen Interrupt auslösen lassen - das hat nur ein
paar Takte Verzögerung.
Man könnte übrigens auch einen DMA-Kanal mißbrauchen, der einfach nur
für ein Byte (bzw. half-word) ausgelegt wird.
Andererseits macht man im Interrupt Modus bei SPI oftmals keinen Gewinn
gegenüber einfachem Polling, denn die Interrupts haben natürlich auch
eine Latenz.
Hallo Jim,
Danke für den Tipp mit dem RTRIS - das sieht so aus, als ob ich nur 32
Takte der SSP Frequenz 'verliere' - das dürfte wohl schnell genug sein.
Jim Meba schrieb:
> Andererseits macht man im Interrupt Modus bei SPI oftmals keinen Gewinn
> gegenüber einfachem Polling, denn die Interrupts haben natürlich auch
> eine Latenz.
Das ist für mich gerade ein ziemliches Performanceproblem. Da die CPU
mit 96 MHz und der SSP mit 2,5 MHz getaktet ist, 'verbratet' der Task
(nach meiner Rechnung) über 1600 Takte im Polling für jedes Empfangene
Byte.
Das bekommt der LCD Task deutlich zu spüren ...
vG Alram
Alram Lechner schrieb:
> Da die CPU
> mit 96 MHz und der SSP mit 2,5 MHz getaktet ist,
Bei diesen Daten lohnt sich Interrut Modus dann doch. Die DMA- Methode
hätte übrigens keine zusätzliche Wartezeit zur Folge, und man könnte
komplette Pakete austauschen.
Jim Meba schrieb:
> Die DMA- Methode
> hätte übrigens keine zusätzliche Wartezeit zur Folge, und man könnte
> komplette Pakete austauschen.
hmmm klingt interessant ... hab noch nie mit DMA gearbeitet. Wie hoch
ist da der Einlernaufwand? Kann man das grob abschätzen? Ich weiss,
hängt von vielen Faktoren ab - nicht zuletzt von meiner Auffassungsgabe
;)
vG Alram
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|