Forum: Mikrocontroller und Digitale Elektronik RFM12b (keine Übertragung)


von Mateusz R. (mateusz224)


Angehängte Dateien:

Lesenswert?

Moin zusammen,
Also vorab das ist mein erster Beitrag hier und auch erst meine zweite 
Erfahrung mit einem uC. Für eine Uni-arbeit muss u.a. auch ein uC 
programmiert werden. Dabei soll von einem uC zu einem Raspberryn Pi die 
Daten übertragen werden. Zunächst versuch ich jetzt nun seit über 10 
Tagen tag täglich 8-10 Stunden eine Funkbrücke (mit einem RFM12b) vom 
PIC zum PIC zu realisieren, jedoch vergebens und bin schon verzweifelt. 
Ich habe so ziemlich alle Forenbeiträge gelesen und finde trotzdem den 
Fehler nicht.
Dabei benutz ich den CCS Compiler und die Hardware SPI.
Ich wäre unheimlich dankbar wenn mir jemand da weiter helfen könnte....

Zusatz Info:
868Mhz Modul

Was überprüft worden ist:
- Statuswort bei: power on reset 0x4000 | wird erhalten
- nIRQ wird ausgelöst beim Sender (Siehe Abbildungen)

Abbildung NewFile1:
Blau: nIRQ
Gelb: MISO

Abbildung NewFile2:
Blau: nIRQ
Gelb: nSEL

PS: Die Abbildungen NewFile0.bmp bitte ignorieren. Weiß leider nicht wie 
ich die wieder löschen kann.

1
#define nIRQ PIN_B1
2
#define nSEL PIN_B0
3
4
void rfm12_send_cmd(int16 cmd)
5
{
6
  #byte lobyte = cmd
7
  #byte hibyte = cmd + 1
8
9
  spi_write(hibyte);
10
  spi_write(lobyte);
11
}  
12
13
int16 rfm_get_status()
14
{
15
  int16 status;
16
  
17
  status = spi_read(0x00);
18
  status<<=8;
19
  status + spi_read(0x00);
20
21
  return status;
22
}
23
char rfm_read_cmd()
24
{
25
    char read;
26
    spi_read(0xB0);
27
    read=spi_read(0x00);
28
    return read;
29
}
30
  
31
void rfm12_init()
32
{
33
  output_high(nSEL);
34
  delay_ms(200);
35
  
36
  output_low(nSEL);
37
  
38
  int16 status;
39
  status = rfm_get_status();
40
  //
41
42
    rfm12_send_cmd(0x8067);   // Je nachdem ob Sender oder Empfänger
43
    //rfm12_send_cmd(0x80A7);  // Je nachdem ob Sender oder Empfänger
44
    rfm12_send_cmd(0x8208);
45
    rfm12_send_cmd(0xA680);
46
    rfm12_send_cmd(0xC647);
47
    rfm12_send_cmd(0x94A0);
48
    rfm12_send_cmd(0xC2AB);
49
    rfm12_send_cmd(0xCA81);
50
    //rfm12_send_cmd(0xCAF3);
51
    rfm12_send_cmd(0xCED4);
52
    rfm12_send_cmd(0xC4F7);
53
    rfm12_send_cmd(0x9850);
54
    rfm12_send_cmd(0xCC77);
55
    rfm12_send_cmd(0xE000);
56
    rfm12_send_cmd(0xC800);
57
    rfm12_send_cmd(0xC040); 
58
59
  output_high(nSEL);
60
}  
61
62
void rfm12_write(char data)
63
{
64
  output_low(nSEL);
65
66
    
67
  rfm_get_status();
68
  rfm12_send_cmd(0x8238);
69
  rfm12_send_cmd(0xB8AA);
70
  rfm12_send_cmd(0xB8AA);
71
  rfm12_send_cmd(0xB8AA);
72
  rfm12_send_cmd(0xB82D);
73
  rfm12_send_cmd(0xB8D4);
74
  rfm12_send_cmd(0xB845);
75
        rfm12_send_cmd(0xB8AA);
76
        rfm12_send_cmd(0xB8AA);
77
        rfm12_send_cmd(0xB8AA);
78
 
79
  rfm12_send_cmd(0x8208);
80
    
81
    
82
83
  output_high(nSEL);
84
    //printf("Status1: 0x%lX\r\n", status);
85
}  
86
87
void rfm12_read()
88
{
89
        char read;
90
        int16 status;
91
        output_low(nSEL);
92
  rfm_get_status();
93
  rfm12_send_cmd(0x82C8);
94
  rfm12_send_cmd(0xCA81);
95
  rfm12_send_cmd(0xCA83);
96
  read=rfm_read_cmd();
97
  //rfm12_send_cmd(0xCA83);
98
  rfm12_send_cmd(0x8208);
99
 
100
  output_high(nSEL);   
101
    
102
    printf("read: %u\r\n", read);
103
}

: Bearbeitet durch User
von Michael U. (amiga)


Lesenswert?

Hallo,

C ist nicht so meine Spielwiese und PIC sowieso nicht, aber:

