PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RFM12 + ATMEGA32 kein Empfang



Mc Delta
20.06.2012, 20:13
Hallo Forum,
Ich bin 16 Jahre alt und beschäftige mich zur Zeit mit Mikrocontrollern.
Ich versuche schon seit Tagen das Funkmodul RFM12B von Pollin zum laufen zu bekommen. http://www.pollin.de/shop/dt/NTg4OTgxOTk-/Bausaetze_Module/Module/Funkmodul_RFM12B_868_S_Sende_Empfangsmodul.html
Leider ohne Erfolg. Ich habe ein LCD Display zur Ausgabe, was perfekt funktioniert an den Mega 32 angeschlossen und das Funkmodul wie folgt:
nSEL an SS
SCK an SCK
SDI an MOSI
SDO an MISO
22622

#include <avr/io.h>#include <util/delay.h>
#include <inttypes.h>
#include "SED1520.h"


#define F_CPU 16000000


#define DDR(x) (_SFR_IO8(_SFR_IO_ADDR(x)-1))
#define PIN(x) (_SFR_IO8(_SFR_IO_ADDR(x)-2))


#define set_bit(reg,bit) ((reg)|=(1<<(bit)))
#define clear_bit(reg,bit) ((reg)&=~(1<<(bit)))
#define toggle_bit(reg,bit) ((reg)^=(1<<(bit)))
#define is_bit_set(reg,bit) ((reg) & (1<<(bit)))


#define OUTPUT(bit) set_bit(DDR(bit##_PORT),bit)
#define INPUT(bit) clear_bit(DDR(bit##_PORT),bit)
#define SET(bit) set_bit((bit##_PORT),bit)
#define CLEAR(bit) clear_bit((bit##_PORT),bit)
#define TOGGLE(bit) toggle_bit((bit##_PORT),bit)
#define READ(bit) is_bit_set(PIN(bit##_PORT),bit)


//Definitions of SPI pins in the microcontroller
#define SPI_CS_PORT PORTB
#define SPI_CS 4
#define SPI_SCK_PORT PORTB
#define SPI_SCK 7
#define SPI_MISO_PORT PORTB
#define SPI_MISO 6
#define SPI_MOSI_PORT PORTB
#define SPI_MOSI 5






//Setup a simple timeout
inline void timeout_init(void)
{
TCCR2 = 0; //disable the timer
TCNT2 = 0; //start counting from 0
TCCR2 = 7; //turn the timer on (prescaler 1024)
TIFR = (1 << TOV2); //clear the overflow flag
}


//Test if the timeout expired
inline uint8_t timeout(void)
{
return (TIFR & (1 << TOV2)); //return non-zero if the timer overflowed
}


//Test if the module is ready for sending / receiving next byte
uint8_t rf12_is_ready(void)
{
CLEAR(SPI_CS); //activate the module
_delay_us(1); //let it respond
uint8_t r = READ(SPI_MISO); //read the SO line (first bit of status word)
SET(SPI_CS); //deactivate the module
return r; //return the value of the first bit
}


//Exchange a word (two bytes, big-endian) with the module
uint16_t rf12_trans(uint16_t to_send)
{
uint16_t received = 0; //buffer for data we are going to read
CLEAR(SPI_CS); //activate the module
SPDR = (to_send >> 8) & 0xFF; //send the upper byte
while (!(SPSR & (1 << SPIF))); //wait until the transmission is complete
received = SPDR; //store received byte
received <<= 8; //move it on its proper position
SPDR = (0xFF & to_send); //send the lower byte
while (!(SPSR & (1 << SPIF))); //wait until the transmission is complete
received |= SPDR; //store received byte
SET(SPI_CS); //deactivate the module
return received; //return the data from the module
}


//send one byte through the radio
void rf12_txbyte(uint8_t b)
{
while (!rf12_is_ready()) //wait while the module is not ready...
if (timeout()) //...if it is too long...
return; //...abort the operation
rf12_trans(0xB800 | b); //send the desired byte
}


//receive one byte through the radio
uint8_t rf12_rxbyte(void)
{
while (!rf12_is_ready()) //wait while the module is not ready...
if (timeout()) //...if it is too long...
return 0; //...abort the operation
return rf12_trans(0xB000); //read the byte from the receive FIFO
}


