Forum: Mikrocontroller und Digitale Elektronik RFM12 Interrupt gesteuert


von Mann N. (hitec)


Lesenswert?

Hallo Zusammen,

ich bin seit lange Zeit mit dem Modul RFM12 beschäftigt, ich kann schon 
senden und empfängen ohne Interrupt. d.h ich hole die Daten ohne 
Interrupt ab. jetzt möchte ich die Daten holen nur wenn sie wirklich 
angekommen sind.
Pin nIRQ von RFM12 ist mit Interrupt (INT0) von Mikrocontroller 
angeschloßen.

der Modul ist wie folgendes initialisiert:

void rf12_init(void)
{
RF_DDR=(1<<SDI)|(1<<SCK);
PORTD|=(1<<SCK);
RF_DDR &= ~(1<<SDO);
DDRD|=(1<<CS);
PORTD|=(1<<CS);


_delay_ms(500); // wait until POR done

rf12_trans(0xC0E0); // AVR CLK: 10MHz
rf12_trans(0x80D7); // Enable FIFO
rf12_trans(0xC2AB); // Data Filter: internal
rf12_trans(0xCA81); // Set FIFO mode
rf12_trans(0xE000); // disable wakeuptimer
rf12_trans(0xC800); // disable low duty cycle
rf12_trans(0xC4F7); // AFC settings: autotuning: -10kHz...+7,5kHz
rf12_trans(0x0000);


}




/****** Interrupt 0 **************/

ISR(INT0_vect){
receive();
}

void init_INT0(void){
EICRA = (1<<ISC01)|(1<<ISC00); //rising Edge
EIMSK=0x01;
}

Mein Problem ist, der sender sendet jede Sekunde ein Packet aber 
Interrupt löst nicht aus beim empfänger, es ist auf high. wie soll ich 
RFM12 konfigurieren damit Interrupt funktioniert.

ich bitte sie um Ratschläge

"""Wer hilft wird geholfen"""

von Lorenz .. (lorenz)


Lesenswert?

Hi,
ich habe die RFM12-Module auch am Laufen, allerdings mir IRQ über den 
FFIT-Pin.
Dein Problem wird wahrscheinlich der IRQ selbst sein. Du hast den 
IRQ-Event auf "rising edge" gestellt. Jedoch ist der IRQ activ LOW. Dann 
musst du im IRQ-Handler selbst aber noch drauf achten, dass du auch 
wirklich alle Bytes abholst. Denn der IRQ des Moduls bleibt solange auf 
LOW, wie Daten vorhanden sind. Durch deine Flankentriggerung wird bei 
dir der IRQ aber nur 1x ausgelöst. Also evtl eine Schleife einbauen.

Lorenz

von Michael U. (amiga)


Angehängte Dateien:

Lesenswert?

Hallo,

vielleicht kannst Du hier was entnehmen:

die Routine empfängt bei mir Datenpakete von mehreren Sensoren.
Den Kram mit meinen Arrays kannst Du ja rauswerfen (Test Sensornummer, 
Prüfsumme, umkopieren in das globale Array).

Läuft hier seit Wochen stabil, manchmal unter
http://roehre.homeip.net

user: test Passwort: test zu erreichen.

Gruß aus Berlin
Michael

von Michael U. (amiga)


Angehängte Dateien:

Lesenswert?

Hallo,

hier noch das .h File dazu.

Gruß aus Berlin
Michael

von Mann N. (hitec)


Lesenswert?

Guten Tag,
Ich danke euch für eure schnelle Antworten, ich werde die Vorschläge 
verarbeiten, die Ergebnisse werde ich auf jeden Fall hier posten.
 bis gleich

von Mann N. (hitec)


Lesenswert?

Hallo Zusammen,

endlich kann ich jetzt senden und empfangen mit Hilfe von Interrupt 
(nIRQ).
dabei habe ich die Deklarationsreihe von Timer und external Interrupt 
ausgetauscht.
damals: klappt nicht
 void main(void){
          init_timer1();
          init_INT1();
          .
          .
          for(;;){
          }
}

jetzt: Klappt
 void main(void){
          init_INT1();
          init_timer1();

          .
          .
          for(;;){
          }
}

