Forum: Mikrocontroller und Digitale Elektronik RFM12b von Polling zu Int (AVR)


von Manfred Bär (Gast)


Lesenswert?

hallo zusammen,

ich habe folgendes Problem. Zurzeit versuche ich (mithilfe der jeelib) 
Daten über 2 RFM12b (868) von einen Arduino auf einen anderen zu 
übertragen. Dabei funktioniert das ganze über Polling ohne Probleme.
Nun möchte ich das ganze auf Interrupt umbauen.

Aktuell löst der Interrupt  verlässlich aus, sobald der Sender Daten 
funkt, diesen überprüfe ich in der ISR mithilfe des Statusbits und lese 
bei 0x8xxx den FIFO aus. (0x8xxx, da die 8 für das FFIT steht, bekomme 
aber meistens 0x801E, selten z.b. 0x8060 und fast nie 0x8000)

Leider bekomme ich je nach Status unterschiedliche (schlechte) Werte, 
welche ich über 0xB000 auslese.
Beim meistens gelesenem 0x801E bekomme ich immer (unabhängig von 
gesendeten Daten) 31dez, bei den anderen Kombinationen andere, 
verschiedene falsche Werte.

Meine aktuelle Config sieht folgendermaßen aus:

0x80E8
0x82D9
0xA640
0xC606
0x97A2
0xC22C
0xCA81
0xCED4
0xC467
0x9800
0xCC77
0xB8AA
0xC80E
0xCA83

Grüße, Manfred

von Christian K. (the_kirsch)


Lesenswert?

Ist zwar bei mir mit dem RFM12 schon etwas her, aber ich hatte damals 
meine Ansteuerung auch komplett über Interrupts gelöst.

Immer wenn das RFM-Modul ein Interrupt ausgelöst hat habe ich per SPI 
das Statusregister ausgelesen. Und je nach dem in welchen Zustand die 
Software war darauf reagiert.

Meinen Code von damals will ich hier nicht posten, aber so hatte ich ihn 
konfiguriert:
1
/* Configuration Setting = 80E7: el=1; ef=1; b=2; x=7 */
2
/* Power Managment = 82D9: er=1; ebb=1; et=0; es=1; ex=1; eb=0; ew=0; dc=1 */
3
/* Frequency Setting = A67C: f=1660 => 868,3 MHz */
4
/* Data Rate = C647: r=71 ; cs=0 => 4,79 kbps */
5
/* Data Rate = C67F: r=127; cs=0 =>  2,7 kbps */
6
/* Power Setting = 90A4: p16=0; d=0; i=4; g=0; r=4 => BW=200kHz; gain=0dB */
7
/* Data Filter = C2AC: al=1; ml=0; s=0; f=4 */
8
/* FIFO Reset Mode = CA81: f=8; al=0; ff=0; dr=1 */
9
/* AFC = C483: a=2; rl=0; st=0; fi=0; oe=1; en=1 */
10
/* TX Configuration Control = 9850: m=5; p=0 */
11
/* Wake-Up Timer = E000: r=0 m=0 */
12
/* Low Duty-Cycle = C800: d=0; en=0 */
13
/* Low Battery and Clock Divider = C000: d=0; v=0 */
14
15
#define SI4420PHYSICAL_CONFIGURATION_SETTING         0x80E7
16
#define SI4420PHYSICAL_POWER_MANAGMENT               0x82D9
17
#define SI4420PHYSICAL_FREQUENCY_SETTING             0xA67C
18
#define SI4420PHYSICAL_DATA_RATE                     0xC67F
19
#define SI4420PHYSICAL_POWER_SETTING                 0x90A4
20
#define SI4420PHYSICAL_DATA_FILTER                   0xC2AC
21
#define SI4420PHYSICAL_FIFO_RESET_MODE               0xCA81
22
#define SI4420PHYSICAL_AFC                           0xC483
23
#define SI4420PHYSICAL_TX_CONFIGURATION_CONTROL      0x9850
24
#define SI4420PHYSICAL_WAKE_UP_TIMER                 0xE000
25
#define SI4420PHYSICAL_LOW_DUTY_CYCLE                0xC800
26
#define SI4420PHYSICAL_LOW_BATTERY_AND_CLOCK_DIVIDER 0xC000