//adaptation to use the statements from rf12b_code.pdf
#define RFXX_WRT_CMD(x) rf12_trans(x)


//prepare the radio module
void radio_config(void)
{
OUTPUT(SPI_CS); OUTPUT(SPI_MOSI); //setup the directions...
OUTPUT(SPI_SCK); INPUT(SPI_MISO); //...of the SPI pins
SET(SPI_CS); //initially deactivate the module
SPCR = (1 << SPE) | (1 << MSTR)| (1 << CPOL); //turn the SPI on
SPSR = 0; //with the single speed
_delay_ms(10); //wait a moment
rf12_trans(0xFE00); //send the reset command
_delay_ms(150); //wait for reset to complete


//Example setup
RFXX_WRT_CMD(0x80E7);//EL,EF,868band,12.0pF
RFXX_WRT_CMD(0x8219);//!er,!ebb,!ET,ES,EX,!eb,!ew,DC
RFXX_WRT_CMD(0xA67C);//868MHz
RFXX_WRT_CMD(0xC647);//4.8kbps
RFXX_WRT_CMD(0x94A0);//VDI,FAST,134kHz,0dBm,-103dBm
RFXX_WRT_CMD(0xC2AC);//AL,!ml,DIG,DQD4
RFXX_WRT_CMD(0xCA81);//FIFO8,SYNC,!ff,DR
RFXX_WRT_CMD(0xCED4);//SYNC=2DD4;
RFXX_WRT_CMD(0xC483);//@PWR,NO RSTRIC,!st,!fi,OE,EN
RFXX_WRT_CMD(0x9850);//!mp,90kHz,MAX OUT
RFXX_WRT_CMD(0xE000);//NOT USE
RFXX_WRT_CMD(0xC800);//NOT USE
RFXX_WRT_CMD(0xC040);//1.66MHz,2.2V
}


//Send data packet through the radio
void radio_send(uint8_t * buffer, uint8_t len)
{
timeout_init(); //setup the timeout timer
rf12_trans(0x8238); //start transmitter
rf12_txbyte(0xAA); //send the preamble, four times 0xAA
rf12_txbyte(0xAA);
rf12_txbyte(0xAA);
rf12_txbyte(0xAA);
rf12_txbyte(0x2D); //then the predefined sync words
rf12_txbyte(0xD4);
rf12_txbyte(0xC0); //and a secret 0xC0DE
rf12_txbyte(0xDE);
rf12_txbyte(len); //next the length of the data
while (len--)
rf12_txbyte(*buffer++); //and then the data itself
rf12_txbyte(0x00); //finish the transmission with two dummy bytes
rf12_txbyte(0x00);
while (!rf12_is_ready() && !timeout()); //wait for the completion of the send operation
rf12_trans(0x8208); //go to idle, disable the transmitter
}


//receive data packet through the radio
int16_t radio_rcv(uint8_t * buffer, uint8_t max_len)
{
uint8_t len, i, timeout_counter;
timeout_init(); //setup the timeout timer
timeout_counter = 3; //after some timeouts the procedure will give-up
while (1)
{
rf12_trans(0x8208); //send the module to the idle
rf12_trans(0x82C8); //and restart as a receiver
_delay_us(150);
rf12_trans(0xCA81); //disable the FIFO, and...
rf12_trans(0xCA83); //...enable again, just to clear it
while(1) //wait for the transmission to start
{
if (timeout()) //if the timeout occurred...
{
if (!(timeout_counter--)) //count it, and if no more trials remain
{
rf12_trans(0x8208); //put the module to the idle state
return -1; //and return an error code
}
timeout_init(); //setup the timer for the next measurement
}
if(rf12_is_ready()) break; //proceed if the module captured some data
}
timeout_init(); //restart the timeout timer
i = rf12_trans(0xB000); //retrieve the received byte
if(i != 0xC0) continue; //test if its correct
i = rf12_rxbyte(); //try to receive the next byte
if(i != 0xDE) continue; //test if its correct
len = rf12_rxbyte(); //try to receive the 'length' byte
if (len > max_len) continue; //test if the passed buffer is large enough
//if all the bytes received so far are correct, we may assume that the
//transmission is not a "false positive", so the program will continue reception
break;
}
i = len; //we re going to read 'len' bytes
while (i--) //loop while there is anything more to read
{
*buffer++ = rf12_rxbyte(); //receive next byte, and advance write pointer
if (timeout()) //if a timeout occured
{
rf12_trans(0x8208); //stop receiving
return -2; //and return error code
}
}
rf12_trans(0x8208); //put the module to the idle state
return len; //return packet length
}


