Forum: Mikrocontroller und Digitale Elektronik RFM12B am LPC1768.


von Alram L. (alram)


Lesenswert?

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

von Wolle G. (wolleg)


Lesenswert?

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"

von Alram L. (alram)


Lesenswert?

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

von Alram L. (alram)


Lesenswert?

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

von Jim M. (turboj)


Lesenswert?

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.

von Alram L. (alram)


Lesenswert?

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

von Jim M. (turboj)


Lesenswert?

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.

von Alram L. (alram)


Lesenswert?

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.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.