von Manfred Bär (Gast)


Lesenswert?

Hallo Christian,

danke für deine Configs, leider wird damit bei mir kein Interrupt mehr 
ausgelöst.
nIRQ bleibt dauerhaft auf high.

Grüße, Manfred

von Christian K. (the_kirsch)


Lesenswert?

Hab für das Modul 3 Oberzustände: Idle, Listening, und Sending

Nach dem ich die obige Konfiguration gesetzt habe, kommt noch ein 
abschließendes 0x8201 um in den Idel-Zustand zu gehen.

Hab hier noch mal nachgeschaut
https://www.silabs.com/documents/public/data-sheets/Si4420.pdf

Das letzte POWER_MANAGMENT Command setzt das Modul wieder in den 
Tiefschlaf

Zur Vollständigkeit:

Für den ListeningMode sende ich
0x82C8 und 0xCA83

und für den SendingMode
0x8238

von Manfred Bär (Gast)


Lesenswert?

Ich benutze den RFM12b, aber der sollte ja bis auf die 
Versorgungsspannung weitestgehend identisch sein. leider ist der FIFO 
lesebefehl nicht sehr ausführlich.

Irgendetwas liegt bei mir noch im Argen...mit deiner Config passiert wie 
gesagt überhaupt nichts. Ich betreibe sie sogar jeweils fest als Sender 
und den anderen als Empfänger, da muss das doch nochmal ein Stück 
einfacher sein.

Hast du die Daten auch per 0xB000 ausgelesen?

von Christian K. (the_kirsch)


Lesenswert?

ja genau, solange das rgit_ffit-Bit im Statusregister gesetzt ist, lese 
ich mit 0xB000 den Fifo aus

von Manfred Bär (Gast)


Lesenswert?

ist es bei dir egal, ob das FFIT Bit allein oder zusammen mit anderen 
Bits gesetzt ist?

von Christian K. (the_kirsch)


Lesenswert?

Der nIRQ-Ausgang bleibt solange Hi, bis alle 6-Interrupt-Bits gelöscht 
sind.

Während die Bits 1-5 durch das Auslesen des Statusregister gelöscht 
werden, wird Bit 0 (also RGIT/FFIT) nur gelöscht wenn:
* der FIFO beim Empfangen-Modus unterhalb des Limits (Parameter "f", bei 
mir 8 Bit) ist
* und beim Senden-Modus der FIFO NICHT voll.

von Christian K. (the_kirsch)


Lesenswert?

Wie gesagt lese ich immer das ganze Statusregister aus, wenn nIRQ auf Hi 
geht.


EDIT:
Mein Code ist vom 2010, und habe jetzt beim Überfliegen einen Bug 
entdeckt, wenn im FIFO genau 16 Bit liegen (also voll aber noch kein 
overflow) bleibt meine State-Maschine hängen, da ich 8 Bits auslese, 
bleiben ja noch 8 Bits im Fifo und nSEL geht nicht auf LOW. Aber ich 
reagiere nur auf Steigende Flanken.


Da meine Software aber den Fifo immer direkt ausliest kommt es nie zu 
diesem Problem. Zumindest in der Anwendung damals.

: Bearbeitet durch User
von Manfred Bär (Gast)


Lesenswert?

Danke für die Info. Ich habe das Datenblatt bereits gelesen, nur kriege 
ich den Baustein damit nicht zum Laufen.

Den nsel benutze ich nicht. Im Grunde hat er ja die gleiche Funktion wie 
nIRQ, nur andersherum gerichtet.

Mir ist aufgefallen dass du nirq auf steigende Flanke auswertest. Beim 
RFM12b muss ich auf fallende Flanke (oder direkt low) abfragen. Ich 
werde mir heute Abend mal zusätzlich das Datenblatt vom RFM12 ansehen.

von Christian K. (the_kirsch)


Lesenswert?

Manfred Bär schrieb:
> Den nsel benutze ich nicht. Im Grunde hat er ja die gleiche Funktion wie
> nIRQ, nur andersherum gerichtet.

Mein Fehler, ich meinte natürlich nIRQ.

Manfred Bär schrieb:
> Beim
> RFM12b muss ich auf fallende Flanke

Auch da hast du recht. Es ist natürlich die fallende Flanke auf die 
getriggert werden muss. Wie gesagt das Projekt liegt bei mir bereits 7 
Jahre zurück.

