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
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