Code:
#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.
Lesezeichen