Forum: HF, Funk und Felder RFM12B-868-D


von CRT (Gast)


Lesenswert?

Hallo,

Ich habe vor einigen Wochen drei Funkchips RFM12B-868-D gekauft und 
versuche seither erfolglos, die Chips (die ja für 3.3V Stromkreise 
ausgelegt sind) in einem 5V Stromkreis zum Laufen zu bekommen. Die 
Übersetzungslogik zwischen den Spannungen funktioniert inzwischen 
zuverlässig, die Software-Seite gestaltet sich jedoch schwierig.

Da das Datasheet an einigen Stellen fehlerhaft / ungenau ist, habe ich 
noch andere Quellen hinzugezogen und versucht, mir einen eigenen Code zu 
schreiben, der sich einfach auf andere Szenarien portieren lässt:
1
// _I = INPUT PORT
2
// _O = OUTPUT PORT
3
// _P = PORT INDEX
4
// _D = DATA DIRECTION REGISTER
5
6
// SPI SCK (clock, output)
7
#define  RFM12B_SCK_I  PINA
8
#define  RFM12B_SCK_O  PORTA
9
#define  RFM12B_SCK_P  5
10
#define  RFM12B_SCK_D  DDRA
11
12
#define  RFM12B_SCK_INIT()  RFM12B_SCK_D |=  (1<<(RFM12B_SCK_P))
13
#define  RFM12B_SCK_LOW()   RFM12B_SCK_O &= ~(1<<(RFM12B_SCK_P))
14
#define  RFM12B_SCK_HIGH()  RFM12B_SCK_O |=  (1<<(RFM12B_SCK_P))
15
16
// SPI MISO / SDO (master in slave out, input)
17
#define  RFM12B_MISO_I  PINA
18
#define  RFM12B_MISO_O  PORTA
19
#define  RFM12B_MISO_P  3
20
#define  RFM12B_MISO_D  DDRA
21
22
#define  RFM12B_MISO_INIT()  ;
23
#define  RFM12B_MISO_LOW()   ~(RFM12B_MISO_HIGH())
24
#define  RFM12B_MISO_HIGH()  RFM12B_MISO_I & (1<<(RFM12B_MISO_P))
25
26
// SPI MOSI / SDI (master out slave in, output)
27
#define  RFM12B_MOSI_I  PINA
28
#define  RFM12B_MOSI_O  PORTA
29
#define  RFM12B_MOSI_P  4
30
#define  RFM12B_MOSI_D  DDRA
31
32
#define  RFM12B_MOSI_INIT()  RFM12B_MOSI_D |=  (1<<(RFM12B_MOSI_P))
33
#define  RFM12B_MOSI_LOW()   RFM12B_MOSI_O &= ~(1<<(RFM12B_MOSI_P))
34
#define  RFM12B_MOSI_HIGH()  RFM12B_MOSI_O |=  (1<<(RFM12B_MOSI_P))
35
36
// SPI SS / CS (slave select, output)
37
#define  RFM12B_SS_I  PINA
38
#define  RFM12B_SS_O  PORTA
39
#define  RFM12B_SS_P  6
40
#define  RFM12B_SS_D  DDRA
41
42
#define  RFM12B_SS_USE  1  // use SS ?
43
44
#if RFM12B_SS_USE == 1
45
  #define  RFM12B_SS_INIT()  RFM12B_SS_D |=  (1<<(RFM12B_SS_P))
46
  #define  RFM12B_SS_LOW()   RFM12B_SS_O &= ~(1<<(RFM12B_SS_P))
47
  #define  RFM12B_SS_HIGH()  RFM12B_SS_O |=  (1<<(RFM12B_SS_P))
48
#else
49
  #define  RFM12B_SS_INIT()  ;
50
  #define  RFM12B_SS_LOW()   ;
51
  #define  RFM12B_SS_HIGH()  ;
