Jim Lindblom code

From emboxit
Revision as of 16:51, 11 September 2015 by Admin (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

From http://www.sparkfun.com/datasheets/BreakoutBoards/RFM22-Example-Code.zip

This code was used to  test communication between two RFM22 modules. WinAVR (AVRDude) was used to compile and write the code.  
Makefiles are set up for serial programming - check  out this tutorial for more info: http://www.sparkfun.com/commerce/tutorial_info.php?tutorials_id=142.
In my testing, I used two 3.3V Arduino Pro's (ATmega328), one programmed with the Receive code and one with the Transmit. 
Data is transmitted in 17-byte packets (16 data, 1  checksum). All of the configuration fuctions were derived from the examples posted on HopeRF's product page:
Transmit Demo: http://www.hoperf.com/upfile/RFM22_transmit_DEMO.pdf
Receive Demo: http://www.hoperf.com/upfile/RFM22_receive_DEMO.pdf
In testing, with a 17cm wire attached to the ANT pin, I got the modules to transmit about 150ft away from eachother, down a hallway. YMMV. I'd love to hear if you got it further!
There are a number of ways to configure and use these modules, and this example is by no means the best or only way to do so. 
I encourage you to try fiddling with the settings to   tune the RFM22 for best operation with your project.
All code is released under the Creative Commons Share-alike v3.0 license. Feel free to use it commercially or otherwise. 
If you have any adjustments to make to the code, I'd love  to  hear about them! Drop me an email (jim@sparkfun.com).
Cheers!
-Jim


This is the Receive code, placed here for an easy reference. Transmit code in zip file above

/*
   Created on: Mar. 30, 2010
	Under project: RFM22
	Author: Jim Lindblom
	RFM22 Receive Example
	
	Hardware: Arduino Pro (ATmega328) running at 8Mhz, 3.3V
	Wiring:
	RFM22 BOB	|	Arduino Pro
	----------------------------
		GND		|	GND
		3.3V	|	3.3V
		GPIO0	|	NC
		GPIO1	|	NC
		GPIO2	|	NC
		RXANT	|	PD6 (D6)
		TXANT	|	PD5 (D5)
		IRQ		|	PD4 (D4)
		CSN		|	PB0 (D8)
		SCK		|	PB4 (D13)
		SDI		|	PB2 (D11)
		SDO		|	PB3 (D12)
		
	Antenna is a 17cm piece of wire sticking straight up into the air.
*/

//======================//
//======================//
#include <avr/io.h>
#include <stdio.h>
#include "RFM22.h"
//======================//
//======================//

#define sbi(var, mask)   ((var) |= (uint8_t)(1 << mask))
#define cbi(var, mask)   ((var) &= (uint8_t)~(1 << mask))

//======================//
//Arduino Pro Specific Defines
#define LED 5

//RFM22 Defines
#define CS 0 //pin for chip select
#define TXANT 5	// PD5
#define RXANT 6	// PD6
#define NIRQ 4	// PD4

//======================//
//======================//

void ioinit(void);
void delay_ms(uint16_t x);
void delay_us(uint16_t x);

//======================//
//======================//

static int uart_putchar(char c, FILE *stream);
uint8_t uart_getchar(void);
static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);

//======================//
//======================//

void init_SPI(void);
void init_RFM22(void);
void to_rx_mode(void);
void rx_reset(void);
void checkINT(void);
void txdata(char data);
char rxdata(void);
char read(uint8_t address);
void write(uint8_t address, char data);

//======================//
//Global Variables
unsigned char RF_RXBUF[35];