int main(void)
{DDRB = 0x00;
DDRD = 0x00;
_delay_ms(200);
GLCD_Init();
_delay_ms(200);
GLCD_ClearScreen();
_delay_ms(200);
GLCD_WriteString("Test");
_delay_ms(2000);




radio_config(); //setup the module


uint8_t buff[200]; //provide some buffer for data
buff[0] = '0';
buff[1] = '0';
buff[2] = '0';
uint8_t test;
/* while(1)
{

GLCD_ClearScreen();
radio_config();
buff[0] = 'a';
buff[1] = 'b';
buff[2] = 'c'; //setup the radio again (not really needed)
radio_send(buff,3); //send the data
GLCD_WriteString("Gesendet: ");
GLCD_WriteInt(buff[0]);
GLCD_WriteInt(buff[1]);
GLCD_WriteInt(buff[2]);
_delay_ms(200);

}*/


while(1)
{
GLCD_ClearScreen();
radio_config();
test = radio_rcv(buff, 200);
GLCD_WriteString("Empfangen: ");
GLCD_WriteInt(test);
GLCD_GoTo(0, 1);
GLCD_WriteChar(buff[0]);
GLCD_WriteInt(buff[0]);
GLCD_WriteHex(buff[0]);
GLCD_GoTo(0, 2);
GLCD_WriteChar(buff[1]);
GLCD_WriteInt(buff[1]);
GLCD_WriteHex(buff[1]);
GLCD_GoTo(0, 3);
GLCD_WriteChar(buff[2]);
GLCD_WriteInt(buff[2]);
GLCD_WriteHex(buff[2]);
GLCD_WriteHex(rf12_trans(0xB000));
_delay_ms(2000);
}
}




Der code soll das Hardware SPI nutzen. Ich habe ihn irgendwo im Netz gefunden und ist bei bei weitem nicht der einzige, den Ich probiert habe.
Der Takt des AVR kommt von einem externen Quarz mit 16 MHz.
Nun zum Problem:
Das Display schreibt zwar die ganze Zeit, dass meine Daten versendet werden, aber wenn das so ist, empfängt mein Modul mit der Empfängersoftware garnichts. Damit meine ich Nullen.
Da die Funkmodule nach einer Zeit warm werden, gehe ich davon aus, dass sie tatsächlich senden.


Wenn mir Jemand helfen könnte wäre das super.
Ich weiß nicht was Ihr noch für Infos braucht oder ob ihr schon über den Code einen Fehler entdecken könnt. Ich bin jedenfalls am Verzweifeln.

Mit freundlichen Güßen
Mc Delta

Mc Delta
21.06.2012, 16:51
Gibt es vielleicht jemanden, der schon Erfahrung mit dem RFM12B hat? Es würde mir auch weiterhelfen, wenn ich einen Schaltplan und eine Bibliothek hätte von der ich ausgehen kann, dass sie funktioniert.
Bisher habe ich mich an den Schaltplan aus dem Datenblatt gehalten. Für mich wäre vor allem Hardware SPI interessant, weil es am einfachsten zu verstehen ist und nicht so viele IOs belegt.
MfG
Mc Delta

Slein
22.06.2012, 22:10
Hi!
Ich glaub nicht, daß die Dinger irgendwie fühlbar warm werden sollten...
Mehr fällt mir dazu leider nicht ein :)

MfG
Niels

KR-500
19.07.2012, 13:34
Hi,