Meine Vermutung für den ersten Fall, dass es nicht funktioniert hat, 
weil ich den Timer für Senden benutze, der Timer lauft ab und die 
Interrupt ist noch nicht initialisiert.
auf jeden Fall hat jetzt geklappt, wenn jemand meine code braucht, kann 
ich es posten.
vielen Dank für eure mitdenken

von Christoph (Gast)


Lesenswert?

@lorenz:

Verstehe ich nicht ... der FIFO des Moduls hält doch max. 16 Bit. Wenn 
ich ihn auslese (ich verwende Bytes, nicht Worte) müßte FFIT doch wieder 
zurück auf HI gehen, oder? Oder meinst Du mit "alle Bytes" "alle Bits" 
oder "alle zwei Bytes"?
Was mir auch nur äußerst zögernd klar wurde ist, dass für das 
Funktionieren des Interrupts natürlich (?) das Rx-Teil des Moduls 
eingeschaltet sein muss. Viele Code-Beispiele für das RFM12-Modul, die 
Polling verwenden schalten das Rx-Teil unmittelbar vor dem Empfang ein 
und danach wieder aus.
Ist sehr verwirrend für mich und zeitintensiv, das Arbeiten mit den 
RFM12-Modulen ... wenn ich daran denke, wie simpel und rasch das 
Arbeiten mit XBEE-Modulen ging, frage ich mich ob sich der Aufwand 
überhaupt lohnt. :)

Christoph

von Michael U. (amiga)


Lesenswert?

Hallo,

@Christoph (Gast):
Was mir auch nur äußerst zögernd klar wurde ist, dass für das
Funktionieren des Interrupts natürlich (?) das Rx-Teil des Moduls
eingeschaltet sein muss. Viele Code-Beispiele für das RFM12-Modul, die
Polling verwenden schalten das Rx-Teil unmittelbar vor dem Empfang ein
und danach wieder aus.

Mal dumm gefragt: wie auch sonst?
Er muß ja schließlich empfangen können, um festzustellen, ob was für ihn 
dabei ist (Syncword).
Wenn der Empfänger ausgeschaltet ist, geht das schlecht. :-)

Viele Codebeispiele basieren aufeinander und sind durchaus nicht 
vollkommen und leider auch nicht immer fehlerfrei.
Die Datenblätter sind ...naja fragwürdig..., einiges merkt man dann 
wirklich erst im Einsatz.

Ganz praktisch sind die Dinger aber ihr Geld allemal wert, seit ich 
einige Ungereimtheiten verstanden habe, kaufen sie hier wie gewünscht 
incl. Empfang transparent komplett im IRQ, Sender mit Sleep usw. usw.

http://www.avr.roehres-home.de

http://roehre.homeip.net

Gruß aus Berlin
Michael

von Christoph K. (hyla)


Lesenswert?

@Michael:

Ich komm hier nicht weiter. Vielleicht hast Du noch einen Tipp...
Ich verwende URadigs USB-Funkmodul-Projekt 
(http://www.ulrichradig.de/home/index.php/avr/usb-funk) für den RFM12. 
Dabei stricke ich an seinem Code Beispiel herum, u.a. habe ich das für 
den CodeVision-Compiler umgearbeitet. Im "Polling-Modus" funktioniert 
das alles so weit. Meine Module funktionieren also, Anschlüsse im 
Source-Code stimmen etc.

Jetzt will ich den in URadigs Code verwendeten Polling Mode auf 
Interrupt
umstellen. Dazu habe ich eine eigene Interrupt-Routine geschrieben, die 
den Into-Interrupt verwendet.
Wenn jetzt etwas gesendet wird geht der (low-aktive) Anschluss NIRQ auf 
Low, der Interrupt wird angesprungen, der Pin bleibt aber low, sodass 
sich dann nichts mehr tut.
Interessanterweise passiert mir das selbe, wenn ich Deine 
RFM12.C-Routinen einbinde. Irgend eine Idee, was ich falsch machen 
könnte?

>> Viele Codebeispiele basieren aufeinander und sind durchaus nicht
>> vollkommen und leider auch nicht immer fehlerfrei.
>> Die Datenblätter sind ...naja fragwürdig..., einiges merkt man dann
>> wirklich erst im Einsatz.

Ohja. ;)


