Hi,
I’ve developed a custom mini-board containing an ATMEGA328P with internal RC oscillator and a HopeRF RFM22B wireless module. I’m currently doing some communication tests with the idea of developing an Arduino library for this module. Using the Arduino IDE, I’ve coded a very basic program that tries to read and write RFM22B’s registers via SPI at different addresses. My board is hooked to an USB/UART converter so I can debug the SPI comms anytime from minicom (Linux).
This is my current code:
/*
* Testing comms between ATMEGA328P and RFM22B module
*/
#define RFM_OFF 9 // PB1 = RFM_OFF
#define RFM_IRQ 2 // PD2 (INT0) = RFM_IRQ
#define SPI_SS 10 // PB2 = SPI_SS
#define SPI_MOSI 11
#define SPI_MISO 12
#define SPI_SCK 13
#define PORT_SPI_SS PORTB
#define BIT_SPI_SS 2
// SPI initialization
static void spi_Init()
{
digitalWrite(SPI_SS, HIGH);
// Configure SPI pins
pinMode(SPI_SS, OUTPUT);
pinMode(SPI_MOSI, OUTPUT);
pinMode(SPI_MISO, INPUT);
pinMode(SPI_SCK, OUTPUT);
// SPI speed = clk/4
SPCR = _BV(SPE) | _BV(MSTR);
}
// RFM22 initialization
void rfm22_Init()
{
byte value;
uint16_t res;
// Condifure pins
pinMode(RFM_IRQ, INPUT);
digitalWrite(RFM_IRQ, HIGH); // enable pull-up
digitalWrite(RFM_OFF, HIGH); // switch RFM off
pinMode(RFM_OFF, OUTPUT);
delay(1000);
digitalWrite(RFM_OFF, LOW); // switch RFM on
delay(1000);
// The following command should return 0x06 (Device version) but is returning 0x08 (Device Type, reg 0x00)
value = spi_readReg(0x01);
Serial.print("Reg 0x01 = ");
Serial.println(value, HEX);
}
// SPI - Write value at a given register address
static void spi_writeReg(byte regAddr, byte value)
{
bitClear(PORT_SPI_SS, BIT_SPI_SS); // SPI_SS = 0 (Select RFM22B module)
delay(1);
regAddr |= 0x80; // Set MSB: write mode
SPDR = regAddr;
while (!(SPSR & _BV(SPIF)))
;
SPDR = value;
while (!(SPSR & _BV(SPIF)))
;
delay(1);
bitSet(PORT_SPI_SS, BIT_SPI_SS); // SPI_SS = 1 (Unselect RFM22B module)
}
// SPI - Read value from a given register address
static byte spi_readReg(byte regAddr)
{
byte value;
regAddr &= 0x7F; // Clear MSB: read mode
bitClear(PORT_SPI_SS, BIT_SPI_SS); // SPI_SS = 0 (Select RFM22B module)
delay(1);
SPDR = regAddr;
while (!(SPSR & _BV(SPIF)))
;
SPDR = 0xFF;
while (!(SPSR & _BV(SPIF)))
;
value = SPDR;
delay(1);
bitSet(PORT_SPI_SS, BIT_SPI_SS); // SPI_SS = 1 (Unselect RFM22B module)
return value;
}
// Setup function
void setup()
{
Serial.begin(9600);
spi_Init();
rfm22_Init();
}
// Main loop
void loop()
{
}
The following command taken from the above code
value = spi_readReg(0x01)
should return the contents of the RFM22 register with address 0x01. However, whatever address I try to read, the RFM module always return the value of the first register (addr = 0x00). I’ve even done some bulk reads starting from different addresses but the result is always the same: a list with the default register values starting from 0x00.
It seems like the RFM22 is not able to understand the address sent by the master. I’d tend to think that this could be due to the inaccuracy of the internal RC oscillator but SPI comms share the same clk line at both ends so this can not be the reason. On the other hand, I’ve tried with lower SPI speeds (clk/16, clk/64) without success.
I’ve looked into some examples found in the net for PIC’s, (even HopeRF’s) but they don’t seem to explain the behaviour of my board. Maybe some of the HopeRF users around herehave a better idea about how to focus this problem.
Thanks in advance for your help,
Daniel.
P.S: Congratulations to Sparkfun for their great website and forums.