ich habe zwei von den Funkmodulen in Betrieb, bei mir werden sie glaub ich nicht warm. Dein Code sieht eig ganz ok aus aber könntest du vlt noch mal den genauen Schaltplan posten mit dem du das Modul angeschlossen hast? Ich hab das Modul bisher immer über eine Software SPI am laufen gehabt, das ist nicht komplizierter als die Hardware SPI, man muss lediglich die rf12_trans Routine ändern.
Das hat jetzt vlt nicht mit der Lösung des Problems zu tun aber gewöhn dir an die {} auch bei einzeilern zu machen besonders deine rf12_rxbyte und rf12_txbyte sind sehr unübersichtlich ;)

Im Anhang ein zip File mit meinem Sourcecode und einem Eagle FIle wie ich das Modul angeschlossen hab.

Viele Grüße

markusj
19.07.2012, 15:52
Hast du berücksichtigt, dass das RFM12B ein 3,3V-Modul ist? Mit 16MHz ist entweder der AVR zu schnell für diese Spannung (die 16MHz sind laut Atmel nur bei 5V zulässig), oder du hast deine Funkchips gegrillt (-> Wärmeentwicklung)

mfG
Markus

Mc Delta
07.10.2012, 10:41
Danke für die Antworten :)
Ich habe mir jetzt die 5 Volt Module geholt und habe noch mal eine Frage und zwar zum SPI:
Fast alle Quellen sagen, dass man das RFM12 wie folgt verbinden soll:
nSEL an SS
SCK an SCK
SDI an MOSI
SDO an MISO

Doch wenn ich gar keine Hardware SPI benutzen will, kann ich ja auch andere IOs benutzen.
Wenn Ich aber die Hardware SPI pins benutze, kann ich dann das RFM12 trotzdem per Software SPI steuern oder lassen sich die Pins (MOSI,MISO,SS,SCK) dann nicht mehr als normale IOs ansteuern?
Es gibt ja eine Option in den Fuses die SPI zu disablen, aber da ich per ISP programmiere funktioniert das nicht.

markusj
07.10.2012, 11:07
Es gibt ja eine Option in den Fuses die SPI zu disablen, aber da ich per ISP programmiere funktioniert das nicht.
Finger weg davon! Das ist für die Programmierung über ISP und hat nichts mit SPI im normalen Betrieb zu tun!


Doch wenn ich gar keine Hardware SPI benutzen will, kann ich ja auch andere IOs benutzen.
Ich wüsste nicht, warum du das tun wolltest (HW-SPI nimmt dir viel Arbeit ab), aber möglich ist das, ja. In dem Falle hast du eine freie Wahl der Anschlüsse am AVR.


Wenn Ich aber die Hardware SPI pins benutze, kann ich dann das RFM12 trotzdem per Software SPI steuern oder lassen sich die Pins (MOSI,MISO,SS,SCK) dann nicht mehr als normale IOs ansteuern?
Wie bereits erwähnt, wenn du SW-SPI machst, bist du nicht an die HW-SPI-Pins gebunden. Es wäre aber Unsinnig, das RFM12 an die HW-SPI-Pins anzuschließen und dann damit SW-SPI zu machen. Aber: Solange du das HW-SPI nicht einschaltest, sind die entsprechenden Pins ganz normale I/O-Pins und können daher nach belieben verwendet werden.

mfG
Markus

Mc Delta
07.10.2012, 11:14
Danke für die schnelle Antwort.
Ich weiß jetzt also, dass ich die HW SPI Pins wie ganz normale IOs benutzen kann. Aber wie aktiviere oder deaktiviere ich denn die HW SPI?
Bzw. welches Register ist dafür zuständig?

KR-500
07.10.2012, 12:17
Hi,