int main(void)
{
	unsigned char i, chksum;

	ioinit();
	init_SPI();
	sbi(PORTB,CS);
	printf("********RFM22 Communication Test********\n");

	//====================//
	//Communications Test
	printf("Reading DTYPE register, should be 0x08: %d", read(DTYPE));
	
	printf("\n*****************************************\n\n");
	
	init_RFM22();	// Initialize all RFM22 registers
	printf("Entering RX Mode...\n");
	to_rx_mode();
	
	while(1)
	{
		if((PIND & (1<<NIRQ)) == 0)	//Interrupt will be generated if data is recieved
		{
			// Read 18-byte packet into RF_RXBUF[]:
			for(i=0; i<17; i++)
			{
				RF_RXBUF[i] = read(0x7F);
			}
			
			// Check that the checksum matches up:
			chksum = 0;
			for(i=0; i<16; i++)
				chksum += RF_RXBUF[i];
		
			// If checksum is good, print out what was received into the terminal
			if(chksum == RF_RXBUF[16])
			{
  				write(0x07, 0x01);	// To ready mode
 				printf("Received: ");
 				for(i=0; i<17; i++)
 					printf("%c", RF_RXBUF[i]);	// Print characters if passed the checksum
 				printf("\n");
 				//printf("To Ready mode\n");
 			}
 			// otherwise reset and start listening again
			else
			{
				rx_reset();
				//printf("Bad checksum RX RESET...Listening again\n");
			}
			delay_ms(50);
		}
	}
 }

// Initialize the RFM22 for transmitting
void init_RFM22(void)
{
	write(INTEN2, 0x00);	// Disable all interrupts
	write(OMFC1, 0x01);		// Set READY mode
	write(0x09, 0x7F);		// Cap = 12.5pF
	write(0x0A, 0x05);		// Clk output is 2MHz
	
	write(0x0B, 0xF4);		// GPIO0 is for RX data output
	write(0x0C, 0xEF);		// GPIO1 is TX/RX data CLK output
	write(0x0D, 0x00);		// GPIO2 for MCLK output
	write(0x0E, 0x00);		// GPIO port use default value
	
	write(0x0F, 0x70);		// NO ADC used
	write(0x10, 0x00);		// no ADC used
	write(0x12, 0x00);		// No temp sensor used
	write(0x13, 0x00);		// no temp sensor used
	
	write(0x70, 0x20);		// No manchester code, no data whiting, data rate < 30Kbps
	
	write(0x1C, 0x1D);		// IF filter bandwidth
	write(0x1D, 0x40);		// AFC Loop
	//write(0x1E, 0x0A);	// AFC timing
	
	write(0x20, 0xA1);		// clock recovery
	write(0x21, 0x20);		// clock recovery
	write(0x22, 0x4E);		// clock recovery
	write(0x23, 0xA5);		// clock recovery
	write(0x24, 0x00);		// clock recovery timing
	write(0x25, 0x0A);		// clock recovery timing
	
	//write(0x2A, 0x18);
	write(0x2C, 0x00);
	write(0x2D, 0x00);
	write(0x2E, 0x00);
	
	write(0x6E, 0x27);		// TX data rate 1
	write(0x6F, 0x52);		// TX data rate 0
	
	write(0x30, 0x8C);		// Data access control
	
	write(0x32, 0xFF);		// Header control
	
	write(0x33, 0x42);		// Header 3, 2, 1, 0 used for head length, fixed packet length, synchronize word length 3, 2,
	
	write(0x34, 64);		// 64 nibble = 32 byte preamble
	write(0x35, 0x20);		// 0x35 need to detect 20bit preamble
	write(0x36, 0x2D);		// synchronize word
	write(0x37, 0xD4);
	write(0x38, 0x00);
	write(0x39, 0x00);
	write(0x3A, 's');		// set tx header 3
	write(0x3B, 'o');		// set tx header 2
	write(0x3C, 'n');		// set tx header 1
	write(0x3D, 'g');		// set tx header 0
	write(0x3E, 17);		// set packet length to 17 bytes
	
	write(0x3F, 's');		// set rx header
	write(0x40, 'o');
	write(0x41, 'n');
	write(0x42, 'g');
	write(0x43, 0xFF);		// check all bits
	write(0x44, 0xFF);		// Check all bits
	write(0x45, 0xFF);		// check all bits
	write(0x46, 0xFF);		// Check all bits
	
	write(0x56, 0x01);
	
	write(0x6D, 0x07);		// Tx power to max
	
	write(0x79, 0x00);		// no frequency hopping
	write(0x7A, 0x00);		// no frequency hopping
	
	write(0x71, 0x22);		// GFSK, fd[8]=0, no invert for TX/RX data, FIFO mode, txclk-->gpio
	
	write(0x72, 0x48);		// Frequency deviation setting to 45K=72*625
	
	write(0x73, 0x00);		// No frequency offset
	write(0x74, 0x00);		// No frequency offset
	
	write(0x75, 0x53);		// frequency set to 434MHz
	write(0x76, 0x64);		// frequency set to 434MHz
	write(0x77, 0x00);		// frequency set to 434Mhz
	
	write(0x5A, 0x7F);
	write(0x59, 0x40);
	write(0x58, 0x80);
	
	write(0x6A, 0x0B);
	write(0x68, 0x04);
	write(0x1F, 0x03);
}