von Manfred Bär (Gast)


Lesenswert?

Kein Problem, ich bin für jede Hilfe dankbar.

Leider bin ich bis morgen Abend nicht zuhause, aber mir ist folgendes 
klargeworden:

Beim Auslesen der Interrupts habe ich nur diejenigen mit 0x8xxx 
"durchgelassen" (und in der Konsole ausgegeben.) Nun erinnere ich mich 
aber daran -wenn ich alle ankommenden Interrupts angezeigt habe- dass 
jeder zweite 0x2xxx (oder 0xAxxx) war. In beiden Fällen ist das 
FIFO-Überlaufbit gesetzt...und das obwohl ich es auslese...Demzufolge 
müsste ja der FIFO-Read-Befehl (von jeelib) nicht richtig funktionieren.
Das wiederum kann ich mir nicht vorstellen.

Wieviele Bits werden denn mit einem Befehl ausgelesen? Im Datenblatt 
wird nicht darauf eingegangen. Sollten es z.b. 8Bit sein müsste ich es 
ja 2x hintereinander auslesen um es komplett zu leeren (falls es 
komplett voll war).

Naja, ich werde das ganze verifizieren sobald ich Zeit finde.

von Manfred Bär (Gast)


Lesenswert?

Also, scheinbar funktioniert doch fast(!) alles wie es soll. Es ist nur 
so, dass der empfangene Wert "33" eben nicht die gewollten Daten sind 
sondern HDR (wie hier zu sehen: 
http://jeelabs.org/2011/06/09/rf12-packet-format-and-design/index.html#comments).

...nur wie schaffe ich es nun stattdessen auf meine Daten zuzugreifen?

von Christian K. (the_kirsch)


Lesenswert?

Mit der RF12 library hab ich keine Erfahrung.

Hab da alles selber gemacht. Inclusive eines Package-Format: 6Byte 
Ziel-Adresse, 6Byte Source-Adresse, 5 Bit Typ, 11 Bit Länge, Payload und 
2 Byte CRC

Hab mich da an Ethernet Orientiert.



Bin mir gerade nicht sicher was du vor hast, willst du von der jeelib 
weg und alles selber machen, oder die Lib umbauen?

von Manfred Bär (Gast)


Lesenswert?

das ist mein erstes Projekt mit Funkmodulen und ich will dafür 
eigentlich nur Temperaturdaten von einem zum anderen senden. Für dieses 
mal reicht mir auch einfach eine funktionierenden fertige Library, nur 
leider bekomme ich die Übertragung über Interrupt nicht hin.

Kurz: Ich will sowenig wie möglich umbauen, sondern nur eine einfache 
Funkstrecke über Interrupts.

von Manfred Bär (Gast)


Lesenswert?

Hallo zusammen,

Gut, um meine Frage zu präzisieren:
Angenommen ich sende ein Paket mit einer großen Datenmenge, z.B. 8Byte.
Der FIFO kann ja nur 2Byte halten. Natürlich kann ich die ersten 2Byte 
über den Interrupt zügig abholen, aber liefert der Sender nicht die 
8Byte in einem Schwung?

Selbstverständlich lässt sich bei ein großes Paket in einzelne kleine 
Pakete aufteilen, um die Signale geordnet abzuarbeiten. Dieses Beispiel 
soll aber nur mein Problem verdeutlichen.

In meinem Fall wird ein 16Bit-Wert übertragen, aber vor den Daten werden 
Syncbyte etc. übertragen, diese landen nicht im FIFO, das habe ich 
verstanden. Aber direkt vor meinen Daten werden noch Informationen 
bezüglich Länge der Daten, Acknowledge und die NodeID übertragen, nun 
schaffe ich es nur genau diese Daten auszulesen. Die (vermutlich) ohne 
Unterbrechung danach gesendeten für mich wichtigen Daten würden den FIFO 
während ich noch in der ISR bin überschreiben.

Nun habe ich einen Versuch gestartet den FIFO erst beim 2. Auffüllen 
(was meine Daten sein sollten) auszulesen, auch hier empfange ich leider 
das gleiche wie zuvor.

Gruß, Manfred

von c-hater (Gast)


Lesenswert?

Manfred Bär schrieb:

> Angenommen ich sende ein Paket mit einer großen Datenmenge, z.B. 8Byte.
> Der FIFO kann ja nur 2Byte halten.

Maximal!

Das Interruptflag wird aber gesetzt, sobald er das erste Byte im Sack 
hat. Die restlichen Bits des FIFO sind nur der Puffer, der es dir 
überhaupt ermöglicht, dieses eine Byte abzuholen, bevor das erste Bit 
des nächsten da ist und in das Empfangsregister übernommen werden 
müsste...

Sprich: das ist eigentlich ein klassischer double buffer. Jedenfalls in 
dieser Anwendung. Man kann die RFM12 auch anders verwenden und den FIFO 
tatsächlich bitweise verwenden, aber das ist wohl weit jenseits deiner 
Liga und vor allem: für deine Anwendung auch nicht nützlich...

> Natürlich kann ich die ersten 2Byte
> über den Interrupt zügig abholen

Das darfst du nicht! Du würdest einfach das gleiche Byte noch einmal 
bekommen. Erst wenn das nächste Mal das Interruptflag gesetzt ist, sind 
die nächsten 8 empfangenen Bits in dem Register gelandet, was du 
auslesen kannst.

> aber liefert der Sender nicht die
> 8Byte in einem Schwung?

Ja klar, jedenfalls, wenn du den Sender so programmiert hast, dass er 
das tun soll...

> Selbstverständlich lässt sich bei ein großes Paket in einzelne kleine
> Pakete aufteilen, um die Signale geordnet abzuarbeiten.

Das ist nicht nötig. Man muß einfach nur das eine Paket richtig 
verarbeiten, das ist alles.

> Aber direkt vor meinen Daten werden noch Informationen
> bezüglich Länge der Daten, Acknowledge und die NodeID übertragen, nun
> schaffe ich es nur genau diese Daten auszulesen. Die (vermutlich) ohne
> Unterbrechung danach gesendeten für mich wichtigen Daten würden den FIFO
> während ich noch in der ISR bin überschreiben.

Dann ist deine ISR schlicht zu langsam. Wenn du nicht in der Lage bist, 
daran etwas zu ändern, hilft nur eins: du mußt das gesamte Datenpaket im 
RAM puffern und ansonsten nix in der ISR tun. Maximal die Länge des zu 
erwartetenden Paketes aus den empfangenen Daten extrahieren, wenn diese 
Länge nicht fix ist.

Erst wenn das Paket vollständig empfangen ist, geht's weiter. Aber nicht 
in der ISR. Oder zumindest nicht ohne Ende der exclusiven 
Codeabarbeitung in dieser letzten ISR-Instanz des Paketes...

von Manfred Bär (Gast)


Lesenswert?

Danke für deine schnelle Antwort.

c-hater schrieb:
> Maximal!
>
> Das Interruptflag wird aber gesetzt, sobald er das erste Byte im Sack
> hat. Die restlichen Bits des FIFO sind nur der Puffer, der es dir
> überhaupt ermöglicht, dieses eine Byte abzuholen, bevor das erste Bit
> des nächsten da ist und in das Empfangsregister übernommen werden
> müsste...

Meine Datenvariable ist derzeit ein int mit 16 Bit, also past genau in 
den FIFO. Ein Anfang wäre es also, stattdessen ein unit8_t zu verwenden? 
Für meine Daten wäre das kein Problem. Mein Interrupt "feuert" bereits 
nach den ersten 8 Bit, demzufolge ging ich davon aus, dass es klappen 
sollte.

c-hater schrieb:
> Das darfst du nicht! Du würdest einfach das gleiche Byte noch einmal
> bekommen. Erst wenn das nächste Mal das Interruptflag gesetzt ist, sind
> die nächsten 8 empfangenen Bits in dem Register gelandet, was du
> auslesen kannst.

Ich ging davon aus, dass beim Auslesen die Daten im FIFO jeweils um 1 
Byte weitergeschoben werden. Danke für die Aufklärung. Jetzt macht auch 
die Aussage mit dem Dummybyte zum Schluss (über die ich hin und wieder 
gestolpert bin) Sinn. Vielen Dank für die Erleuchtung.

c-hater schrieb:
>> aber liefert der Sender nicht die
>> 8Byte in einem Schwung?
>
> Ja klar, jedenfalls, wenn du den Sender so programmiert hast, dass er
> das tun soll...

das stimmt natürlich, ich wollte damit auf das zeitliche Problem -dass 
nach meinem Verständnis auftritt- verdeutlichen. Ich verwende die 
Jeelib, und habe vor allem was den Aufbau der gesendeten Pakete angeht 
wenig Überblick.

c-hater schrieb:
> Dann ist deine ISR schlicht zu langsam. Wenn du nicht in der Lage bist,
> daran etwas zu ändern, hilft nur eins: du mußt das gesamte Datenpaket im
> RAM puffern und ansonsten nix in der ISR tun. Maximal die Länge des zu
> erwartetenden Paketes aus den empfangenen Daten extrahieren, wenn diese
> Länge nicht fix ist.

meine ISR ist zugegebenermaßen relativ lang, allerdings wird der 
Großteil nur ausgeführt wenn ich wirklich die Nutzdaten empfangen habe. 
Soweit der Plan. Abgesehen davon ist sie vernachlässigbar im Bezug auf 
die zeitlichen Abstände zwischen den Paketen.

Mein letzter Versuch war folgender:
Um auf die Daten die später übertragen werden zugreifen zu können, habe 
ich beim ersten Interrupt nur einen Counter inkrementiert, den FIFO 
ausgelesen um den FFIT abzuarbeiten und den FIFO neu gestartet. Viel 
kürzer lässt sich der ISR nicht erledigen oder?
Erst wenn der Counter eine gewisse Anzahl erreicht hat, werden die Daten 
erfasst und weiterverarbeitet.
Ist dies prinzipiell so machbar? Wenn ja hat sich einfach noch ein 
Fehler eingeschlichen, wenn nein wäre ich über Aufklärung dankbar :)

