SparkFun Forums 

Where electronics enthusiasts find answers.

Your source for all things Atmel.
#38237
I am having trouble getting my MCU to communicate with the nRF24L01. I attached a copy of my board schematic and all of my code. Here are the things I am absolutely sure of:

The MCU is working properly. I can send and receive bytes just fine over the USART, which leads me to my next fact: the USART is working fine. The LED connected to PORTC also works like it should, so the only feature on the board currently not functioning is the nRF24L01.

Essentially what I am trying to do is set a value in a register and then read it back out. I am just doing this to make sure it works and try something very basic, but so far it doesn't read out the correct value.

You will see in main I am trying to write the value 0x03 into the EN_AA register (register 0x01). I am then trying to read it out and simply transmit the byte (in binary form for debugging) to my PC over the USART.

"00000000" comes up in hyperterminal regardless of what I send over SPI. I'm not sure if my functions are wrong or if I'm not setting up the nRF24L01 correctly. I'll go ahead and say I'm not sure if I need to write to the config register first (I tried that - no luck).

Any ideas? Thanks ahead of time.


Top level C file with main and most functions
Code: Select all
#include <avr/io.h>
#include <util/delay.h>
#include "USART.h"

//Clock is 16MHz

void CSN_high(void);                   //Drive the CSN line high
void CSN_low(void);                    //Drive the CSN line low
void SPI_Send(unsigned char);     //Send a byte over SPI
unsigned char SPI_Receive(void); //Receive a byte over SPI
void To_PC(unsigned char);          //Send a byte in binary format over USART
void SPI_Init(void);                      //Init SPI
void Init(void);                             //Init the MCU

//24L01 Defines
#define CE   6   //PORTA 6
#define CSN 5   //PORTA 5
#define IRQ  4   //PORTA 4

//LED Define (active low)
#define LED 4	//PORTC 4


int main(void)
{
	unsigned char ch;                //Dummy storage variable
	
	Init();                                 //Init the MCU
	
	USART0_Transmit('\n');       //Send CRLF pair over USART
	USART0_Transmit('\r');

	CSN_high();                       //Drive CSN high

	while(1)
	{
		CSN_low();                //Pull CSN low to transmit a command

		SPI_Send(0x21);       //Write to the EN_AA register
		SPI_Send(0x03);       //Turn on AA on Pipe 0 & 1

		CSN_high();              //Signal end of command

		CSN_low();               //Signal new command

		SPI_Send(0x01);	      //Issue read command for EN_AA register
		ch = SPI_Receive();  //Receive the byte (send dummy byte)

		CSN_high();              //Signal end of command

		To_PC(ch);                //Send the character over USART in binary

		USART0_Receive();    //Dummy receive to pause the program
	}

	return 0;
}

void Init(void)
{
	//Only the LED is on PORTC. Set it as output and turn it off.
	PORTC = 0xFF;
	DDRC  = 0xFF;

	//24L01 control signals CE, CSN, and IRQ on PORTA.
	//Set CE and CSN as output and IRQ as input
	PORTA = 0xEF;
	DDRA  = 0xEF;

	USART0_Init();
	SPI_Init();
}

//Convert a byte to binary over USART. This is just for debugging.
void To_PC(unsigned char ch)
{
	if(ch & 0x80)
		USART0_Transmit('1');
	else
		USART0_Transmit('0');

	if(ch & 0x40)
		USART0_Transmit('1');
	else
		USART0_Transmit('0');

	if(ch & 0x20)
		USART0_Transmit('1');
	else
		USART0_Transmit('0');

	if(ch & 0x10)
		USART0_Transmit('1');
	else
		USART0_Transmit('0');

	if(ch & 0x08)
		USART0_Transmit('1');
	else
		USART0_Transmit('0');

	if(ch & 0x04)
		USART0_Transmit('1');
	else
		USART0_Transmit('0');

	if(ch & 0x02)
		USART0_Transmit('1');
	else
		USART0_Transmit('0');

	if(ch & 0x01)
		USART0_Transmit('1');
	else
		USART0_Transmit('0');
	
	USART0_Transmit('\n');
	USART0_Transmit('\r');
}