52
#endif
53
54
// IRQ (input)
55
#define  RFM12B_IRQ_I  PINA
56
#define  RFM12B_IRQ_O  PORTA
57
#define  RFM12B_IRQ_P  2
58
#define  RFM12B_IRQ_D  DDRA
59
60
#define  RFM12B_IRQ_INIT()  ;
61
#define  RFM12B_IRQ_LOW()   ~(RFM12B_IRQ_HIGH())
62
#define  RFM12B_IRQ_HIGH()  RFM12B_IRQ_I & (1<<(RFM12B_IRQ_P))
63
#define  RFM12B_IRQ_WAIT()  while(RFM12B_IRQ_HIGH())
64
65
// send and receive a 16bit-word via spi
66
uint16_t RFM12B_spi(uint16_t cmd)
67
{
68
  uint8_t i;
69
  uint16_t recv = 0;
70
  // start communication
71
  RFM12B_SCK_LOW();
72
  RFM12B_SS_LOW();
73
  // read 16 bits
74
  for(i=0; i<16; i++)
75
  {
76
    // send bit
77
    if(cmd & 0x8000)
78
      RFM12B_MOSI_HIGH();
79
    else
80
      RFM12B_MOSI_LOW();
81
    // clock
82
    RFM12B_SCK_HIGH();
83
    recv<<=1;
84
    // receive bit
85
    if(RFM12B_MISO_HIGH())
86
    {
87
      recv|=0x0001;
88
    }
89
    // clock
90
    RFM12B_SCK_LOW();
91
    cmd<<=1;
92
  }
93
  // end communication
94
  RFM12B_SS_HIGH();
95
  return recv;
96
}
97
98
// initialize hardware (atmel)
99
void RFM12B_init_hard() {
100
  // set default values
101
  RFM12B_SS_HIGH();
102
  RFM12B_MOSI_HIGH();
103
  RFM12B_SCK_LOW();
104
  // init ports
105
  RFM12B_SCK_INIT();
106
  RFM12B_MOSI_INIT();
107
  RFM12B_MISO_INIT();
108
  RFM12B_SS_INIT();
109
  RFM12B_IRQ_INIT();
110
}
111
112
// initialize software (rfm12b)
113
//   uint8_t  receiver  whether the rfm12b should be used as receiver or transmitter
114
void RFM12B_init_soft(uint8_t receiver)
115
{
116
  RFM12B_spi(0x80E7); //EL,EF,868band,12.0pF
117
  // init mode
118
  if(receiver)
119
    RFM12B_spi(0x8299); //er,!ebb,ET,ES,EX,!eb,!ew,DC (bug was here)
120
  else
121
    RFM12B_spi(0x8239); //!er,!ebb,ET,ES,EX,!eb,!ew,DC
122
  RFM12B_spi(0xA640); //frequency select
123
  RFM12B_spi(0xC647); //4.8kbps
124
  // RFM12B_spi(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm
125
    RFM12B_spi(0x94A5);
126
  RFM12B_spi(0xC2AC); //AL,!ml,DIG,DQD4
127
  RFM12B_spi(0xCA81); //FIFO8,SYNC,!ff,DR
128
  RFM12B_spi(0xCED4); //SYNC=2DD4AG
129
  RFM12B_spi(0xC483); //@PWR,NO RSTRIC,!st,!fi,OE,EN
130
  RFM12B_spi(0x9850); //!mp,90kHz,MAX OUT
131
  RFM12B_spi(0xCC17); //OB1ACOB0, LPX,Iddy,CDDIT,CBW0
132
  RFM12B_spi(0xE000); //NOT USED
133
  RFM12B_spi(0xC800); //NOT USED
134
  RFM12B_spi(0xC040); //1.66MHz,2.2V
135
}
136
137
// clear fifo buffer
138
void RFM12B_clear_fifo()
139
{
140
  RFM12B_spi(0xCA81);
141
  RFM12B_spi(0xCA83);
142
}
143
144
// send a byte
145
//   uint8_t  data  data to send
146
void RFM12B_put(uint8_t data)
147
{
148
  RFM12B_IRQ_WAIT();
149
  RFM12B_spi(0xB800 + data);
150
}
151
152
// receive a byte
153
uint8_t RFM12B_get()
154
{
155
  uint8_t data;
156
  while(1)
157
  {
158
    data = RFM12B_spi(0x0000);
159
    if ((data&0x8000))
160
    {
161
      data = RFM12B_spi(0xB000);
162
      return (data&0x00FF);
163
    }
164
  }
165
}