void rfm12_send_cmd(int16 cmd)
{
  #byte lobyte = cmd
  #byte hibyte = cmd + 1

  spi_write(hibyte);
  spi_write(lobyte);

Ich kenne den Compiler nicht, was macht #byte?

Sollte das nicht eher nur

  spi_write(cmd & 0xFF);
  spi_write((cmd >> 8) & 0xFF);

heißen?

Vermutlich muß auch noch ein cast auf byte oder char rein oder was 
spi_write() da erwartet.

Gruß aus Berlin
Michael

: Bearbeitet durch User
von Mateusz R. (mateusz224)


Lesenswert?

Hej,
ja so könnte man das auch machen, ich hatte das jetzt so übernommen und 
es scheint auch zu funktionieren da ich die Register setzen kann. Also 
kann mir den Status des RFM12b auslesen lassen oder den RFM12b so 
konigurieren, dass er mir sein Clk ausgibt am PIN CLK. Von daher glaub 
ich weniger, dass es was mit der SPI Kommuniktion zu tun hat, sondern 
eher mit dem Fifo oder allgemein mit der richtigen Konfiguration des 
RFM12b (vielleicht auch timing probleme).... Ich habe nur die INFO: "PIC 
und C" mit rein genommen der vollständigkeit halber... aber glaube, dass 
das Problem bei der Konfiguration der (über SPI) zu sendenden Daten 
liegt.

: Bearbeitet durch User
von Michael U. (amiga)


Lesenswert?

Hallo,

ok, dann geht Deine Version an dieser Stelle.
Ich habe einen RFM12 (den alten) hier noch als Empfänger laufen, 
allerdings an einem AVR.
1
void rfm12_init()
2
{
3
4
  RFM12_PORT |= (1<<RFM12_IRQ) | (1<<RFM12_CS) | (1<<RFM12_SDO);    // PullUp ein / Ausgang H
5
  RFM12_DDR  |= (1<<RFM12_CS) | (1<<RFM12_SDI) | (1<<RFM12_SCK);    // Ausgänge
6
  RFM12_DDR  &= ~((1<<RFM12_IRQ) | (1<<RFM12_SDO));                 // Eingang
7
8
  MCUCR |= (1<<ISC01);                          // INT0 fallende Flanke für RFM12 nIRQ
9
  GICR |= (1<<INT0);
10
11
  rfm12_send_cmd(0x0000);  // Status read
12
13
  rfm12_send_cmd(0xC080);  // CLK-Frequenz / Batterie-Level
14
  rfm12_send_cmd(0x80D7);  // FIFO ein, 433MHZ-Band, C = 12pF
15
  rfm12_send_cmd(0xC2AB);  // Clock Recovery Auto, Filter digital, DQD-Thresold 3
16
  rfm12_send_cmd(0xCA81);  // FIFO-Level 8 Bit, Sync Pattern ein, High senity Reset aus
17
  rfm12_send_cmd(0xE000);  // WakeUp aus
18
  rfm12_send_cmd(0xC800);  // Low Duty Cycle aus
19
  rfm12_send_cmd(0xC4F3);  // AFC immer, +7,5 / -10kHz, Add Freq-Offset zur PLL, Berechne Freq. Offset aus AFC                      // Status read
20
  rfm12_send_cmd(0xA620);  // Frequenz 433,92MHz  // Status read
21
22
  rfm12_send_cmd(0x948C);  // VDI Output, VDI Fast, Bandbreite 200kHz, LBA-Gain -6dB, RSSI-Thresold -79dB
23
24
  rfm12_send_cmd(0xC610);  // Baudrate 19200
25
  rfm12_send_cmd(0x8281);  // Empfänger ein, Clock Out aus
26
  rfm12_send_cmd(0xCA81);  // set FIFO mode
27
  rfm12_send_cmd(0xCA83);  // enable FIFO
28
}

Ist ein 433MHz RFM12 und die Baudrate stimmt auch nicht, die ist 21000 
oder so.

Vielleicht hilft Dir die Initialisierung etwas weiter.

Gruß aus Berlin
Michael

: Bearbeitet durch User
von Mateusz R. (mateusz224)


Lesenswert?

könntest du vielleicht dein ganzen Code posten? Also ich habe mir schon 
zahlreiche Programme angeschaut und die sehen eigentlich identisch aus 
(außer, dass diese oft eine softawre spi haben) was mich ja extrem 
wundert...

Also den Sender/Empfänger Code, sowie wie du die Daten sendest und 
empfängst.

Beste Grüße aus Bremen

von Michael U. (amiga)


Lesenswert?

Hallo,

Kann ich machen, hat aber ein Problem:
der Kram ist von 2009/2010 und heute noch in Betrieb.
http://www.avr.roehres-home.de/sensoren/index.html

Ursprünglich alls AVR-ASM, C dann als Übung für mich. Außerdem sende ich 
mit den alten RFM02, mit dem RFM12 habe ich nie gesendet...

Ich hänge die C-Sachen trotzdem mal hier ran, auf meiner Homepage sind 
nur die ASM-Projekte.
Vielleicht hilft es ja.

Ich könnte natürlich mal einen Sender mit RFM12 zusammenstecken und in C 
was senden, einen spielenden USB-Empfänger habe ich ja da.

Gruß aus Berlin
Michael

von Mateusz R. (mateusz224)


Lesenswert?

Super schau ich mir gleich mal genauer an. Wie gesagt ich sitz da schon 
ca. 100 Stunden dran und weiß nicht mehr weiter, weiß ja nicht mal ob 
der Sender was Sendet oder das am Empfänger liegt. Und habe keine Ahnung 
wie ich das rausbekommen kann...

von Stefan (Gast)


Lesenswert?

Hast du einen DVB-T Empfänger für deinen PC ?
Dann kannst du es testen, ob er sendet.
Habe ich auch so gemacht.

von Mateusz R. (mateusz224)


Lesenswert?

Nop, weiß ehrlich gesagt nicht mal was das ist^^ Würde mir einen aber 
zulegen, wenn ich dadurch die Info erhalte. Also was ich weiß ist, dass 
der Sender angeschaltet ist und das die Trägerfräquenz an ist (Sendet). 
Aber ob auf dieser sich die Daten befinden die ich versuche zu Senden 
weiß ich nicht.

von Mateusz R. (mateusz224)


Angehängte Dateien:

Lesenswert?

Also was mich extrem wundert ist eigentlich die Abbildung. Gelb ist 
dabei der nSEL und Blau der nIRQ.
Was man erkennen kann ist der Aufruf der rfm12_write() funktion. Dabei 
wird mit der fallenden nSEL Flanke die Daten übertragen. Ich habe jetzt 
einmal 1ms dalay in der Funktion eingebaut (Abbildung NewFile4) um zu 
sehen was  dabei passieren wird. (Abbildung NewFile3 ist ohne delay).
Denn was mich verwirrt ist dass nIRQ bei einem high Pegel bedeutet, dass 
dieser sendebereit (bzw. das Fifo bereit ist diesen mit Daten zu 
füllen). Das bedeutet dass erst wenn die rfm12_write() Methode 
aufgerufen wird ist dieser soweit (wahrscheinlich durch setzen der -> 
0x8238). Hatte jedoch auch ebenfalls das so verstanden gehabt dass beim 
Senden das Fifo gefüllt wird und ebenfalls nIRQ dann auf low fallen 
würde, da das Fifo voll ist. Jedoch passiert da nichts.

Ist das der Fehler?
1
void rfm12_write(char data)
2
{
3
  output_low(nSEL);
4
  rfm_get_status();
5
  rfm12_send_cmd(0x8238);
6
    delay_ms(1);  //mit und ohne in der Abbildung
7
  rfm12_send_cmd(0xB8AA);
8
  rfm12_send_cmd(0xB8AA);
9
  rfm12_send_cmd(0xB8AA);
10
  rfm12_send_cmd(0xB82D);
11
  rfm12_send_cmd(0xB8D4);
12
  rfm12_send_cmd(0xB845);
13
        rfm12_send_cmd(0xB8AA);
14
        rfm12_send_cmd(0xB8AA);
15
        rfm12_send_cmd(0xB8AA);    
16
  rfm12_send_cmd(0x8208);
17
  output_high(nSEL);
18
}

von Felix P. (fixxl)


Lesenswert?

Bist du sicher, dass es funktioniert, wenn man den Chip Select auf low 
zieht und dann eine Serie von Befehlen schickt? Ich kenne es so, dass 
vor und nach jedem Befehl CS auf low bzw. high gezogen werden muss.

von Mateusz R. (mateusz224)


Lesenswert?

Jein, also wie gesagt den RFM12b kann ich so konfigurieren. Also es 
scheint so zu funktionieren ich hatte trotzdem es versucht bei jedem 
befehl den chip select auf low zu ziehen... also:
1
void rfm12_write(char data)
2
{   output_high(nSEL);
3
  output_low(nSEL);
4
  rfm_get_status();
5
  rfm12_send_cmd(0x8238);
6
    output_high(nSEL);
7
  output_low(nSEL);
8
9
    rfm_get_status();
10
    output_high(nSEL);
11
  output_low(nSEL);
12
  rfm12_send_cmd(0xB8AA);
13
    output_high(nSEL);
14
  output_low(nSEL);
15
  rfm12_send_cmd(0xB8AA);
16
    output_high(nSEL);
17
  output_low(nSEL);
18
  rfm12_send_cmd(0xB8AA);
19
    output_high(nSEL);
20
  output_low(nSEL);
21
  rfm12_send_cmd(0xB82D);
22
    output_high(nSEL);
23
  output_low(nSEL);
24
  rfm12_send_cmd(0xB8D4);
25
    output_high(nSEL);
26
  output_low(nSEL);
27
  rfm12_send_cmd(0xB845);
28
   output_high(nSEL);
29
  output_low(nSEL);
30
    rfm12_send_cmd(0xB8AA);
31
   output_high(nSEL);
32
  output_low(nSEL);
33
    rfm12_send_cmd(0xB8AA);
34
   output_high(nSEL);
35
  output_low(nSEL);
36
    rfm12_send_cmd(0xB8AA);
37
   output_high(nSEL);
38
  output_low(nSEL);
39
40
  rfm12_send_cmd(0x8208);
41
        output_high(nSEL);
42
}

Da ich nicht sicher war wegen dem entprellen hatte ich auch das versucht 
mit 1ms delay dazwischen... hat alles nicht geklappt. Mit 1ms delay war 
dann auch der nIRQ auf dauer high... keine Ahnung wieso.

Ich seh gerade (da ich zuvor das mit dem 434MHz modul probiert hatte) 
dass ocj eine 433MHz Antene immer noch rangelötet ist aber das dürft 
eigentlich nicht das Problem sein wenn die beiden Module nebeneinander 
liegen.

von Chris L. (kingkernel)


Lesenswert?

Wie sieht denn dein Aufbau aus? Ich hatte mit den RFM12b-868 Modulen 
massive Probleme mit falschen Kondensatoren in der Spannungsversorgung. 
Alles lief, bis auf das senden. Dann klappte das Senden irgendwann aber 
ich hatte ständig fehler. Ein paar minuten später ging wieder nichts 
mehr

von Mateusz R. (mateusz224)


Angehängte Dateien:

Lesenswert?

Hej,
also ich habe ebend gerade irgendwelche Daten empfangen ohne dass der 
Sender an war... eine gewisse Zeit (1min) zumindest und dann wieder nur 
0  ganz komisches Verhalten... kann das Verhalten auch nicht mehr 
reproduzieren...

Also der Schaltplan sieht so aus, wie bei den meisten die ich im 
Internet gesehn...

: Bearbeitet durch User
von Felix P. (fixxl)


Lesenswert?

Bin gerade noch einmal das Datenblatt durchgegangen, das Timing-Diagramm 
auf Seite 13 ist relativ eindeutig: Vor jedem SPI-Befehl muss der 
Chip-Select auf low gezogen, dann die 16 Bit übertragen und anschließend 
der Chip-Select wieder high gesetzt werden.

Bevor du deinen Code jetzt mit output_low und output_high flutest, würde 
ich einfach die Funktion rfm12_send_cmd entsprechend anpassen. Hast du 
mit dem Oszi mal SDI und SCK angeschaut, um zu vergleichen, ob deine 
Kommandos richtig rausgeschickt werden? Ich bin kein CCS-Experte, von 
daher kann ich nicht sagen, ob diese Konstruktion mit #byte so 
funktioniert.

Was mir auch seltsam vorkommt:
1
int16 rfm_get_status() {
2
  int16 status;
3
  status = spi_read(0x00);
4
  status<<=8;
5
  status + spi_read(0x00);
6
  return status;
7
}
Was passiert in der Zeile vor dem return? Muss das kein += sein?

von andy (Gast)


Angehängte Dateien:

Lesenswert?

Hier mal mein alter Source. Hat damals sehr gut funktioniert.

von Chris L. (kingkernel)


Lesenswert?

Die 100nF am RFM12b reichen nicht! Da muss zwingend zusätzlich noch ein 
10µF-Elko dazu!

von Mateusz R. (mateusz224)


Angehängte Dateien:

Lesenswert?

So habe das jetzt mit nSEL angepasst bekomme jedoch wie schon vorher 
angesprochen jetzt kein Interupt auf nIRQ (ständig auf high).

Stimmt, da fehlte ein += ist auch korrigiert.

Habe noch einen 10uF Kondensator angelötet.


Alles bewirkte keine Änderung... Ja die Daten werden korrekt über die 
SPI übertragen, im Anhang nSEL und und das CLK Signal...

Kann das an der Hardware SPI liegen dass diese zu schnell ist und das 
RFM12b nicht hinterherkommt? eine CLK Periode dauert wie man in der 
Abbildung erkennen kann 500ns.

: Bearbeitet durch User
von Frank G. (frank_g53)


Lesenswert?

Stefan schrieb:
> Hast du einen DVB-T Empfänger für deinen PC ?
> Dann kannst du es testen, ob er sendet.

Mateusz R. schrieb:
> Würde mir einen aber
> zulegen, wenn ich dadurch die Info erhalte.

http://www.stall.biz/project/868mhz-funksignal-ansehen-mit-dvb-t-stick

Stichworte: RTL2832 und SDR

von Stefan (Gast)


Lesenswert?

Spendier der SEL Leitung noch einen
Widerstand zum Pluspol.

von Stefan (Gast)


Angehängte Dateien:

Lesenswert?

So ist eigentlich die Grundbeschaltung.

von Michael U. (amiga)


Lesenswert?

Hallo,

Das wären dann 2MHz, SPI-Geschwindigkeit ist ok, das Datenblatt sagt 
Clock Low, Clock High jeweils Minimum 25ns, also theoretisch 50ns für 
die Periode.

Einschränkung ist beim Zugriff auf den FIFO, da sind nur maximal 1/4 vom 
Clock, also 10MHz/4 = 2,5MHz zulässig.

Richtig ist die Anmerkung irgendwo oben: nSEL geht vor Beginn einer 
Kommandosequenz auf Low und am Ende wieder auf High.

Das sagen auch alle Timingdiagramme im Datenblatt.
Vielleicht schaffe ich es morgen mal, einen RFM12 als Sender anzuwerfen.

Gruß aus Berlin
Michael.

von Mateusz R. (mateusz224)


Lesenswert?

Jop stimmt das mit dem pull up Widerstand habe ich tatsächlich 
vergessen^^
Ist jetzt auch korrigiert... -> keine Änderung.

ich poste nochmal den aktuellen Code mit den vorgenommenen Änderungen:
1
#define nIRQ PIN_B1
2
#define nSEL PIN_B0
3
//#define  RFM12B_STATUS       RFM12B_spi(0x0000)
4
//#define  RFM12B_RGIT()       (RFM12B_STATUS & 0x8000)
5
//#define  RFM12B_WAIT_RGIT()  while(!RFM12B_RGIT()) {  }
6
7
void rfm12_send_cmd(int16 cmd)
8
{
9
  output_low(nSEL);
10
  #byte lobyte = cmd
11
  #byte hibyte = cmd + 1
12
13
  spi_write(hibyte);
14
  spi_write(lobyte);
15
    output_high(nSEL);
16
}
17
18
int16 rfm_get_status()
19
{
20
    output_low(nSEL);
21
  int16 status;
22
  
23
  status = spi_read(0x00);
24
  status<<=8;
25
  status += spi_read(0x00);
26
    output_high(nSEL);
27
28
  return status;
29
}
30
char rfm_read_cmd()
31
{
32
    output_low(nSEL);
33
    char read;
34
    spi_read(0xB0);
35
    read=spi_read(0x00);
36
    output_high(nSEL);
37
    return read;
38
}
39
  
40
void rfm12_init()
41
{
42
  output_high(nSEL);
43
  delay_ms(200);
44
  
45
  output_low(nSEL);
46
  
47
  int16 status;
48
  status = rfm_get_status();
49
50
    //rfm12_send_cmd(0x8067);
51
    rfm12_send_cmd(0x80A7);
52
53
    rfm12_send_cmd(0x8208);
54
55
    rfm12_send_cmd(0xA680);
56
    rfm12_send_cmd(0xC647);
57
    rfm12_send_cmd(0x94A0);
58
    rfm12_send_cmd(0xC2AB);
59
    rfm12_send_cmd(0xCA81);
60
    //rfm12_send_cmd(0xCAF3);
61
    rfm12_send_cmd(0xCED4);
62
    rfm12_send_cmd(0xC4F7);
63
    rfm12_send_cmd(0x9850);
64
    rfm12_send_cmd(0xCC77);
65
    rfm12_send_cmd(0xE000);
66
    rfm12_send_cmd(0xC800);
67
    rfm12_send_cmd(0xC040); 
68
    //rfm12_send_cmd(0x8057);
69
    
70
71
    //status = rfm_get_status();
72
   // printf("Status: 0x%lX\r\n", status);
73
}  
74
75
void rfm12_write(char data)
76
{   
77
  output_low(nSEL);
78
    
79
    
80
  rfm_get_status();
81
82
  rfm12_send_cmd(0x8238);
83
  rfm12_send_cmd(0xB8AA);
84
  rfm12_send_cmd(0xB8AA);
85
  rfm12_send_cmd(0xB8AA);
86
  rfm12_send_cmd(0xB82D);
87
  rfm12_send_cmd(0xB8D4);
88
  rfm12_send_cmd(0xB845);
89
    rfm12_send_cmd(0xB8AA);
90
    rfm12_send_cmd(0xB8AA);
91
    rfm12_send_cmd(0xB8AA);
92
  rfm12_send_cmd(0x8208);
93
  output_high(nSEL);
94
    //printf("Status1: 0x%lX\r\n", status);
95
}  
96
97
void rfm12_read()
98
{
99
    char read1, read2;
100
    int16 status;
101
    
102
    
103
  rfm_get_status();
104
  rfm12_send_cmd(0x82C8);
105
  rfm12_send_cmd(0xCA81);
106
  rfm12_send_cmd(0xCA83);
107
    delay_ms(4);
108
  read1=rfm_read_cmd();
109
  rfm12_send_cmd(0x8208);
110
    
111
    printf("read1: %u\r\n", read1);
112
    //printf("Status: 0x%1X\r\n", status);
113
}

Bzgl.:
  #byte lobyte = cmd
  #byte hibyte = cmd + 1
ist richtig, habe mich nochmal informiert, das ist wirklich ein CCS 
spezifischer optimierter Befehl, der mit einem Assembler Befehl (das 
nächste Register) defeniert. (int16) cmd zu schiften kostet mehrere 
Assembler Befehle.

von Felix P. (fixxl)


Lesenswert?

Bei deiner Registerkonfiguration in der Init ist mir noch aufgefallen:
1
rfm12_send_cmd(0x80A7);
Damit hast du den FIFO-Modus nicht aktiviert, das Bit ef (Bit 6) ist 
nicht gesetzt und Daten- und Datentaktausgabe würden über die Pins 6 und 
7 ausgegeben. Für FIFO-Betrieb müsste der Befehl 0x80E7 lauten.

Das meiner Meinung nach größte Problem, das mir dummerweise erst jetzt 
aufgefallen ist, besteht aber wohl darin, dass du die Daten einfach 
unmittelbar nacheinander ins Datenregister schreibst, ohne darauf zu 
warten, dass sie verschickt werden und Platz für neue Daten ist. Beim 
RFM69CW, dem Nachfolger des RFM12b, würde das funktionieren, da der 
Puffer entsprechend groß ist, beim RFM12b passen da aber nur zwei Byte 
gleichzeitig hinein.

Vor jedem neuen Byte, welches ins Senderegister geschrieben wird, muss 
überprüft werden, ob das Senderegister aufnahmefähig ist (MSB des 
Statusregisters auf 1) oder nicht (MSB des Statusregisters auf 0). Deine 
write-Funktion sollte am Ende also ungefähr so aussehen:
1
void rfm12_write(char data) {   
2
   
3
  rfm_get_status();
4
5
  rfm12_send_cmd(0x8238);
6
  
7
  while(!(rfm_get_status() & (1<<15)));
8
  rfm12_send_cmd(0xB8AA);
9
  
10
  while(!(rfm_get_status() & (1<<15)));
11
  rfm12_send_cmd(0xB8AA);
12
13
  while(!(rfm_get_status() & (1<<15)));
14
  rfm12_send_cmd(0xB8AA);
15
16
  while(!(rfm_get_status() & (1<<15)));
17
  rfm12_send_cmd(0xB82D);
18
19
  while(!(rfm_get_status() & (1<<15)));
20
  rfm12_send_cmd(0xB8D4);
21
22
  while(!(rfm_get_status() & (1<<15)));
23
  rfm12_send_cmd(0xB845);
24
25
  while(!(rfm_get_status() & (1<<15)));
26
  rfm12_send_cmd(0xB8AA);
27
28
  while(!(rfm_get_status() & (1<<15))); 
29
  rfm12_send_cmd(0xB8AA);
30
31
  while(!(rfm_get_status() & (1<<15)));
32
  rfm12_send_cmd(0xB8AA);
33
34
  rfm12_send_cmd(0x8208);
35
}

Selbstverständlich kannst du aber, um das nicht immer ausschreiben zu 
müssen, auch eine Funktion schreiben, die das Warten und den 
Schreibzugriff zusammenfasst.

Ganz alternativ würde natürlich auch die Auswertung des Interrupts 
funktionieren.

: Bearbeitet durch User
von Mateusz R. (mateusz224)


Lesenswert?

Hmm also ich habe den nicht gesetzt, da das der Empfangs Fifo ist und 
das der Sender gewesen ist. Das Empfangs FiFo habe ich auf dem anderen 
Modul aktiviert (ist in dem geposteten Code kommentiert: 
rfm12_send_cmd(0x8067);)

bzgl.:
while(!(rfm_get_status() & (1<<15)));

sowas ähnliches hatte ich auch vorher (while(!(rfm_get_status() & 
0x8000));) jedoch MOSI bleibt dann auf dauer LOW und MISO verhält sich 
ebenfalls merkwürdig also geht auf high wenn nSEL low geht.

Ich geh davon aus, dass das Senderegister nie aufnahmefähig ist bzw. das 
FFIT Bit nie zurück gesetzt wird und dass das Programm deswegen in einer 
dauerschleife hängenbleibt und deswegen ist:

MISO: High bei nSEL
MOSI: (durch versenden von 0x0000) Low
nIRQ: dauer High

: Bearbeitet durch User
von Felix P. (fixxl)


Lesenswert?

Mateusz R. schrieb:
> Hmm also ich habe den nicht gesetzt, da das der Empfangs Fifo ist und
> das der Sender gewesen ist. Das Empfangs FiFo habe ich auf dem anderen
> Modul aktiviert (ist in dem geposteten Code kommentiert:
> rfm12_send_cmd(0x8067);)
Ah, okay. Schaden tut es trotzdem nicht, wenn man beides aktiviert.

> bzgl.:
> while(!(rfm_get_status() & (1<<15)));
>
> sowas ähnliches hatte ich auch vorher (while(!(rfm_get_status() &
> 0x8000));) jedoch MOSI bleibt dann auf dauer LOW und MISO verhält sich
> ebenfalls merkwürdig also geht auf high wenn nSEL low geht.
>
> Ich geh davon aus, dass das Senderegister nie aufnahmefähig ist bzw. das
> FFIT Bit nie zurück gesetzt wird und dass das Programm deswegen in einer
> dauerschleife hängenbleibt und deswegen ist:
>
> MISO: high bei nSEL
> MOSI: (durch versenden von 0x0000) Low
Was MOSI tut, entscheidest du selbst: MOSI ist ein Ausgang deines 
Mikrocontrollers. Wenn MOSI dauerhaft auf low ist, obwohl du Daten 
sendest, ist das ein Problem der Software oder Hardware.

Dass MISO auf high geht, wenn du NSEL low ziehst (und gleichzeitig auch 
MOSI auf low ist), ist absolut in Ordnung. Dann gibt der Pegel nämlich 
den Zustand des MSB des Statusregisters wieder, im Sendemodus also RGIT. 
Und RGIT = 1 bedeutet, dass du den Wert xx per Befehl 0xB8xx ins 
Senderegister schreiben darfst. Wenn RGIT auf 1 ist, muss gleichzeitig 
auch nIRQ auf low sein und wird erst high, wenn du etwas ins 
Senderegister schreibst.

von Michael U. (amiga)


Lesenswert?

Hallo,

ich weiß nicht, ob ich es heute noch schaffe, den RFM12 mal anzuwerfen.

Zur Abfrage des FIFO: SDO spiegelt immer den Zustand des FIFO-Status 
sobald nSEL auf L geht. Man muß beim Senden/Empfangen also nicht den 
Status lesen, man kann sofort den Zustand von SDO abfragen.
1
void RFM12_read_fifo(char *data_buf, char len)
2
  {
3
4
    unsigned char byte = 0, i, j;
5
6
    RFM12_send_cmd(0x82C8);            // Empfänger ein
7
8
    RFM12_send_cmd(0xCA81);            // set FIFO mode
9
10
    RFM12_send_cmd(0xCA83);            // enable FIFO
11
12
      RFM12_PORT &= ~(1<<RFM12_SCK);        // CLK auf L
13
      RFM12_PORT &= ~(1<<RFM12_SDI);        // DATA auf L
14
15
    for (i=0; i<len; i++)
16
      {
17
        RFM12_PORT &= ~(1<<RFM12_CS);      // CS auf L
18
        asm("nop");
19
        asm("nop");
20
      while (!(RFM12_PIN & (1<<RFM12_SDO)))  // warten bis SDO 1 -> FFIL 
21
        {
22
        }
23
                
24
      byte = 0xB0;              // Receive FIFO
25
26
      for (j=0; j<8; j++)
27
        { 
28
        if (byte & 0x80)
29
            {
30
            RFM12_PORT |= (1<<RFM12_SDI);  // DATA auf H
31
            }
32
        else
33
            {
34
            RFM12_PORT &= ~(1<<RFM12_SDI);  // DATA auf L
35
            }
36
        asm("nop");
37
        asm("nop");
38
        asm("nop");
39
          RFM12_PORT |= (1<<RFM12_SCK);    // CLK auf H
40
        asm("nop");
41
        asm("nop");
42
        asm("nop");
43
        asm("nop");
44
          RFM12_PORT &= ~(1<<RFM12_SCK);    // CLK auf L
45
        byte = (byte << 1);          // nächstes Bit nach oben
46
        }
47
48
      byte = 0;
49
50
      for (j=0; j<8; j++)
51
        {     
52
        byte = (byte << 1);          // eins höher schieben
53
        if ((RFM12_PIN & (1<<RFM12_SDO)) == (1<<RFM12_SDO))  // Bit 1?
54
            {
55
            byte = (byte | 0x01);        // ja
56
            }
57
        asm("nop");
58
          RFM12_PORT |= (1<<RFM12_SCK);    // CLK auf H
59
        asm("nop");
60
        asm("nop");
61
          RFM12_PORT &= ~(1<<RFM12_SCK);    // CLK auf L
62
        }
63
      *data_buf++ = byte;
64
      RFM12_PORT |= (1<<RFM12_CS);      // CS auf H
65
    }
66
67
    RFM12_send_cmd(0x8208);            // Empfänger aus
68
69
  }

Die Routine ist Software-SPI auf einem AVR, es geht ja nur um die 
Einleseschleife der Daten.
Ich lese eine feste Anzahl Bytes als Telegramm ein.

Gestartet wird im Interrupt, wenn derIRQ den Empfang der Magic-Pattern 
meldet.

Gruß aus Berlin
Michael

von Mateusz R. (mateusz224)


Lesenswert?

@Felix:
Also ich bin mit nicht sicher ob du mcih richtig verstanden hast, bin 
aber auch furchtbar in erklären^^. Also MOSI ist deswegen die ganze Zeit 
auf LOW durch die hinzugefügte Zeile:
1
while(!(rfm_get_status() & (1<<15)));

beim lesen des Status Registers wird auf die MOSI Leitung 00000000 
00000000 gelegt. Da jedoch die oben genannte Aussage nie true wird 
(wieso auch immer!!?!?!?!!) bleibt das Programm da stecken. Und nIRQ 
verändert sich NIE es ist IMMER auf HIGH und ich glaub das ist das 
Problem. Das irgendwas mit dem FIFO nicht stimmt... aber es funktioniert 
bei beiden Modulen nicht also ist das auch kein Hardware schaden... habe 
das auch schon vorher bei einem 434MHz Modul versucht gleiches 
Problem...

nIRQ hat nur dann sich verändert wenn ich nicht für jeden befehl nSEL 
auf low gezogen habe...

@Miachel
 "SDO spiegelt immer den Zustand des FIFO-Status"

stimmt jedoch glaub ich nicht dass es den gewünschten Effekt mit sich 
bring... also ich werde das später testen, aber eigetlich würde ich den 
nIRQ schon funktionsfähig haben wollen damit das hauptprogramm weiter 
abeiten kann und nicht die ganze Zeit auf ankommende Daten warten muss 
bzw den Fifo überprüfen muss...

: Bearbeitet durch User
von Stefan (Gast)


Lesenswert?

Also der SEL Pin muß auf Low, dann empfängt das Modul
Daten oder einen Befehl.
Beim Empfänger geht nur MISO auf high, wenn er 2DD4
empfangen hat. Dabei wird auch ein Datenbyte mit gesendet.
Dieses holt man mit B0000 ab.
Sendet der Sender kein 2DD4 so kann beim Empfänger auch der
MOSI Pin nicht auf high gehen.

von Mateusz R. (mateusz224)


Lesenswert?

@Stefan
Das tut doch mein Programm ich Sende ja 0x8B2D und anschließend 0x8BD4 
oder meinst du etwas anderes?

von Michael U. (amiga)


Lesenswert?

Hallo,

ich hatte nicht soviel Zeit, das alles durchzuschauen, meine 
Initialisierung als Empfänger ist ja schon in meinem Posting ziemlich 
weit oben.

Die läuft so mit diesen Werten, ist für 433MHz.
Wenn der RFM meldet, daß das MagicPattern empfängen wurde startet die 
zuletzt gepostete Routint und warte darauf, das SDO auf H geht, dann ist 
ein Byte im FIOF und das hole ich ab und warte auf das nächste.

Es gibt auch eine komplette IRQ-Lösung bei mir, die muß ich erst 
raussuchen.
Meine C-Sachen sind da leider etwas ungeordnet, das Original ist 
komplett in AVR-Assembler.

Das Einschalten des Empfängers ist bei mir mit:
1
    RFM12_send_cmd(0x82C8);            // Empfänger ein
2
    RFM12_send_cmd(0xCA81);            // set FIFO mode
3
    RFM12_send_cmd(0xCA83);            // enable FIFO

Am Ende eines Datenpaketes schalte ich wieder aus:
1
   RFM12_send_cmd(0x8208);            // Empfänger aus

Das stammt aus Testsourcen, die so laufen, aber nicht komplett sind.
Es ging mir ja nur um die Initialisierung des RFM12 als Empfänger und 
das auslesen des FIFO.

Jedesmal Status komplett holen kann je nach eingesteller Baudrate und 
SPI-Geschwindigkeit durchaus zum Überlauf des FIFO führen. Die haben das 
mit dem Bit auf SDO durchaus mit Absicht eingebaut.

Gruß aus Berlin
Michael

: Bearbeitet durch User
von Stefan (Gast)


Lesenswert?

Wollte nur damit sagen, wenn der MOSI nicht
auf high geht, dann sendet der Sender nicht.
Deshalb habe ich das vorgeschlagen mit dem
DVB-T Stick. Damit du überhaupt mal siehst,
ob er sendet. So weist du nicht wo der Fehler liegt.
Beim Sender oder Empfänger.

von Michael U. (amiga)


Lesenswert?

Hallo,

deshalb hatte ich mir vor Jahren dieses hochwertige Gerät gekauft:
http://www.ebay.de/itm/GY-560-Frequency-Counter-Frequenzzahler-fur-Transmitter-Funkgerat-Tragbar-Neu-/311368892559?hash=item487f08408f

Gibt es also immernoch...
Ist nicht wirklich zu gebrauchen, aber als Sendeindikator nutzbar, auch 
wenn man bei RFM12 o.ä. den RFM12-Antennendraht besser um die Antenne 
des Gerätches wickelt.

Gruß aus Berlin
Michael

von Felix P. (fixxl)


Lesenswert?

Mateusz R. schrieb:
> beim lesen des Status Registers wird auf die MOSI Leitung 00000000
> 00000000 gelegt. Da jedoch die oben genannte Aussage nie true wird
> (wieso auch immer!!?!?!?!!) bleibt das Programm da stecken.
Wenn MISO beim Aktivieren des Chips auf high geht, muss das MSB des 
Statusregisters gesetzt sein und dementsprechend sollte die 
while-Schleife auch abbrechen. Sehr komisch!

Hast du mal mit dem Oszi die MISO-Leitung überwacht, ob das eingelesene 
Resultat dem tatsächlichen Pegel entspricht? Nicht dass der Fehler 
irgendwo in den spi-Routinen liegt.

von Mateusz R. (mateusz224)


Lesenswert?

Also kurzzeitig hat die nIRQ Leitung funktioniert und nach einiger Zeit 
nicht mehr... ist aber auch nicht reproduzierbar gewesen... und jetzt 
habe ich es geschafft die Platine zu schrotten^^

Naja kann aber die Tests weiter auf dem Raspberry machen, da ist ja das 
gleiche Ergebnis und zwar dass nIRQ auf dauer HIGH ist.

Also ich versuch erstmal den Fifo interrupt stabil zu erhalten... wenn 
das funktioniert dann schau ich ob ich auch Daten erhalte.

Denke solange kein nIRQ interrupt ausgelöst wird bzw. dass FFIT bit auch 
gesetzt wird beim Sender, werde ich auch keine Daten beim Empfänger 
erhalten.

PS: Ja die spi-Routinen sind in Ordnung.

: Bearbeitet durch User
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.