wie du die HW SPI aktivierst, bzw deakivierst steht im Datenblatt (http://www.atmel.com/Images/doc2503.pdf). Ab Seite 132 geht es allgemein mit der SPI los, ab Seite 136 beginnt die "Register Description".
Zum aktivieren benutzt man das SPCR Register (S. 136) hier sind erklärt was die einzelnen Bits machen. Wir wollen die SPI im "Master Mode" (MSTR) betreiben und sie aktivieren (SPE). Eventuell musst du noch die SPI Clock Rate anpassen und die entsprechenden Pins müssen auf Ausgan bzw Eingang gestzt werden.



DDRB |= (1<<PB7) | (1<<PB5) | (1<<PB4);
PORTB |= (1<<PB4);
SPCR = (1<<SPE) | (1<<MSTR);

Als nächstes muss eine Routine zum Senden und Empfangen geschrieben werden. Dazu muss als erstes CHip Select aktiviert werden, danach werden die Daten in das Datenregister SPDR (S. 138 ) geschrieben. Die SPI beginnt sofort mit dem Übertragen, man muss lediglich darauf warten, dass die Schnittstelle fertig wird. Das kann man in dem SPSR (S. 138 ) Register feststellen mit dem SPIF Bit.



PORTB &=~ (1<<PB4) //Chip select auf low
SPDR = data;
while(!(SPSR & (1<<SPIF));
PORTB |= (1<<PB4);
return SPDR;


Hoffe das war verstädnlich viele Grüße
KR-500

Mc Delta
20.10.2012, 22:15
So Ich hab es jetzt nach einer Pause endlich geschafft die Funkmodule zum funken zu bringen. :D
Dabei benutze ich eine abgeänderte Software von Benedikt K. http://www.mikrocontroller.net/topic/67273

#include <avr/io.h>#include <avr/interrupt.h>
#include "rfm12.h"


#define F_CPU 1000000UL
#include <util/delay.h>






#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif




#define IRQ_Port PORTD
#define IRQ_Pin PIND
#define IRQ_DDR DDRD
#define IRQ 2
#define IRQ_Output() IRQ_DDR |= (1<<IRQ)
#define IRQ_Input() IRQ_DDR&=~ (1<<IRQ)
#define IRQ_High() IRQ_Port|= (1<<IRQ)
#define IRQ_Low() IRQ_Port&=~(1<<IRQ)
#define IRQ_Wait_Low() while(IRQ_Pin&(1<<IRQ))


#define RF_PORT PORTB
#define RF_DDR DDRB
#define RF_PIN PINB


#define SDI 5
#define SCK 7
#define CS 4
#define SDO 6




void _delay_s(int s)
{
for (unsigned char i=0; i<s*100; i++)
_delay_ms(10);
}




unsigned short rf12_trans(unsigned short wert)
{ unsigned short werti=0;
unsigned char i;


cbi(RF_PORT, CS);
for (i=0; i<16; i++)
{ if (wert&32768)
sbi(RF_PORT, SDI);
else
cbi(RF_PORT, SDI);
werti<<=1;
if (RF_PIN&(1<<SDO))
werti|=1;
sbi(RF_PORT, SCK);
wert<<=1;
_delay_us(0.3);
cbi(RF_PORT, SCK);
}
sbi(RF_PORT, CS);
return werti;
}


void rf12_init(void)
{
RF_DDR=(1<<SDI)|(1<<SCK)|(1<<CS);
RF_PORT=(1<<CS);
IRQ_Input();


for (unsigned char i=0; i<10; i++)
_delay_ms(10); // 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
}




void rf12_ready(void)
{ cbi(RF_PORT, CS);
while (!(RF_PIN&(1<<SDO))); // wait until FIFO ready
}


void rf12_txdata(unsigned char data)
{
rf12_trans(0x8238); // TX on
rf12_ready();
rf12_trans(0xB8AA);
rf12_ready();
rf12_trans(0xB8AA);
rf12_ready();
rf12_trans(0xB8AA);
rf12_ready();
rf12_trans(0xB82D);
rf12_ready();
rf12_trans(0xB8D4);
rf12_ready();
rf12_trans(0xB800|(data));
rf12_ready();
rf12_trans(0x8208); // TX off
}


char rf12_rxdata(void)
{
unsigned char data;
rf12_trans(0x82C8); // RX on
rf12_trans(0xCA81); // set FIFO mode
rf12_trans(0xCA83); // enable FIFO
rf12_ready();
data=rf12_trans(0xB000);
rf12_trans(0x8208); // RX off

return data;
}




Leider hat das ganze keine hohe Effektivität. (um die 10%)
Deswegen wollte ich fragen, was ich machen kann um die Genauigkeit zu verbessern?
Dafür spielt ja wahrscheinlich die Funktion rf12_ready() eine Rolle und auch diese
"Dummy Bytes".
Wie genau funktioniert das eigentlich?

rf12_trans(0xB8AA);
rf12_ready();
rf12_trans(0xB8AA);
rf12_ready();
rf12_trans(0xB8AA);
rf12_ready();
rf12_trans(0xB82D);
rf12_ready();
rf12_trans(0xB8D4);

markusj
21.10.2012, 11:46
Vermutlich muss am Empfänger etwas an der Frequenz (Stichwort: AFC) optimiert werden. Und das sind keine Dummy-Bytes sondern Kommandos. Wie wäre es, wenn du dich Mal mit dem Datenblatt des RF12 auseinander setzt?

mfG
Markus

Mc Delta
21.10.2012, 14:55
Das ist der Link zu einem gut erklärten Datenblatt.
http://www.mikrocontroller.net/articles/RFM12#Senderegister_schreiben_.28TX_Register_Write _B8xx.29 (http://www.mikrocontroller.net/articles/RFM12#Senderegister_schreiben_.28TX_Register_Write _B8xx.29)

Zum Thema Senderegister steht da:



Senden von mehr oder weniger Takteinlauf-Bytes (viele Flankenwechsel, möglichst gleich viele 0-Bits und 1-Bits, etwa 0xAA, 0x55, 0xCC usw.
Senden des Synchronmusters
Senden der Daten

Natürlich sind
0xB8xx Kommandos, aber es bedeutet, dass xx in den Sender geschrieben wird.
Ich wollte eigentlich nur wissen, wie der Empfänger weiß, dass er Daten im FIFO hat und was 0xB8AA, 0xB82D und 0xB8D4 bewirken bzw. warum sie nicht gesendet werden.
In dem Datenblatt steht übrigens auch :
ein Dummy-Byte (typischerweise 0xAA)

Also wird dieses 0/1 Bit wohl doch als Dummy verwendet.

markusj
21.10.2012, 16:20
Das ist der Link zu einem gut erklärten Datenblatt.
Das ist kein Datenblatt. Das Datenblatt gibt es beim Hersteller, in englischer Sprache formuliert, deutlich Umfangreicher und auch nicht ganz fehlerfrei ;)

Mit 0xB8 wird der Sende-Fifo adressiert, das zweite Byte sind die zu schreibenden Daten. Zur Taktsynchronisation benötigen die RF-Chips ein geeignetes Bitmuster, hier 0xAA (1010...) das hat aber nichts mit Dummy zu tun. Der Beginn eines Datenpaketes wird dann durch das Synchronmuster signalisiert, dieses ist 0x2DD4. Wenn der Receiver dieses Muster erkennt, beginnt er empfangene Daten im Fifo zu speichern. (Mit al=1) Das Synchronmuster wird dabei, wenn ich mich richtig erinnere, verschluckt.

Das Dummy-Byte zum Schluss dient nur dazu, auf Senderseite nach den Nutzdaten den Sender rechtzeitig abschalten zu können. Wenn das letzte Datenbyte gesendet wurde, ist ein Byte im Fifo frei, der RFM12 wackelt dann nochmal an der Leitung um neue Daten anzufordern. Genau an dieser Stelle kann der Sender dann deaktiviert werden. Mit dem RGUR-Interrupt geht das auch ohne Dummy-Byte.

mfG
Markus

Mc Delta
21.10.2012, 18:06
Danke für die Erklärung. War hilfreich.
Ich habe noch mal unter IRQ nachgeschaut, weil ich vorher vergeblich versucht hatte den Interrupt von dort zu beziehen. Ich glaube der Code ist immer an der Stelle hängengeblieben wo er warten sollte bis das RFM12 bereit ist.
Jedenfalls steht dort, dass man 0xCAF3 zur Konfiguration des FIFOs benutzen soll um das Problem zu beheben. Das würde ja bedeuten, dass ein Interrupt erst ausgelöst wird, wenn der FIFO komplett voll ist (15 bit) oder? Bei 0xCA83 wird der Interrupt ja schon bei 8 bit ausgelöst also
der Hälfte an Speicherplatz.
Ich kann mir nur nicht erklären, warum das eine Fehlerursache sein sollte.

Mario_aus_Berlin
07.11.2012, 15:13
Hallo

hat jemand zufällig eine funktionierende Lib für das RFM12-Modul mit Kommentaren. Ich bin nämlich langsam am Verzweifeln mit diesem Modul. Wenn dann bitte in C.
Danke schon mal im Voraus.

masasibe
09.11.2012, 15:27
Hallo Mario,

im mikrocontroller.net gibt es einen tollen Thread über das RFM 12.
Der Code von Benedikt K. stellt quasi eine komplette UART-Funkverbindung her.

Du brauchst zwei ATmega8, die du an je ein RFM12 anschließt.
Was dem dem einen ATmega über UART hineinschickst kommt dann
beim anderen wieder heraus und umgekehrt.

Ich hofffe das konnte dir helfen,

mfg masasibe

Edit: Hier ist noch der Link: http://www.mikrocontroller.net/topic/71682

Mc Delta
09.11.2012, 15:35
Probier die mal:



#include <avr/io.h>
#include <avr/interrupt.h>
#include "rfm12.h"


#define F_CPU 1000000UL
#include <util/delay.h>






#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif




#define IRQ_Port PORTD
#define IRQ_Pin PIND
#define IRQ_DDR DDRD
#define IRQ 2
#define IRQ_Output() IRQ_DDR |= (1<<IRQ)
#define IRQ_Input() IRQ_DDR&=~ (1<<IRQ)
#define IRQ_High() IRQ_Port|= (1<<IRQ)
#define IRQ_Low() IRQ_Port&=~(1<<IRQ)
#define IRQ_Wait_Low() while(IRQ_Pin&(1<<IRQ))


#define RF_PORT PORTB
#define RF_DDR DDRB
#define RF_PIN PINB


#define SDI 5
#define SCK 7
#define CS 4
#define SDO 6




void _delay_s(int s)
{
for (unsigned char i=0; i<s*100; i++)
_delay_ms(10);
}




unsigned short rf12_trans(unsigned short wert)
{ unsigned short werti=0;
unsigned char i;


cbi(RF_PORT, CS);
for (i=0; i<16; i++)
{ if (wert&32768)
sbi(RF_PORT, SDI);
else
cbi(RF_PORT, SDI);
werti<<=1;
if (RF_PIN&(1<<SDO))
werti|=1;
sbi(RF_PORT, SCK);
wert<<=1;
_delay_us(0.3);
cbi(RF_PORT, SCK);
}
sbi(RF_PORT, CS);
return werti;
}


void rf12_init(void)
{
RF_DDR=(1<<SDI)|(1<<SCK)|(1<<CS);
RF_PORT=(1<<CS);
IRQ_Input();


for (unsigned char i=0; i<10; i++)
_delay_ms(10); // wait until POR done


rf12_trans(0xC0E0); // AVR CLK: 10MHz
rf12_trans(0x80D7); // Enable FIFO
rf12_trans(0xC2AC); // 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(0x9850); // 0 dB, fsk:15kHz
rf12_trans(0xC623); // 10 kbps
}




void rf12_ready(void)
{ cbi(RF_PORT, CS);
while (!(RF_PIN&(1<<SDO))); // wait until FIFO ready
}


void rf12_txdata(unsigned char *data, unsigned char number)
{ unsigned char i;
rf12_trans(0x8238); // TX on
rf12_ready();
rf12_trans(0xB8AA);
rf12_ready();
rf12_trans(0xB8AA);
rf12_ready();
rf12_trans(0xB8AA);
rf12_ready();
rf12_trans(0xB82D);
rf12_ready();
rf12_trans(0xB8D4);
for (i=0; i<number; i++)
{ rf12_ready();
rf12_trans(0xB800|(*data++));
}
rf12_ready();
rf12_trans(0xB8AA);
rf12_ready();
rf12_trans(0x8208); // TX off
}


void rf12_rxdata(unsigned char *data, unsigned char number)
{ unsigned char i;
rf12_trans(0x82C8); // RX on
rf12_trans(0xCA81); // set FIFO mode
rf12_trans(0xCA83); // enable FIFO
for (i=0; i<number; i++)
{ rf12_ready();
*data++=rf12_trans(0xB000);
}
rf12_trans(0x8208); // RX off
}



Die habe ich irgendwo auf http://www.mikrocontroller.net/articles/RFM12 gefunden. und ein bisschen an der Konfiguration rumgespielt.