von c-hater (Gast)


Lesenswert?

Manfred Bär schrieb:

> Um auf die Daten die später übertragen werden zugreifen zu können, habe
> ich beim ersten Interrupt nur einen Counter inkrementiert, den FIFO
> ausgelesen um den FFIT abzuarbeiten

Bis hierher schick und richtig.

> und den FIFO neu gestartet

Vollkommen falsch. Der muß einfach weiter laufen, um die nächsten 8 Bits 
zu empfangen. Einige davon hat er mit einiger Wahrscheinlichkeit bereits 
empfangen, während du noch das Flagregister und das empfangene Byte 
liest. Wenn du jetzt den Fifo zurücksetzt, sind diese Bits wech und der 
ganze Rest, den du ausliest, wird Müll sein...

von Manfred Bär (Gast)


Lesenswert?

c-hater schrieb:
>> und den FIFO neu gestartet
>
> Vollkommen falsch. Der muß einfach weiter laufen, um die nächsten 8 Bits
> zu empfangen. Einige davon hat er mit einiger Wahrscheinlichkeit bereits
> empfangen, während du noch das Flagregister und das empfangene Byte
> liest. Wenn du jetzt den Fifo zurücksetzt, sind diese Bits wech und der
> ganze Rest, den du ausliest, wird Müll sein...