Mein Problem ist, dass die testweise Kommunikation zwischen zwei µCs 
(ein ATtiny45 bei 3.3V mit einem Funkchip und diesem Code und ein 
ATmega32 bei 5V mit Pegelkonverter und Funkchip) nicht funktioniert. Auf 
der Receiver-Seite wird nie ein Interrupt ausgelöst und auch das 
abgefragte Interrupt-Bit im Statusregister bei "RFM12B_get()" ist nie 
gesetzt, obwohl in unmittelbarer Nähe der andere Funkchip wie wild 
sendet/senden sollte. Nichtmal irgendwelcher "Müll" kommt an.

Meine Fragen sind folgende:
1. Hat jemand den Chip RFM12B schonmal erfolgreich zum Laufen gebracht?
2. Welcher Code wurde verwendet?
3. Vielleicht hat jemand ähnliche Probleme gehabt und kann mir ein wenig 
auf die Sprünge helfen.

Vielen Dank im Voraus!

CRT

von Analog (Gast)


Lesenswert?

Beitrag "Beispielprogramm für RFM12 433MHz Funk-Module"

ist zwar für 433MHz, kannst Dir aber das SPI-Protokoll mal ansehen.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

War bei deinen "anderen Quellen" bereits die Elektor Januar 2009 dabei? 
Dort ist ein längerer Artikel von B. Kainka zu diesen Modulen sogar 
speziell auf 868 MHz. Programmiersprache ist allerdings BASCOM AVR.

von CRT (Gast)


Lesenswert?

Vielen Dank für die schnellen Antworten.

@Analog: Ich habe mir den Link angesehen und werde es in der nächsten 
Zeit mit der dort verwendeten SPI Implementation versuchen. Was mir 
immernoch etwas schleierhaft ist: Laut dem Datasheet des Controllers 
überträgt dieser das erste Bit des Statusregisters bereits mit dem 
ersten Bit des "Commands" - ich frage mich, wie bei einer syncronen 
Datenübertragung möglich ist, dass der Slave schon weiß, was er mir 
schicken soll, bevor der Master die Übertragung des ersten Bits beendet 
hat. Weißt du dazu Genaueres?

@Stefan B.: Ich kannte die Elektor bisher noch nicht, entsprechend 
gehörte sie noch nicht zu meinen Quellen. Ich werde aber versuchen, sie 
in den nächsten Tagen irgendwo aufzutreiben. Zu Rate gezogen habe ich 
bisher v.A. das Datasheet des Herstellers (weitestgehend unbrauchbar), 
das Code-Example des Herstellers (ebenso unbenutzbar) und diese 
Quickstart-Anleitung: 
http://zenburn.net/~goroux/rfm12b/rfm12b_and_avr-%20quick_start.pdf 
Außerdem habe ich einen kurzen Blick auf den Code bei 
http://www.das-labor.org/ geworfen. An allen Implementationen hat mich 
gestört, dass man nicht vollständig frei definieren könnte, welche Pins 
man verwenden möchte, sondern dass es immer Randbedingungen gab (meist, 
dass sie im gleichen Port sein müssen). Störend ist natürlich auch, wenn 
die Implementationen schlicht fehlerhaft sind.

von Benedikt K. (benedikt)


Lesenswert?