Grüße,
Christoph

von Michael U. (amiga)


Angehängte Dateien:

Lesenswert?

Hallo,

da ich ja immernoch an meinem Logicanalyzer den RFM12-Empfänger als 
Signalgeber dran habe, gibt es einen Screenshot.

nIRQ geht bei Fifo voll auf L (zeitgleich mit SDO = H, eigentlich 
logisch)
und geht wieder auf H bei der H/L-Flanke des Taktes, der das erste 
Datenbit aus dem Fifo holt eigentlich auch logisch).

Vermutung: irgendwas stimmt bei Deinem Empfangskommando nicht, so das 
der Fifo einfach nicht ausgelesen wird. Dann dürfte nIRQ bis in alle 
Ewigkeit auf L bleiben.

PS: eigentlich ja zu warm für Computer, aber mein Sensor sagt hier 3 
Grad weniger als auf dem Balkon.
Sollte mich wohl in den Keller oder ins Gefrierfach begeben...

http://roehre.homeip.net

Gruß aus Berlin
Michael

von Christoph K. (hyla)


Lesenswert?

Was ist das für ein Logikanalysator? :)

Ich bin immer noch nicht weiter. Zwischendurch ging mal gar nichts mehr. 
Tot, das Modul, der ATmega8 war zu nichts mehr zu bewegen. Mehr aus 
Verzweiflung habe ich mal einen externen Takt an XTAL1 gelegt und siehe 
da: Der Chip wurde wieder erkannt, ich hatte beim pausenlosen Umflashen 
;) aus Versehen auf "externen Oszillator" gefused.
Es bleibt dabei. Polling geht. Obwohl ich da auch ein komisches Phänomen 
sehe: ich sende den Zählerstand eines 8 Bit Counters, der Empfänger gibt 
das über USB/USART aus. Am Anfang werden brav meine Ziffern ausgegeben:

 98
 99
100
101
...

Nach einiger Zeit kommt zwischen diese Ziffern irgend ein Zeichen 
dazu:

z.B:

öö ö9ö8ö
öö ö9ö9ö
öö1ö0ö0ö
öö1ö0ö1ö
...

Wenn ich den Empfänger resette stimmt es für eine Weile wieder. ;)

Also, im Prinzip geht das. Aber kaum nehme ich den Interrupt mit hinein 
geht nichts mehr. Und NIRQ geht auf "lo" und bleibt da lieber mal ;)

Naja. Mit den Jahren ...

Grüße,
Christoph

von Michael U. (amiga)


Lesenswert?

Hallo,

sendest Du den Zählerstand als Byte oder schon als ASCII-Ziffern?
Sendest Du alles einzelnm also Sender aktiv, Sync-Bytes und Sync-Word 
schicken, Deinen Zählerstand Sneder wieder aus?

Die Module brauchen prinzipbedingt ausreichend Pegelwechsel, damit die 
Bitsyncronisation nicht aus dem Tritt kommt.
Wenn Du also z.B. binär 00, 01, 01, 03 usw. direkt hintereinander 
sendest, ist der Kram üner kurz oder lang aus dem Tritt.
Es gibt je für den Empfänger nur die Möglichkeit, den Buttakt aus den 
Daten zu gewinnen.
Deshalb am Anfang die 3x 0xAA, das ist eine gut geeignete 0-1 Folge, die 
einmal AFC und Vertärkung des Empfängers einregelt und andererseits die 
PLL für den Bittakt einrasten läßt.
Das Synword gibt dann den Hinweis, wo ein Byte anfängt. Die Bits sehen 
schließlich alle gleich aus...

Ab jetzt ist der Empfänger darauf angewiesen, mit den Flanken in den 
Datenbytes den Bittakt stabil zu halten. Sind es zuwenig Flanken kommt 
er aus dem Tritt.
Auch eine Störung kann nicht abgefangen werden, es gibt ja in den Daten 
keinen Hinweis mehr, wann ein Byte beginnt.