void SPI_Send(unsigned char ch)
{
	SPDR = ch;						//Load the data register
	
	while( !(SPSR & (1 << SPIF)) ); //Wait for it to finish sending
}

unsigned char SPI_Receive(void)
{
	
	SPI_Send(0x05);					//Load with a dummy value
	return SPDR;					//Return the received byte
}

void CSN_high(void)
{
	PORTA |= (1 << CSN);			//Pull up PORTA Bit 5
}

void CSN_low(void)
{
	PORTA &= ~(1 << CSN);			//Pull down PORTA Bit 5
}

void SPI_Init(void)
{
	PORTB = 0xFF;
	DDRB  = 0xBF;					//SCK and MOSI are outputs, MISO is input
	
	//Turn on SPI, enable Master mode, Use clk/16. MSB first
	SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0) | (1 << DORD);
}

USART.c - a file I have used several times so I am positive this is working
Code: Select all
#include "USART.h"

void USART0_Init( )
{
	UBRR0H = (unsigned char)(BAUD0 >> 8);	//Set baud rate
	UBRR0L = (unsigned char)(BAUD0);
	
	//Enable receiver and transmitter
	UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
	UCSR0C = (0 << USBS0) | (3 << UCSZ00);	//Set frame format: 8data, 2stop bit
}


char USART0_Receive( void )
{
	while ( !(UCSR0A & (1 << RXC0)) );	// Wait for data to be received 
	return UDR0;						// Get and return received data from buffer 
}

void USART0_Transmit( unsigned char data )
{
	while ( !( UCSR0A & (1 << UDRE0)) );// Wait for empty transmit buffer
	UDR0 = data;						// Put data into buffer, sends the data
}

void USART0_Transmit_ptr( unsigned char data[])
{
	unsigned char j = 0;
	while(data[j] != '\0')
	{
		USART0_Transmit( data[j] );
		j++;
	}
}
[/code]
By Lajon
#38250
Code: Select all
   //Turn on SPI, enable Master mode, Use clk/16. MSB first 
   SPCR = (1 << SPE) | (1 << MSTR) | (1 << SPR0) | (1 << DORD); 
The DORD setting does not match your comment, i.e., you are setting up for LSB first.

BTW, brennen has made tutorials and code for the RF24L01, might be easier to start with that:
http://www.diyembedded.com/
/Lars
By mrdudeman
#38252
Yay!! The DORD bit was throwing me off!

It must have been very late when I typed that in because I actually remember reading the datasheet and thinking "Ah, I am supposed to set DORD for MSB first!" :oops:

Hyperterminal just returned a nice "00000011" to me...yay!!!

Thanks!
By stevech
#38258
To send binary on the USART, it's easier if you either
1) use the USART in 8 bit mode and a terminal program on the PC side in the 8 bit mode, displaying in hex. I like the Bray's 1.9b terminal program
http://www.hw-server.com/software/termv ... l#download

If you must use 7 bit UART modes, n the AVR, you can send a byte as two hexadecimal ASCII characters like 9F instead of binary digits in ASCII 10011111.

Here's an AVR project using the same Tx/Rx radios:

http://www.avrfreaks.net/index.php?modu ... pe=project
By mrdudeman
#38296
I don't want to fiddle with settings in a terminal program to have it show me the output I want. I want to show ASCII characters and binary at will. I'm not too concerned with wasting 1-2mS.

Also, I'm using 8 bit mode, so I'm not sure what you are talking about with the 7 bit mode comment. I don't want it to display in hex - I want it in binary. The If/else structure works perfectly fine and it took me 5 seconds to code it.
By stevech
#38341
mrdudeman wrote:I The If/else structure works perfectly fine and it took me 5 seconds to code it.
That's pretty quick!

The (free) Bray's terminal program enables you to choose the display mode:
ASCII
HEX
Decimal
BINARY

Lots of other useful features too.