meine Intention dahinter war, den FIFO für den nächsten Interrupt zu 
befähigen.

Dafür schreibe ich die Befehle
0xCA81 und danach 0xCA83

Eventuell habe ich mich einfach schlecht/falsch ausgedrückt.

von Manfred Bär (Gast)


Lesenswert?

Ok, ich habe das Datenblatt nochmal zu Rate gezogen. In der Tat 
unterbrechen diese das Auffüllen des FIFO für eine kurze Zeit. Womöglich 
habe ich etwas falsch interpretiert. Das bedeutet, durch das Auslesen 
allein wird der Interrupt zurückgesetzt und ist wieder startbereit.

von c-hater (Gast)


Lesenswert?

Manfred Bär schrieb:

> Das bedeutet, durch das Auslesen
> allein wird der Interrupt zurückgesetzt und ist wieder startbereit.

Genauso ist das. Analog dazu funktioniert auch das Senden, hier setzt 
der Schreibvorgang den Interrupt zurück.

Alle anderen Interruptbits werden hingegen allein schon durch das Lesen 
des Statusregisters zurückgesetzt. Das Schema der Interruptbehandlung 
ist also ziemlich einfach.

Allerdings gibt es eine Sache, die es dann doch wieder komplizierter 
macht. Nämlich den Fall, dass ein Interrupt auftritt, während du gerade 
beim Datenaustausch mit dem RFM bist, also gerade ein SPI-Vorgang läuft. 
Dann darf der NICHT einfach abgebrochen werden, um das Statusregister 
zu lesen, sondern sollte schön bis zum Ende ausgeführt werden. Erst 
danach dann das Statusregister lesen.