CRT wrote:
> Was mir
> immernoch etwas schleierhaft ist: Laut dem Datasheet des Controllers
> überträgt dieser das erste Bit des Statusregisters bereits mit dem
> ersten Bit des "Commands" - ich frage mich, wie bei einer syncronen
> Datenübertragung möglich ist, dass der Slave schon weiß, was er mir
> schicken soll, bevor der Master die Übertragung des ersten Bits beendet
> hat.

Sobald CS auf Low geht, gibt der RF12 das FFIT Bit aus.
Das Datenblatt ist etwas uneindeutig was das Statusregister angeht:
Version 1:
Parallel zum Senden eines (beliebigen) Befehls, wird das Statusregister 
ausgegeben. Dies sieht man auch im Timingdiagramm auf Seite 13 des 
Datenblatts.
Version 2:
Nur das FFIT Bit wird ausgegeben, was danach kommt ist sonst was. Wenn 
man das Statusregister komplett lesen möchte, muss man den Befehl 0x0000 
senden. Dies steht auf Seite 23.

Beides kann in die Angaben aus dem Datenblatt hineininterpretieren. 
Welche Version richtig ist, habe ich noch nicht ausprobiert. Mit Version 
2 ist man aber auf der sicheren Seite.

> Ich kannte die Elektor bisher noch nicht, entsprechend
> gehörte sie noch nicht zu meinen Quellen. Ich werde aber versuchen, sie
> in den nächsten Tagen irgendwo aufzutreiben.

Schau aber erst rein ehe du die kaufst. Da wurde im Prinzip nur das 
Datenblatt wiedergegeben und ein paar Bascom Beispiele gezeigt. Nichts 
was man nicht auch kostenlos und besser im Internet finden kann.

von CRT (Gast)


Lesenswert?

Vielen Dank auch dir, Benedikt K., für deine schnelle und hilfreiche 
Antwort!