Also einzelne nicht zu lange Pakete und dann Sender aus.
Die Empfangsroutine muß natürlich wissen, wieviele Bytes erwartet 
werden, wenn die da sind, wird der Fifo aus- und wieder angemacht, damit 
der Empfänger wieder syncronisieren kann.

Gruß aus Berlin
Michael

von Christoph K. (hyla)


Lesenswert?

Michael U. schrieb:
> Hallo,
>
> sendest Du den Zählerstand als Byte oder schon als ASCII-Ziffern?

Als ASCII-Ziffern.

> Sendest Du alles einzelnm also Sender aktiv, Sync-Bytes und Sync-Word
> schicken, Deinen Zählerstand Sneder wieder aus?

Genau. Mords Overhead. :)
URadig hat sogar noch ein Byte für "Byte-Anzahl" und ein Checksum Byte.

>
> Die Module brauchen prinzipbedingt ausreichend Pegelwechsel, damit die
> Bitsyncronisation nicht aus dem Tritt kommt.
> Wenn Du also z.B. binär 00, 01, 01, 03 usw. direkt hintereinander
> sendest, ist der Kram üner kurz oder lang aus dem Tritt.

Wie gesagt. Sollte passen.

> Ab jetzt ist der Empfänger darauf angewiesen, mit den Flanken in den
> Datenbytes den Bittakt stabil zu halten. Sind es zuwenig Flanken kommt
> er aus dem Tritt.
> Auch eine Störung kann nicht abgefangen werden, es gibt ja in den Daten
> keinen Hinweis mehr, wann ein Byte beginnt.

Interessant.

> Die Empfangsroutine muß natürlich wissen, wieviele Bytes erwartet
> werden, wenn die da sind, wird der Fifo aus- und wieder angemacht, damit
> der Empfänger wieder syncronisieren kann.

Ich würde (später, wenn alles mal funktioniert) mit dem <CR> arbeiten. 
Also einfach solange Zeichen in den Buffer laden, bis ein Return kommt.


Nochmal zu meinem Interrupt-Problem. Es ist echt myteriös.
Ich initialisiere das Modul in üblicher Weise ;)
Am Schluss meiner INIT-Routine habe ich:

   MCUCR |= ISC01;             // INT0 fallende Flanke für RFM12 nIRQ
//    GICR = INT0;
   rf12_trans(0x82C8);     // RX on

Meine Interrupt-Routine ist "Short & Sweet":

interrupt[EXT_INT0] void ext_int0_isr(void)
{
    rf12_rx_ready = TRUE;
}

Ich setze einfach ein Flag, wenn der Interrupt ausgelöst wurde.
Im Moment läuft Polling zur Abfrage der gesendeten Daten.
Am Pin NIRQ sehe ich negative Spikes in Vierer-Gruppen, die meinen 
gesendeten Bytes entsprechen.

Kompiliere ich das so wie oben funktioniert alles.
Nehme ich die Kommentierung vor der GICR-Zeile weg (enable also den 
INT0) funktioniert das Polling zwar immer noch, aber die Spikes an NIRQ 
sind nicht mehr da, der Interrupt wird ganz zu Beginn einmal ausgelöst 
und dann nie mehr.
Wenn ich die MCUCR-Zeile wegkommentiere und das kompiliere (d.h. ja: 
Low-level des INT0-Pins generiert einen Interrupt) kriege ich viele viel 
Interrupts und sonst nichts (klar: NIRQ ist und bleibt auf LOW und löst 
damit immer wieder Interrupts aus). Auch nicht brauchbar.

Idee? Ich nicht mehr.

Grüße,
Christoph

von Michael U. (amiga)


Lesenswert?

Hallo,

   MCUCR |= ISC01;             // INT0 fallende Flanke für RFM12 nIRQ
//    GICR = INT0;
   rf12_trans(0x82C8);     // RX on

Das stimmt aber so nicht.

MCUCR |= (1<<ISC01)
und
GICR = (1<<INT0)
wäre richtig, das sind Bitnummern...

Wobei GCIR |= (1<<INT0) sicherer wäre, um nicht andere Bits in GCIR 
ungwollt auf 0 zu setzen.