von Felix P. (fixxl)


Lesenswert?

Das RFM12(B) hat im Gegensatz zu seinem mittlerweile ganz gut 
etablierten Nachfolger RFM69CW den Nachteil, dass man den Empfang 
aufgrund des sehr kleinen FIFOs quasi in Echtzeit abwickeln muss: Das 
Byte vom Sender kommt rein, das Modul signalisiert das, man muss die 
Daten umgehend abholen und dann heißt es darauf zu warten, bis das 
nächste eintrudelt, womit die Story wieder von vorne beginnt. Wie 
schnell hintereinander die Daten eintreffen, liegt logischerweise an der 
Datenrate des Senders.

Ein Neustart des FIFO zwischen den Bytes darf nicht erfolgen, denn damit 
sperrt man die Annahme von Bytes so lange, bis die beiden Schlüsselbytes 
(beim RFM12 0x2D, 0xD4) wieder gesendet werden, um den FIFO wieder für 
den Datenempfang zu öffnen. Erst wenn das komplette Datenpaket empfangen 
wurde, sollte man den Empfänger neu starten.

von Manfred Bär (Gast)


Lesenswert?

Hallo Felix, das stimmt...man verliert nicht nur die Daten während der 
FIFO ausgeschaltet ist, sondern das komplette restliche Paket. Danke für 
den Hinweis.

dank c-hater konnte ich gestern auch meinen Empfang relativ stabil auf 
meine Daten umstellen. Das bedeutet: Löst der Interrupt aus bekomme ich 
bis auf seltene Ausnahmen (fehlerhafte Übertragung?) richtige Daten am 
Empfänger. Vielen Dank!

Ein kleiner Dämpfer ist die Tatsache, dass die Interrupts nicht immer 
mitspielen. Damit meine ich nicht, dass ein paar verschluckt werden, 
vielmehr geht nach dem Kompilieren und Überspielen des Codes entweder 
(fast) alles reibungslos oder garnichts. Auch wenn ich den Arduino 
während er fleissig empfängt abstecke und wieder anstecke ist nicht 
sicher ob er wirklich wieder Ints registriert.

Ich habe schon mitbekommen, dass die RFMs zickig seien, was die 
Versorgungsspannung angeht, aber das genannte Verhalten spricht meiner 
Meinung nach nicht für unsaubere Versorgung.

von c-hater (Gast)


Lesenswert?

Manfred Bär schrieb:

> Ein kleiner Dämpfer ist die Tatsache, dass die Interrupts nicht immer
> mitspielen. Damit meine ich nicht, dass ein paar verschluckt werden,
> vielmehr geht nach dem Kompilieren und Überspielen des Codes entweder
> (fast) alles reibungslos oder garnichts.

Bekanntes Problem. Drei mögliche Ursachen:

1)
Du hast den Reset des RFM nicht mit dem Reset deines Steuercontrollers 
gekoppelt (und benutzt die Hardware-SPI-Schnittstelle deines Controllers 
zur Kommunikation mit dem RFM und hast keine Vorsorge im Sinne der 
Eigensicherheit getroffen, also AVR-SS/RFM-SEL nicht per physischem 
Widerstand auf Low gezogen).

Dann hast du dem RFM u.U. implizit DURCH das Programmieren völligen 
Gurkensalat gesendet, von dem er sich nur schwer wieder erholt. Beachte: 
SPI und ISP benutzen bei den meisten Megas die gleichen Pins...

2)
Du hast den Reset des RFM mit dem Reset deines Controllers mit dem Reset 
des RFM gekoppelt.