Ich habe die von mir verwendete Implementation mit der in dem anderen 
Beitrag und der von Wikipedia 
(http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus#Example_of_bit-banging_the_SPI_Master_protocol) 
verglichen und musste feststellen, dass es auch hier wieder Unterschiede 
gibt, wobei die von mir verwendete Implementation näher an dem 
Wikipedia-Beispielcode ist. Da der Funkchip aber vermutlich nach dem 
Heruntersetzen der Clock schnell genug sein nächstes Bit auf den Bus 
schaufelt, bevor der Atmel es lesen möchte und du außerdem den Code 
erfolgreich verwendest, muss es wohl ebenso funktionieren. Dass ich 
dennoch bisher bei meinem Receiver das erste Bit nie gesetzt bekam, bei 
meinem Chip im Transmitter-Modus aber halbwegs sinnvolle Werte beim 
Status-Read-Command rauskamen (0xA040, 0xE040 bei der ersten Abfrage), 
muss ich nun davon ausgehen, dass meine SPI-Implementation zwar stimmt, 
mein Chip aber schlicht und einfach nichts empfängt, was er mir liefern 
könnte.

@Benedikt K.: Warum hast du SPI so implementiert, wie du es 
implementiert hast? Hast du außerdem detailierte Informationen bezüglich 
des nFFS-Pins? Du schreibst in deinem Post, man möge ihn mit 10 kOhm auf 
Vdd pullen, das habe ich auch getan. Im Datasheet des auf elektor 
verlinkten Si4420 
(https://www.silabs.com/Support%20Documents/TechnicalDocs/Si4420.pdf) 
steht auf Seite 4 "nFFS | FIFO select input (active low) In FIFO mode, 
when bit ef is set in Configuration Setting Command"; "ef" ist sowohl in 
deiner alsauch meiner Implementation auf 1, müsste dann nicht nFFS auf 
logisch high, also physisch low sein, um den FIFO zu verwenden?

von Benedikt K. (benedikt)


Lesenswert?

CRT wrote:
> Warum hast du SPI so implementiert, wie du es
> implementiert hast?

Weil es so dem Timing aus dem Datenblatt entspricht.

> Hast du außerdem detailierte Informationen bezüglich
> des nFFS-Pins? Du schreibst in deinem Post, man möge ihn mit 10 kOhm auf
> Vdd pullen, das habe ich auch getan. Im Datasheet des auf elektor
> verlinkten Si4420
> (https://www.silabs.com/Support%20Documents/TechnicalDocs/Si4420.pdf)
> steht auf Seite 4 "nFFS | FIFO select input (active low) In FIFO mode,
> when bit ef is set in Configuration Setting Command"; "ef" ist sowohl in
> deiner alsauch meiner Implementation auf 1, müsste dann nicht nFFS auf
> logisch high, also physisch low sein, um den FIFO zu verwenden?

Datenblatt RF12, Seite 14: Bit ef enables FIFO mode. -> ef muss 1 sein 
wenn man das FIFO verwendet. Gleichzeitig wird nFFS auch ein eigener 
Chipselect für das FIFO, man kann dann ohne Befehle zu senden, direkt 
die Daten auslesen, wenn man nFFS auf Low zieht anstelle von nSEL. Da 
ich dies aber nicht mache, muss nFFS deaktiviert werden, daher der 
Pullup.

von CRT (Gast)


Lesenswert?

Nochmals vielen Dank für all eure Hilfe! Ich habe es nun geschafft, 
einen Transmitter so zu programmieren, dass er auf die Flags im 
Status-Register Rücksicht nimmt und wartet, bis der Chip bereit ist, die 
nächsten Daten zu verarbeiten.

Ich werde mich nun wieder an einem Receiver versuchen und weitere 
Ergebnisse und Fragen hier posten. Mein Quellcode sieht inzwischen so 
aus:
1
// _I = INPUT PORT
2
// _O = OUTPUT PORT
3
// _P = PORT INDEX
4
// _D = DATA DIRECTION REGISTER
5
6
// SPI SCK (clock, output)
7
#define  RFM12B_SCK_I  PINA
8
#define  RFM12B_SCK_O  PORTA
9
#define  RFM12B_SCK_P  5
10
#define  RFM12B_SCK_D  DDRA
11
12
#define  RFM12B_SCK_INIT()  RFM12B_SCK_D |=  (1<<(RFM12B_SCK_P))
13
#define  RFM12B_SCK_LOW()   RFM12B_SCK_O &= ~(1<<(RFM12B_SCK_P))
14
#define  RFM12B_SCK_HIGH()  RFM12B_SCK_O |=  (1<<(RFM12B_SCK_P))
15
16
// SPI MISO / SDO (master in slave out, input)
17
#define  RFM12B_MISO_I  PINA
18
#define  RFM12B_MISO_O  PORTA
19
#define  RFM12B_MISO_P  3
20
#define  RFM12B_MISO_D  DDRA
21
22
#define  RFM12B_MISO_INIT()  RFM12B_MISO_D &= ~(1<<(RFM12B_MISO_P))
23
#define  RFM12B_MISO_LOW()   ~(RFM12B_MISO_HIGH())
24
#define  RFM12B_MISO_HIGH()  RFM12B_MISO_I & (1<<(RFM12B_MISO_P))
25
26
// SPI MOSI / SDI (master out slave in, output)
27
#define  RFM12B_MOSI_I  PINA
28
#define  RFM12B_MOSI_O  PORTA
29
#define  RFM12B_MOSI_P  4
30
#define  RFM12B_MOSI_D  DDRA
31
32
#define  RFM12B_MOSI_INIT()  RFM12B_MOSI_D |=  (1<<(RFM12B_MOSI_P))
33
#define  RFM12B_MOSI_LOW()   RFM12B_MOSI_O &= ~(1<<(RFM12B_MOSI_P))
34
#define  RFM12B_MOSI_HIGH()  RFM12B_MOSI_O |=  (1<<(RFM12B_MOSI_P))
35
36
// SPI SS / CS (slave select, output)
37
#define  RFM12B_SS_I  PINA
38
#define  RFM12B_SS_O  PORTA
39
#define  RFM12B_SS_P  6
40
#define  RFM12B_SS_D  DDRA
41
42
#define  RFM12B_SS_INIT()  RFM12B_SS_D |=  (1<<(RFM12B_SS_P))
43
#define  RFM12B_SS_LOW()   RFM12B_SS_O &= ~(1<<(RFM12B_SS_P))
44
#define  RFM12B_SS_HIGH()  RFM12B_SS_O |=  (1<<(RFM12B_SS_P))
45
46
#define  RFM12B_STATUS       RFM12B_spi(0x0000)
47
48
// INTs
49
#define  RFM12B_RGIT()       (RFM12B_STATUS & 0x8000)
50
#define  RFM12B_WAIT_RGIT()  while(!RFM12B_RGIT()) {  }
51
#define  RFM12B_FFIT()       (RFM12B_STATUS & 0x8000)
52
#define  RFM12B_WAIT_FFIT()  while(!RFM12B_FFIT()) {  }
53
54
// send and receive a 16bit-word via spi
55
uint16_t RFM12B_spi(uint16_t cmd)
56
{
57
  uint8_t i;
58
  uint16_t recv = 0;
59
  // start communication
60
  RFM12B_SCK_LOW();
61
  RFM12B_SS_LOW();
62
  // read 16 bits
63
  for(i=0; i<16; i++)
64
  {
65
    // send bit
66
    if(cmd & 0x8000)
67
      RFM12B_MOSI_HIGH();
68
    else
69
      RFM12B_MOSI_LOW();
70
    // clock
71
    RFM12B_SCK_HIGH();
72
    recv<<=1;
73
    // receive bit
74
    if(RFM12B_MISO_HIGH())
75
    {
76
      recv|=0x0001;
77
    }
78
    // clock
79
    RFM12B_SCK_LOW();
80
    cmd<<=1;
81
  }
82
  // end communication
83
  RFM12B_SS_HIGH();
84
  return recv;
85
}
86
87
// initialize hardware (atmel) (CHECKED)
88
void RFM12B_init_hard()
89
{
90
  // set default values
91
  RFM12B_SS_HIGH();
92
  RFM12B_MOSI_HIGH();
93
  RFM12B_SCK_LOW();
94
  // init ports
95
  RFM12B_SCK_INIT();
96
  RFM12B_MOSI_INIT();
97
  RFM12B_MISO_INIT();
98
  RFM12B_SS_INIT();
99
}
100
101
// initialize software (rfm12b) (CHECKED)
102
void RFM12B_init_soft()
103
{
104
/*  RFM12B_spi(0xC0E0); // CLK: 10MHz,2.2V*/
105
/*  RFM12B_spi(0x80E7); // EL,EF,868band,12.0pF*/
106
/*  RFM12B_spi(0xC2AB); // AL,!ml,DIG,DQD 3*/
107
/*  RFM12B_spi(0xCA81); // FIFO8,SYNC,!ff,DR*/
108
/*  RFM12B_spi(0xE000); // WakeUp-Timer: NOT USED*/
109
/*  RFM12B_spi(0xC800); // Low-Duty-Cycle: NOT USED*/
110
/*  RFM12B_spi(0xC4F7); // AFC settings: autotuning: -10kHz...+7,5kHz*/
111
/*  */
112
/*  RFM12B_spi(0xA640); //frequency select*/
113
/*  // RFM12B_spi(0x94A0); //VDI,FAST,134kHz,0dBm,-103dBm*/
114
/*  RFM12B_spi(0x94A5);*/
115
/*  RFM12B_spi(0xC647); //4.8kbps*/
116
/*  RFM12B_spi(0x9850); //!mp,90kHz,MAX OUT*/
117
  RFM12B_spi(0x80D7);//EL,EF,433band,12.0pF
118
  RFM12B_spi(0x8239);//!er,!ebb,ET,ES,EX,!eb,!ew,DC
119
  RFM12B_spi(0xA640);//434MHz
120
  RFM12B_spi(0xC647);//4.8kbps
121
  RFM12B_spi(0x94A0);//VDI,FAST,134kHz,0dBm,-103dBm
122
  RFM12B_spi(0xC2AC);//AL,!ml,DIG,DQD4
123
  RFM12B_spi(0xCA81);//FIFO8,SYNC,!ff,DR
124
  RFM12B_spi(0xCED4);//SYNC=2DD4;
125
  RFM12B_spi(0xC483);//@PWR,NO RSTRIC,!st,!fi,OE,EN
126
  RFM12B_spi(0x9850);//!mp,90kHz,MAX OUT
127
  RFM12B_spi(0xCC77);//OB1,OB0, LPX,!ddy,DDIT,BW0
128
  RFM12B_spi(0xE000);//NOT USE
129
  RFM12B_spi(0xC800);//NOT USE
130
  RFM12B_spi(0xC040);//1.66MHz,2.2V
131
}
132
133
// send a byte (CHECKED)
134
//   uint8_t  data  data to send
135
void RFM12B_put(uint8_t data)
136
{
137
  RFM12B_WAIT_RGIT();
138
  RFM12B_spi(0xB800 + data);
139
}
140
141
// receive a byte (CHECKED)
142
uint8_t RFM12B_get()
143
{
144
  RFM12B_WAIT_FFIT();
145
  return RFM12B_spi(0xB000) & 0x00FF;
146
}
147
148
// transmit multiple bytes (CHECKED)
149
//   uint8_t  data[]  data to transmit
150
//   uint8_t  length  length of the data to transmit
151
void RFM12B_transmit(uint8_t data[], uint8_t length)
152
{
153
  uint8_t i;
154
  // enable TX
155
  RFM12B_spi(0x8238);
156
  RFM12B_put(0xAA);
157
  RFM12B_put(0xAA);
158
  RFM12B_put(0xAA);
159
  RFM12B_put(0x2D);
160
  RFM12B_put(0xD4);
161
162
  for(i = 0; i < length; i++)
163
164
  {
165
    RFM12B_put(data[i]);
166
167
  }
168
169
  RFM12B_WAIT_RGIT();
170
  // disable TX
171
172
  RFM12B_spi(0x8208);
173
}
174
175
176
// receive multiple bytes (CHECKED)
177
//   uint8_t  data[]  buffer for received data
178
//   uint8_t  length  length of data to receive
179
180
void RFM12B_receive(uint8_t *data, uint8_t length)
181
182
{
183
  uint8_t i;
184
  // enable RX
185
186
  RFM12B_spi(0x82C8);
187
  // set FIFO mode
188
189
  RFM12B_spi(0xCA81);
190
  // enable FIFO
191
192
  RFM12B_spi(0xCA83);
193
194
  for(i = 0; i < length; i++)
195
196
  {
197
    data[i] = RFM12B_get();
198
199
  }
200
  RFM12B_WAIT_FFIT();
201
  // disable RX
202
203
  RFM12B_spi(0x8208);
204
205
}

Die Software-Initialisierung muss ich nochmal durchgehen, damit ich sie 
verstehe.

Wenn jemand einen Fehler findet oder Denkanstöße in irgendeine Richtung 
für mich hat, immer her damit! :)

von CRT (Gast)


Lesenswert?

Mein RFM12B-Treiber funktioniert nun! Ich arbeite gerade noch daran, ihn 
an einigen Stellen zu überarbeiten, außerdem versuche ich mich an der 
Interrupt-Implementation und gehe nochmal die Initialisierung durch. 
Wenn er tadellos funktioniert werde ich ihn hier als Code-Schnipsel zur 
freien Verwendung durch andere verlinken.

Eine Frage kam mir noch bzgl. Frequenzen: Das 868 MHz-Band ist relativ 
restriktiv limitiert (Quellen: 
http://de.wikipedia.org/wiki/Short_Range_Devices und 
http://www.roboternetz.de/wissen/index.php/Funkmodule). Stellenweise 
darf man nur mit Duty Cycle 0,1% oder 1% senden, hier sind offenbar auch 
kritische Funkdienste wie sogenannte "Social Alarms" unterwegs, deren 
Störung unbedingt vermieden werden muss.

Aus diesem Grund würde es mich freuen, wenn möglichst viele Augen den 
folgenden Gedankengang und die Rechnung nachvollziehen und ihre 
Meinung/Bedenken darüber äußern würden:

Laut Wikipedia (http://de.wikipedia.org/wiki/Short_Range_Devices) und 
RoboterNetz (http://www.roboternetz.de/wissen/index.php/Funkmodule) ist 
der Bereich 869,3 - 869,4 MHz im 868 MHz-Band "offen"; ich kenne mich 
mit der Terminologie nicht aus, nehme aber an, dass das bedeutet, dass 
hier keine Duty Cycle und Nutzungseinschränkungen gemacht werden. Ist 
das richtig?

Das Code-Datensheet sagt auf Seite 2 zum Frequency Setting Command, die 
Frequenz berechne sich über Fc = 860 + F * 0.0050 MHz; möchte ich nun 
also auf 869,3 MHz senden, muss ich nach F auflösen, Fc einsetzen und 
bekomme dann für F (also den Wert von f11..f0) 1860 oder 0x744. Ist das 
richtig?

Was bedeuten die Frequenzangaben beim AFC Command (Seite 5) und TX 
Configuration Control Command (Seite 6)?

Die Einschränkung der 10mW sollte nicht überschritten werden, denn: Laut 
Datasheet Seite 5 beträgt die "Max. available output power" im 868 
MHz-Band typischerweise 4 dBm; laut Wikipedia 
(http://en.wikipedia.org/wiki/DBm#Unit_conversions) entspricht das 
2,5mW; ist das richtig?

Ich hätte nun, davon ausgehend, dass ich die Basis-Frequenz einstellen 
muss und der Funkchip dann die Basisfrequenz +- die Frequency Deviation 
besendet, folgende Einstellungen vorgenommen:

Frequency Setting Command (0xA74E): Fc = 869,350 MHz (Mitte des 
Bereiches 869,300 - 869,400 MHz) => F = 1870 = 0x74E
TX Configuration Control Command (0x9820): p = 000b (Output Power: 
0dBm), m = 0010b (Frequency Deviation: 45kHz)

AFC und den Receiver Control Command hätte ich außenvor gelassen, da sie 
scheinbar nur beim Empfangen der Signale eine Rolle spielen.

von MrNice (Gast)


Lesenswert?

Hey,

habe mir soeben auch diese Module zugelegt und würde mich für deine 
Implementierung interessieren. Die Ansätze hier sind schon sehr 
hilfreich!

Hast du weiter gearbeitet oder ist das Projekt tot?
Würde mich über jeden Codefetzen freuen ;)

Danke...

von CRT (Gast)


Lesenswert?

Hallo.

Entschuldige, dass ich mich erst so spät melde, ich wollte eigendlich 
den Code noch überarbeiten und dann hier hochladen. Dabei ist mir aber 
der normale Alltag dazwischengekommen und ich habe das ganze aus den 
Augen verloren.

Meine bisherige unbereinigte (!!!) Version habe ich hier online 
gestellt: http://www.joachim-neu.de/index.php?lang=1&id=102

Dort werde ich auch Änderungen einpflegen und den Code falls nötig 
aktualisieren.

Ich möchte mich nochmal für die Hilfe aus dem Forum hier bedanken, 
namentlich bei Benedikt K., Stefan B. und Analog. Ich hoffe der Code 
hilft anderen bei der Ansteuerung ihrer Funkmodule!

CRT

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.