void to_rx_mode(void)
{
 	write(0x07, 0x01);	// to ready mode
	
	sbi(PORTD, RXANT);
	cbi(PORTD, TXANT);
	delay_ms(50);
	rx_reset();
}

void rx_reset(void)
{
	unsigned char i;
	
	write(0x07, 0x01);	// to ready mode
	
	i = read(0x03);
	i = read(0x04);
	
	write(0x7E, 17);
	
	write(0x08, 0x03);
	write(0x08, 0x00);
	
	write(0x07, 5);
	
	write(0x05, 2);
}

void checkINT(void)
{
	if ((PIND & (1<<NIRQ)) == 0)
		printf("INT == 0\n");
	else
		printf("INT == 1\n");
}

void write(uint8_t address, char data)
{
	//write any data byte to any single address
	//adds a 0 to the MSB of the address byte (WRITE mode)
	
	address |= 0x80;

	cbi(PORTB,CS);
	delay_ms(1);
	txdata(address);
	delay_ms(1);
	txdata(data);
	delay_ms(1);
	sbi(PORTB,CS);
}

char read(uint8_t address)
{
	//returns the contents of any 1 byte register from any address
	//sets the MSB for every address byte (READ mode)

	char byte;

	address &= 0x7F;

	cbi(PORTB,CS);
	txdata(address);
	byte = rxdata();
	sbi(PORTB,CS);

	return byte;
}

char rxdata(void)
{
	SPDR = 0x55;
	while((SPSR&0x80) == 0x00);

	return SPDR;
}

void txdata(char data)
{
	SPDR = data;
	while((SPSR&0x80) == 0x00);
}

void init_SPI(void)
{
	// enable SPI
	// make SPI master
	// SCLK idle low
	// sample data on rising edge
	// SPCR |= 0b01010011;	// SPIclk = FOSC/128
	SPCR |= 0b01010000;	// SPIclk = Fosc/4
}

static int uart_putchar(char c, FILE *stream)
{
    if (c == '\n') uart_putchar('\r', stream);

    loop_until_bit_is_set(UCSR0A, UDRE0);
    UDR0 = c;

    return 0;
}

uint8_t uart_getchar(void)
{
    while( !(UCSR0A & (1<<RXC0)) );
    return(UDR0);
}


void ioinit (void)
{
    //1 = output, 0 = input
   DDRB = 0b11101111; //MISO input
   DDRC = 0b11111111; //All outputs
   DDRD = 0b11101110; //PORTD (RX on PD0), PD4 input
	stdout = &mystdout; //Required for printf init
	int MYUBRR = 103;
	UBRR0H = (MYUBRR) >> 8;
	UBRR0L = MYUBRR;
	UCSR0B = (1<<RXEN0)|(1<<TXEN0);
	UCSR0C = (3<<UCSZ00);
 	UCSR0A = (1<<U2X0);

	TCCR2B = (1<<CS21);
	
	cbi(PORTD, TXANT);
	cbi(PORTD, RXANT);
}

//General short delays
void delay_ms(uint16_t x)
{
    for (; x > 0 ; x--)
        delay_us(1000);
}

//General short delays
void delay_us(uint16_t x)
{
    while(x > 256)
    {
        TIFR2 = (1<<TOV2); //Clear any interrupt flags on Timer2
        TCNT2 = 0; //256 - 125 = 131 : Preload timer 2 for x clicks. Should be 1us per click
        while( (TIFR2 & (1<<TOV2)) == 0);

        x -= 256;
    }

    TIFR2 = (1<<TOV2); //Clear any interrupt flags on Timer2
    TCNT2= 256 - x; //256 - 125 = 131 : Preload timer 2 for x clicks. Should be 1us per click
    while( (TIFR2 & (1<<TOV2)) == 0);
}









[[Category:]]