Dann hast du zwar nicht das Gurkensalat-Problem, aber dafür ein anderes: 
Nach einem Reset des RFM mußt du eine gewisse, recht lange Zeit warten, 
bevor du ihn das erste Mal mit irgendeiner SPI-Aktivität behelligen 
darfst, sonst landet er auch wieder im Wald und findet nicht mehr raus. 
Ich kann mich nicht mehr erinnern, was das DB dazu sagte (auf jeden Fall 
wurde das Problem dort erwähnt, da bin ich ziemlich sicher), ich warte 
in meinem Code jedenfalls in dieser Situation mindestens 50ms. Und er 
funktioniert sehr zuverlässig, auch nach einem Reset. ;o)

3)
Du benutzt einfach den falschen Typ Interrupt in deinem AVR. Die 
Interrupts des RFM sind vom Charakter her Level-Interrupts, also so 
lange Low, wie irgendeine Interruptursache besteht, also nicht alle 
Interrupts zurückgesetzt sind. Dementsprechend kannst du auf AVR-Seite 
auch nur entweder einen LowLevel-Interrupt verwenden oder du mußt die 
ISR eines Edge-Interrupts so gestalten, dass effektiv die Wirkung eines 
LowLevel-Interrupts erzielt wird.

Ich mache das in meinem Code allerdings ziemlich anders. Bei mir läuft 
die gesamte Logik der Kommunikation mit dem RFM in einer Statemachine in 
der SPI-ISR. Den externen Interrupt des RFM benutze ich nur dazu, um den 
SPI-Interrupt zu enablen, wenn er das gerade nicht ist. Die SPI-ISR 
ihrerseit muss dann natürlich immer am Ende eines Datenaustauschs 
entscheiden, was sie weiter tut. Dazu schaut sie auf den Pegel des 
Interruptpins. Ist der Low, macht sie eine Abfrage des Statusregisters 
des RFM, ansonsten disabled sie ihren eigenen Interrupt.

Das Ergebnis ist das gleiche, wie bei Verwendung eines 
LowLevel-Interupts, die Sache ist nur deutlich effizienter und hat den 
Vorteil, dass das Problem des RFM-Interrupts bei laufender 
SPI-Kommunikation ohne jeden zusätzlichen Verwaltungsaufwand gleich mit 
abgehandelt wird.

von Manfred Bär (Gast)


Lesenswert?

hallo c-hater,

danke für die ausführliche Antwort!
ich habe tatsächlich die Resets nicht gekoppelt.

Das heißt ich verbinde die beiden Pins und lege sie über Pulldown auf 
Masse?

c-hater schrieb:
> Nach einem Reset des RFM mußt du eine gewisse, recht lange Zeit warten,
> bevor du ihn das erste Mal mit irgendeiner SPI-Aktivität behelligen
> darfst, sonst landet er auch wieder im Wald und findet nicht mehr raus.

da das Projekt später in der Regel durchlaufen soll und dementsprechend 
nicht oft einen Reset erfährt ist die Wartezeit unproblematisch, ich 
gönne ihm aktuell sogar 200ms :)

c-hater schrieb:
> Ich mache das in meinem Code allerdings ziemlich anders. Bei mir läuft
> die gesamte Logik der Kommunikation mit dem RFM in einer Statemachine in
> der SPI-ISR. Den externen Interrupt des RFM benutze ich nur dazu, um den
> SPI-Interrupt zu enablen, wenn er das gerade nicht ist. Die SPI-ISR
> ihrerseit muss dann natürlich immer am Ende eines Datenaustauschs
> entscheiden, was sie weiter tut. Dazu schaut sie auf den Pegel des
> Interruptpins. Ist der Low, macht sie eine Abfrage des Statusregisters
> des RFM, ansonsten disabled sie ihren eigenen Interrupt.

das klingt nach einer gut durchdachten Möglichkeit, allerdings traue ich 
mich noch nicht dran, sowas in der Art selbst umzusetzen.

von Manfred Bär (Gast)


Lesenswert?

Nach längerer Zeit habe ich nun wieder Zeit gefunden.

Ich hab nun die beiden Reset-Pins miteinander verbunden, leider 
funktioniert nun garnichts mehr. Auch mit einem Testprogramm zum 
Überprüfen der Funktionalität der Module wird nichts empfangen. Es 
scheint so als ob durch die Verbindung der Resets der Bausteil zerstört 
wurde?

Beitrag #6891179 wurde von einem Moderator gelöscht.
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.