Hallo zusammen,
ich programmiere schon seit einigen Wochen 2 Platinen mit dem RFM12. Ein
als Sender und ein als Empfänger. Der Sender sendet alle paar ms Daten
an den Empfänger. Der Empfänger hat folgenden Code womit es auch
tadellos funktioniert:
1
intmain(void)//Hauptprogramm
2
{
3
initPorts();//AVR-Ports initialisieren
4
initUART();//zu Testzwecken
5
initInterrupt();//Interrups initialisieren
6
7
Power_On();//Powern On Prozedur
8
9
RFM_ON();//RFM einschalten //TODO RFM muss auf Dauer+
10
_delay_ms(200);//Etwas Zeit verbummeln bis das Modul bereit ist
In der Beschreibung aus Robotik-Hardware
http://robotikhardware.de/download/RN-MikroFunk_1.7.pdf steht, dass der
RFM12 einen Interrupt auslöst, sobald das Synchronisationsmuster
(0x2DD4) erkannt wird. In der Interrupt-Routune lasse ich nur ein Port
togglen, den ich mit dem Ossi messen kann. So sehe ob der Interrupt
auslöst. Und das ist der Fall.
Der Code ist aber nicht besonders elegant, da der µC in der Zeile
1
while(PIND&(1<<RFM_IRQ))
solange wartet, bis der RFM_IRQ auf low springt. Deswegen wollte ich mit
der Interrupt-Routine die Daten erst dann auswerten, sobald das
Synchronisationsmuster empfangen wird. Doch sobald ich zu Testzwecken
die Zeile
1
while(PIND&(1<<RFM_IRQ))
auskommentiere, müsste er RFM12 meiner Meinung nach, ständig Interrupts
auslösen, doch passiert gar nichts. Er löst kein Interrupt aus. Aber
warum nicht ??? Die rote LED blinkt und zeigt, dass die Checksumme ok
ist, aber warum kein Interupt ???
Ich halte mich so zielmlich an die Beschreibung, was genaue diese
Funktion ab S. 65 beschreibt.
Wo ist mein Denkfehler ???
Gruss
Peter F. schrieb:> Der Empfänger hat folgenden Code womit es auch> tadellos funktioniert:
Das finde ich insoweit interessant, als dem Datasheet gemäss der
Receiver eigentlich erst eingeschaltet werden müsste. Siehe Power
Management Command = 0x82xx.
Peter F. schrieb:> In der Beschreibung aus Robotik-Hardware [...] steht, dass der> RFM12 einen Interrupt auslöst, sobald das Synchronisationsmuster> (0x2DD4) erkannt wird.
Wo genau? Kann ich da auf die Schnelle nicht finden. Im Datasheet stehen
zwar ein paar Gründe für Interrupts, aber dieser gehört nicht dazu. Da
die Synchronisation selbst nicht im FIFO auftaucht kommt der Interrupt
vielmehr erst, nachdem genug Nutzdatenbits empfangen wurden.
MCUCR |= (0<<ISC01) | (0<<ISC00);
Hast du's so schonmal probiert?
Ich habe nen Interrupt beim Senden (Wakeup) und einen beim Empfang. Bei
mir sind ISC01 und ISC00 beide auf 0.
Guckst Du hier: http://bralug.de/wiki/RFM12-Funkbr%C3%BCcke
A. K. schrieb:> Das finde ich insoweit interessant, als dem Datasheet gemäss der> Receiver eigentlich erst eingeschaltet werden müsste. Siehe Power> Management Command = 0x82xx.
Mach ich doch mit:
1
RFM_EMPF_EIN();//Empfang einschalten
A. K. schrieb:> Da> die Synchronisation selbst nicht im FIFO auftaucht kommt der Interrupt> vielmehr erst, nachdem genug Nutzdatenbits empfangen wurden.
Ok ich glaube ich vertue mich an der Stelle. Dann löst er halt ein
Interrupt aus, sobald er Nutzdaten hat. Tut er aber nicht sobald ich die
besagte Zeile auskommentiere. Die Nutzdaten werden aber trotzdem
gesendet, warum dann kein Interrupt ? Das einzige was ich im Code ändere
ist nur die Zeile:
1
while(PIND&(1<<RFM_IRQ))
Stefan B. schrieb:> MCUCR |= (0<<ISC01) | (0<<ISC00);>> Hast du's so schonmal probiert?
Ja. Das macht kein Unterschied. Der nIRQ vom RFM12 steht bei nicht
auskommentierter Zeile, immer auf High und springt kurz auf Low. Ob ich
jetzt die Flanke nutze oder den Pegel ändert nichts.
Hab Dir mal ein Beispiel angehängt.
Empfänger sowie Sender haben einen Atmega328p mit internen 8Mhz.
Empfänger läuft mit 5v (mit Spannungsteiler für den RFM12B), Sender mit
3,3V.
Sind 868Mhz-Teile, aber das macht keinen Unterschied. Dieses Prog funzt
auch bei 433Mhz.
Sender sendet mit Wake-Up-Timer im Abstand von 1.5 mins. Beispiel für 6
sowie 60 Sekunden auch dabei.
Empfang funzt mit INT0 Interrupt.
Habs Programm kurz reduziert, so dass man leichter durchblickt. Die
Einrückungen sind mein Stil, ich finds besser so.
Ist von der o.g. Bralug-Seite.
Musst Dir nur die Mühe machen, das Ding mal runter zu laden, entpacken
und anschauen. Es ist alles darin gut beschrieben.
Hier: http://kanal35.npage.de/funkmodul.html gibts nen echt gut
gemachten RFM-Calculator.
Gruss und nen guten Rutsch
Peter F. schrieb:> Der nIRQ vom RFM12 steht bei nicht> auskommentierter Zeile, immer auf High und springt kurz auf Low. Ob ich> jetzt die Flanke nutze oder den Pegel ändert nichts.
Das ist Unsinn. Bei Interuptsteuerung MUSS ein pegelgetriggerter
Interrupt verwendet werden, sonst besteht die höchst reale Gefahr von
Deadlocks durch RFM-seitig aktive, aber vom AVR nicht mehr erkennbare
Interrupts.
Das ist doch logisch, wenn man bedenkt, daß es mehrere Interruptquellen
des RFM gibt und die Behandlung der Interrupts mindestens einen (relativ
länglichen) Lesevorgang des Statusregisters erfordert, bei vielen
Interrupts aber sogar noch weitere, noch länglichere Operationen.
Während dieser ganzen Zeiten können weitere Interrupts des RFM
auftreten, die dann keinen weiteren Pegelwechsel bei nIRQ mehr
verursachen, weil der vorige Interrupt ja aus RFM-Sicht noch nicht
behandelt und damit der nIRQ-Ausgang noch aktiv (also Low) war.
Natürlich muß aber auf AVR-Seite die Interruptbehandlung auch korrekt an
die Levelsteuerung angepaßt sein. Das Schema muß also ungefähr so
aussehen:
IRQ!
-deaktiviere Interrupt
-lies RFM-Statusregister
-behandle alle im Statuswort erkennbaren aktiven RFM-Interrupts,
insbesondere auch die, die eine über das Auslesen das Statuswortes
hinausgehende Behandlung erfordern. Das sind natürlich insbesondere
die,
die ein Einlesen oder Ausgeben von Daten erfordern.
-aktiviere Interrupt wieder
Nun können zwei Fälle auftreten. Entweder sind damit alle "pending"
Interrupts des RFM korrekt behandelt. Dann ist die Sache hiermit bis zum
nächsten Interrupt abgeschlossen, weil dann (und NUR dann!) der RFM
nIRQ auf High gelegt hat.
Oder es sind eben doch zwischenzeitlich weitere Interrupts im RFM
ausgelöst worden, dann landet man nach der Reaktivierung des Interrupts
umittelbar wieder bei "IRQ!", weil der nIRQ-Ausgang des RFM12 nach wie
vor auf Low liegt.