Außerdem würde ich vor Freigabe immer mit
GIFR |= (1<<INT0)
einen evtl. anstehende INT0-IRQ löschen.

Gruß aus Berlin

von Christoph K. (hyla)


Lesenswert?

Hi,

ich hab meinen Fehler gefunden (wenn auch noch nicht behoben :) ).
Michael, Dein Tipp ...

>> irgendwas stimmt bei Deinem Empfangskommando nicht

... war gut. Es ist aber nicht das Kommando selbst (es funktioniert ja 
klaglos, wenn ich das mit Polling einsetze). Das Problem ist, um einen 
Interrupt per NIRQ-Spike zu generieren muss das Modul - natürlich - 
entsprechend konfiguriert sein. Ein Teil der Konfiguration erfolgt in 
der Lese-Routine selbst. Um einen Interrupt zu bekommen, muss ich die 
Lese-Routine gestartet haben, das passiert aber nicht, weil eben der 
Interrupt nicht auslöst.

Okay. An diesem Code weiter zu machen hat wenig Sinn. Das ist so ein 
häßliches Sammelsurium, ich fange eher noch mal von vorne an. :)

>>    MCUCR |= ISC01;             // INT0 fallende Flanke für RFM12 nIRQ
>> //    GICR = INT0;
>>    rf12_trans(0x82C8);     // RX on

> Das stimmt aber so nicht.

Doch. Das ist eins meiner Probleme mit den zahlreichen Code-Beispielen 
(die es ja unbestreitbar gibt). Ich mag die "Bitschubsereien" im Code 
nicht, also so etwas wie GCIR |= (1<<INT0). Ich habe statt dessen ein 
Definitionsfile für jeden Chip, in dem den Funktions-Bits (also z.B. 
ISC01) nicht die Nummer des Bits (z.b. 1) zugeordnet wird, sondern der 
Wert (also hier 2). Ich kann deshalb die Funktionsbits einfach 
verodern, ohne die Schiebebefehle. Ich darf das nur nicht durcheinander 
bringen ;)

Eine saftige Fehlerquelle mehr für mich :)

Grüße,
Christoph

von Michael U. (amiga)


Lesenswert?

Hallo,

Christoph Klein schrieb:
> ich hab meinen Fehler gefunden (wenn auch noch nicht behoben :) ).
> Michael, Dein Tipp ...
>
>>> irgendwas stimmt bei Deinem Empfangskommando nicht
>
> ... war gut. Es ist aber nicht das Kommando selbst (es funktioniert ja
> klaglos, wenn ich das mit Polling einsetze). Das Problem ist, um einen
> Interrupt per NIRQ-Spike zu generieren muss das Modul - natürlich -
> entsprechend konfiguriert sein. Ein Teil der Konfiguration erfolgt in
> der Lese-Routine selbst. Um einen Interrupt zu bekommen, muss ich die
> Lese-Routine gestartet haben, das passiert aber nicht, weil eben der
> Interrupt nicht auslöst.

Kenne ich auch nur zu gut sowas...

Ich habe da kein Problem mit dem Bitgeschiebe, das geht schon 
automatisch bei mir. Daß die Zeilen da etwas länger sind, ist mir auch 
egal.

> Eine saftige Fehlerquelle mehr für mich :)

Genau wegen solcher Nebeneffekte laß ich es lieber.
Da ich ja sowieso viele Routinen recycle wäre es wohl nervend, wenn ich 
dann jedesmal an 2 Stellen aufpassen müßte.
Wenn dann eine anderer AVR rein soll, dann werden eben die Errors 
angeklickt und vor Ort korrigiert. Trotz aller Ungereimtheiten hat man 
bei Atmal eigentlich schnell raus, wo da noch eine 0 oder 1 in einen 
Registernamen reingekommen ist.

Gruß aus Berlin
Michael

von Tweaker (Gast)


Lesenswert?

Kann jemand noch einem kurz zusammenfassen, was ich für den 
Interrupt-Betrieb machen muss?

Bei mir löst bei einem mal aus, nach dem nächsten Flash nicht mehr....

THX

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.