Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[PIC] PIC16F886 + nRF24L01 (SPI)

Status
Not open for further replies.

megacrypto

Junior Member level 2
Joined
Sep 21, 2009
Messages
20
Helped
5
Reputation
10
Reaction score
5
Trophy points
1,283
Activity points
1,425
Been working on this for months now, learning from scratch all about programming in C, MCUs, SPI, Registers, and now the nRF24 module. I looked at hundreds of codes (I learn through trial and error - get a working code then learn about every part about it by trying things here and there). I finally got to get the SPI working to communicate between the 2 PIC16F886 (code in XC8), and that was my first step (posted my result in https://www.edaboard.com/threads/324784/)

My objective has been always to get the nRF24 working (i want to play around with light control, curtains, ect.). This is the most I got so far (and I have been honestly through every single code & article there is out there for the nRF24L01 and PICs (most of them are for the PIC18's and many are in CCS).

Anyways, this is how far I got:

My SPI files:

spi.h
Code:
#ifndef SPI_H
#define	SPI_H

#ifdef	__cplusplus
extern "C" {
#endif

void SPI_Init();
unsigned char SPI_Send(unsigned char data);



#ifdef	__cplusplus
}
#endif

#endif	/* SPI_H */

spi.c
Code:
#include <xc.h>
#include "spi.h"

void SPI_Init()
{
//    INTCON = 0;         // Disable all interrupts

    TRISC3 = 0;         // SCK=RC3 is the serial clock
    TRISC4 = 1;         // SDI=RC4 is serial data input
    TRISC5 = 0;         // SDO=RC5 is serial data output

    SMP = 0;            // Input data sampled at middle data output time
    CKP = 1;            // Idle state for clock is a high level
    CKE = 0;            // Transmit occurs on idle to active clock state

    SSPEN = 1;          // Enables serial port
    SSPIF = 0;

    SSPM3 = 0;          //
    SSPM2 = 0;          //
    SSPM1 = 0;          //
    SSPM0 = 1;          // SPI Master mode, clock = FOSC/16

}

unsigned char SPI_Send(unsigned char data)
{
    SSPBUF = data;          // Put command into SPI buffer
    while (!BF);            // Wait for the transfer to finish
    return SSPBUF;          // Save the read value
}

and these work (they are the ones I used for the master PIC in the above link when directly connected the two PICs via SPI) and I know that with the nRF the PIC is the master and the nRF is the slave, so I used the same files for both PICs connected to the nRF modules.

Now this is where I have been stuck for the last months. This is the code for the TX side:

main.c (TX):
Code:
#include <xc.h>

// CONFIG1
#pragma config FOSC = INTRC_NOCLKOUT, WDTE = OFF, PWRTE = OFF, MCLRE = OFF
#pragma config CP = OFF, CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
#pragma config LVP = OFF, DEBUG = OFF
// CONFIG2
#pragma config BOR4V = BOR40V, WRT = OFF

// Set Clock Freq. & Delays
#ifndef _XTAL_FREQ
    #define _XTAL_FREQ 8000000
    #define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/8000000.0)))
    #define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/8000.0)))
#endif

#include "spi.h"

void Init(void);
void transmit_data(void);
void configure_transmitter(void);
unsigned char spi1_send_read_byte(unsigned char byte);

// Defines
#define SPI_SCK		RC3		// Clock pin, PORTC pin 3
#define SPI_SO		RC5		// Serial output pin, PORTC pin 5
#define SPI_SI		RC4		// Serial input pin, PORTC pin 4
#define SPI_CSN		RC2		// CSN output pin, PORTC pin 2
#define SPI_CE		RC1		// CE output pin, PORTC pin 1
#define SPI_IRQ		RB0		// IRQ input pin, PORTB pin 0
#define SPI_SCALE	4               // postscaling of signal
#define LED		RA0
#define PB		RA1

void main(){
    Init();
    SPI_Init();
    configure_transmitter();

    while(1){
        transmit_data();
        LED = 1;
        __delay_ms(200);			//200 ms delay
        LED = 0;
        __delay_ms(3270);			//3.27 s delay
    }
}

void Init(void)
{
	PORTA = 0x00;
	ADCON1 = 0x0F;		// set up PORTA to be digital I/Os
	TRISA = 0x02;		// PORTA<7.2,0> outputs PORTA<1> input
	TRISBbits.TRISB0 = 1;	// IRQ input
	TRISCbits.TRISC1 = 0;	// CE output
	TRISCbits.TRISC2 = 0;	// CSN output
}

void configure_transmitter(void)
{
    unsigned char i, j, data, cmd;

    SPI_CE = 0;
    SPI_CSN = 0;

	// PTX, CRC enabled, mask a couple of ints
 	SPI_Send(0x20);
  	SPI_Send(0x38);
	SPI_CSN = 1;
    SPI_CSN = 0;

	//auto retransmit off
 	SPI_Send(0x24);
   	SPI_Send(0x00);
    SPI_CSN = 1;
    SPI_CSN = 0;

	//address width = 5
   	SPI_Send(0x23);
 	SPI_Send(0x03);
    SPI_CSN = 1;
    SPI_CSN = 0;

	//data rate = 1MB
   	SPI_Send(0x26);
 	SPI_Send(0x07);
    SPI_CSN = 1;
    SPI_CSN = 0;

	//set channel 2, this is default but we did it anyway...
   	SPI_Send(0x25);
 	SPI_Send(0x02);
    SPI_CSN = 1;
    SPI_CSN = 0;

	//set address E7E7E7E7E7, also default...
   	SPI_Send(0x30);
    for (j = 0; j < 5; j++)
    {
        SPI_Send(0xE7);
    }
    SPI_CSN = 1;
    SPI_CSN = 0;

    //disable auto-ack, RX mode
    //shouldn't have to do this, but it won't TX if you don't
   	SPI_Send(0x21);
 	SPI_Send(0x00);
    SPI_CSN = 1;
}

void transmit_data(void)
{
    unsigned char i, data, cmd;

    SPI_CSN = 0;

    //clear previous ints
    SPI_Send(0x27);
    SPI_Send(0x7E);
    SPI_CSN = 1;
    SPI_CSN = 0;

    //PWR_UP = 1
    SPI_Send(0x20);
    SPI_Send(0x3A);
    SPI_CSN = 1;
    SPI_CSN = 0;

    //clear TX fifo
    //the data sheet says that this is supposed to come up 0 after POR, but that doesn't seem to be the case
    SPI_Send(0xE1);
    SPI_CSN = 1;
    SPI_CSN = 0;

    //4 byte payload
    SPI_Send(0xA0);
    SPI_Send(0x34);
    SPI_Send(0x33);
    SPI_Send(0x32);
    SPI_Send(0x31);
    SPI_CSN = 1;

    //Pulse CE to start transmission
    SPI_CE = 1;
    __delay_ms(69);			//delay 69 ms
    SPI_CE = 0;
}

and this is the main.c (RX) side:
Code:
#include <xc.h>

// CONFIG1
#pragma config FOSC = INTRC_NOCLKOUT, WDTE = OFF, PWRTE = OFF, MCLRE = OFF
#pragma config CP = OFF, CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
#pragma config LVP = OFF, DEBUG = OFF
// CONFIG2
#pragma config BOR4V = BOR40V, WRT = OFF

// Set Clock Freq. & Delays
#ifndef _XTAL_FREQ
    #define _XTAL_FREQ 8000000
    #define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/8000000.0)))
    #define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/8000.0)))
#endif

#include "spi.h"

void Init(void);
void reset_RX(void);
void configure_RX(void);

// Defines
#define SPI_SCK		RC3		// Clock pin, PORTC pin 3
#define SPI_SO		RC5		// Serial output pin, PORTC pin 5
#define SPI_SI		RC4		// Serial input pin, PORTC pin 4
#define SPI_CSN		RC2		// CSN output pin, PORTC pin 2
#define SPI_CE		RC1		// CE output pin, PORTC pin 1
#define SPI_IRQ		RB0		// IRQ input pin, PORTB pin 0
#define SPI_SCALE	4               // postscaling of signal
#define LED		RA0
#define PB		RA1

void main(){
    Init();
    SPI_Init();
    configure_RX();
    unsigned char i;

    while(1){
        if (SPI_IRQ == 0)    //wait for anything
        {
            for (i = 0; i < 5; i++)  //flash LED 5 times if data received
            {
                LED = 1;
                __delay_ms(200);		// 200 ms delay
                LED = 0;
                __delay_ms(196);		// 196 ms
            }
            __delay_ms(196);			// 196 ms
            reset_RX();
        }
    }
}

void Init(void)
{
	PORTA = 0x00;
	ADCON1 = 0x0F;		// set up PORTA to be digital I/Os
	TRISA = 0x02;		// PORTA<7.2,0> outputs PORTA<1> input
	TRISBbits.TRISB0 = 1;	// IRQ input
	TRISCbits.TRISC1 = 0;	// CE output
	TRISCbits.TRISC2 = 0;	// CSN output
}

//configure nRF24L01 for receive
void configure_RX(void)
{
    unsigned char i, j;

    SPI_CSN = 0;
    SPI_CE = 0;

    //PRX, CRC enabled
    SPI_Send(0x20);
    SPI_Send(0x39);
    SPI_CSN = 1;
    SPI_CSN = 0;

    //disable auto-ack for all channels
    SPI_Send(0x21);
    SPI_Send(0x00);
    SPI_CSN = 1;
    SPI_CSN = 0;

    //address width = 5 bytes
    SPI_Send(0x23);
    SPI_Send(0x03);
    SPI_CSN = 1;
    SPI_CSN = 0;

    //data rate = 1MB
    SPI_Send(0x26);
    SPI_Send(0x07);
    SPI_CSN = 1;
    SPI_CSN = 0;

    //4 byte payload
    SPI_Send(0x31);
    SPI_Send(0x04);
    SPI_CSN = 1;
    SPI_CSN = 0;

    //set channel 2
    SPI_Send(0x25);
    SPI_Send(0x02);
    SPI_CSN = 1;
    SPI_CSN = 0;

    //set address E7E7E7E7E7
    SPI_Send(0x30);
    for (j = 0; j < 5; j++)
	SPI_Send(0xE7);
    SPI_CSN = 1;
    SPI_CSN = 0;

    //PWR_UP = 1
    SPI_Send(0x20);
    SPI_Send(0x3B);
    SPI_CSN = 1;
    SPI_CE = 1;
}

void reset_RX(void)
{
    unsigned char i, j;
    unsigned char buffer[4];

    //Read RX payload
    SPI_CSN = 0;
    SPI_Send(0x61);
    for (j = 0; j < 4; j++)
    {
        buffer[j] = SPI_Send(0);
    }
    SPI_CSN = 1;

    //Flush RX FIFO
    SPI_CSN = 0;
    SPI_Send(0xE2);
    SPI_CSN = 1;
    SPI_CSN = 0;

    //reset int
    SPI_Send(0x27);
    SPI_Send(0x40);
    SPI_CSN = 1;
}

i truly would love to get this working and really would appreciate anyone who is willing to give the time to help me out here.

- - - Updated - - -

This is the original code I used, it was written for PIC18F4520 (maybe someone could tell me where I went wrong)

tx.c:
Code:
/*
** Tx.c
** Transmit test program for PIC18F4520 and nRF24L01 or nRF24L01+
** Uses the Microchip C18 compiler
** Based on SFE code for the CC5X compiler in 24L01demo_V01.c
*/

[B][COLOR="#0000FF"]#include <p18cxxx.h>
#include <spi.h>
#include <timers.h>[/COLOR][/B]

[B][COLOR="#FF0000"]// Pragmas
#pragma config OSC = INTIO67
#pragma config PWRT = ON
//#pragma config MCLRE = OFF
#pragma config BOREN = OFF[/COLOR][/B]


//function prototypes
void init(void);
void transmit_data(void);
void configure_transmitter(void);
[COLOR="#FF0000"][B]unsigned char spi_Send_Read(unsigned char);
unsigned char spi1_send_read_byte(unsigned char byte);
void dly(unsigned int);[/B][/COLOR]


// Defines
[COLOR="#0000FF"]#define SPI_SCK		LATCbits.LATC3		// Clock pin, PORTC pin 3 
#define SPI_SO		LATCbits.LATC5		// Serial output pin, PORTC pin 5 
#define SPI_SI		PORTCbits.RC4		// Serial input pin, PORTC pin 4 
#define SPI_CSN		LATCbits.LATC2		// CSN output pin, PORTC pin 2
#define SPI_CE		LATCbits.LATC1		// CE output pin, PORTC pin 1
#define SPI_IRQ		PORTBbits.RB0		// IRQ input pin, PORTB pin 0
#define SPI_SCALE	4              		// postscaling of signal 
#define LED			LATAbits.LATA0
#define PB			PORTAbits.RA1[/COLOR]

[COLOR="#FF0000"][B]// Macros
#define nop() _asm nop _endasm
[/B][/COLOR]
void main(void)
{
	init();
	configure_transmitter();  
	while (1)  
	{
		transmit_data();
		LED = 1;
		dly(63973);			//200 ms delay
		LED = 0;           
		dly(40000);			//3.27 s delay 
		nop();          
	}
}


void init(void)
{
[COLOR="#FF0000"][B]	// run internal oscillator at 8 MHz
	OSCCON = OSCCON | 0x70;
	while (OSCCONbits.IOFS == 0)
		;[/B][/COLOR]
[COLOR="#0000FF"]	PORTA = 0x00;
	ADCON1 = 0x0F;		// set up PORTA to be digital I/Os
	TRISA = 0x02;		// PORTA<7.2,0> outputs PORTA<1> input
	TRISCbits.TRISC3 = 0;	// SDO output
	TRISCbits.TRISC5 = 0;   // SCK output
	TRISCbits.TRISC2 = 0;	// CSN output
	TRISCbits.TRISC1 = 0;	// CE output
	TRISBbits.TRISB0 = 1;	// IRQ input[/COLOR]
[COLOR="#FF0000"][B]	OpenSPI(SPI_FOSC_16, MODE_00, SMPMID); //open SPI1
	OpenTimer0( TIMER_INT_OFF &
            	T0_16BIT &
            	T0_SOURCE_INT &
            	T0_PS_1_256 );[/B][/COLOR]
}

void configure_transmitter(void)
{
    unsigned char i, j, data, cmd;

    SPI_CE = 0;
    SPI_CSN = 0;

	// PTX, CRC enabled, mask a couple of ints    
 	spi_Send_Read(0x20);
  	spi_Send_Read(0x38);
	SPI_CSN = 1; 
    SPI_CSN = 0;
    
	//auto retransmit off
 	spi_Send_Read(0x24);    
   	spi_Send_Read(0x00);    
    SPI_CSN = 1;
    SPI_CSN = 0;
    
	//address width = 5
   	spi_Send_Read(0x23);
 	spi_Send_Read(0x03);    
    SPI_CSN = 1;
    SPI_CSN = 0;
    
	//data rate = 1MB
   	spi_Send_Read(0x26);
 	spi_Send_Read(0x07);
    SPI_CSN = 1; 
    SPI_CSN = 0;
    
	//set channel 2, this is default but we did it anyway...
   	spi_Send_Read(0x25);
 	spi_Send_Read(0x02);
    SPI_CSN = 1;
    SPI_CSN = 0;
    
	//set address E7E7E7E7E7, also default...
   	spi_Send_Read(0x30);    
    for (j = 0; j < 5; j++)
    {
        spi_Send_Read(0xE7);
    }  
    SPI_CSN = 1;
    SPI_CSN = 0;
    
    //disable auto-ack, RX mode
    //shouldn't have to do this, but it won't TX if you don't
   	spi_Send_Read(0x21);
 	spi_Send_Read(0x00);
    SPI_CSN = 1;
}

void transmit_data(void)
{
    unsigned char i, data, cmd;   
    
    SPI_CSN = 0;
    
	//clear previous ints
  	spi_Send_Read(0x27);
 	spi_Send_Read(0x7E);
	SPI_CSN = 1;
    SPI_CSN = 0;
    
	//PWR_UP = 1
   	spi_Send_Read(0x20);
 	spi_Send_Read(0x3A);
    SPI_CSN = 1;
    SPI_CSN = 0;
    
    //clear TX fifo
    //the data sheet says that this is supposed to come up 0 after POR, but that doesn't seem to be the case
   	spi_Send_Read(0xE1);
    SPI_CSN = 1;
    SPI_CSN = 0;
    
	//4 byte payload
   	spi_Send_Read(0xA0);
   	spi_Send_Read(0x34);
  	spi_Send_Read(0x33);
   	spi_Send_Read(0x32);
  	spi_Send_Read(0x31);
    SPI_CSN = 1;
    
    //Pulse CE to start transmission
    SPI_CE = 1;
    dly(65000);			//delay 69 ms
    SPI_CE = 0;
}


[COLOR="#FF0000"][B]unsigned char spi_Send_Read(unsigned char byte)
{
	SSPBUF = byte;	
	while(!DataRdySPI())
		;	
	return SSPBUF;
}	

void dly(unsigned int c)
{
	INTCONbits.TMR0IF = 0;
	WriteTimer0(c);
	while (INTCONbits.TMR0IF == 0)
		;
}[/B][/COLOR]

and this is the rx.c:
Code:
/*
** Rx.c
** Receive test program for PIC18F4520 and nRF24L01 or nRF24L01+
** Uses the Microchip C18 compiler
** Based on SFE code for the CC5X compiler in 24L01demo_V01.c
**
** The LED is flashed five times when data are received.
** The received data in the buffer may be checked using the 
** debugger Watch window.*/

#include <p18cxxx.h>
#include <spi.h>
#include <timers.h>

// Pragmas
#pragma config OSC = INTIO67
#pragma config PWRT = ON
#pragma config MCLRE = OFF
#pragma config BOREN = OFF

//function prototypes
void init(void);
void reset_RX(void);
void configure_RX(void);
unsigned char spi_Send_Read(unsigned char);
void dly(unsigned int);

// Defines
#define SPI_SCK		LATCbits.LATC3		// Clock pin, PORTC pin 3 
#define SPI_SO		LATCbits.LATC5		// Serial output pin, PORTC pin 5 
#define SPI_SI		PORTCbits.RC4		// Serial input pin, PORTC pin 4 
#define SPI_CSN		LATCbits.LATC2		// CSN output pin, PORTC pin 2
#define SPI_CE		LATCbits.LATC1		// CE output pin, PORTC pin 1
#define SPI_IRQ		PORTBbits.RB0		// IRQ input pin, PORTB pin 0
#define SPI_SCALE	4              		// postscaling of signal 
#define LED			LATAbits.LATA0
#define PB			PORTAbits.RA1

// Macros
#define nop() _asm nop _endasm

void main(void)
{
	unsigned char i;

	init();
	configure_RX();
	while(1)
	{
   		if (SPI_IRQ == 0)    //wait for anything
        {
            for (i = 0; i < 5; i++)  //flash LED 5 times if data received
            {
                LED = 1;
                dly(63973);		// 200 ms delay
                LED = 0;
                dly(63973);		// 196 ms
            }
            dly(63973);			// 196 ms
            reset_RX();            
        }
	}
}

// initialise 18F4520
void init(void)
{
	// run internal oscillator at 8 MHz
	OSCCON = OSCCON | 0x70;
	while (OSCCONbits.IOFS == 0)
		;

	PORTA = 0x00;
	ADCON1 = 0x0F;		// set up PORTA to be digital I/Os
	TRISA = 0x02;		// PORTA<7.2,0> outputs PORTA<1> input
	TRISCbits.TRISC3 = 0;	// SDO output
	TRISCbits.TRISC5 = 0;   // SCK output
	TRISCbits.TRISC2 = 0;	// CSN output
	TRISCbits.TRISC1 = 0;	// CE output
	TRISBbits.TRISB0 = 1;	// IRQ input
	OpenSPI(SPI_FOSC_16, MODE_00, SMPMID); //open SPI1
	OpenTimer0( TIMER_INT_OFF &
            	T0_16BIT &
            	T0_SOURCE_INT &
            	T0_PS_1_256 );
}

//configure nRF24L01 for receive
void configure_RX(void)
{
    unsigned char i, j;

    SPI_CSN = 0;
    SPI_CE = 0;
    
	//PRX, CRC enabled
	spi_Send_Read(0x20);
	spi_Send_Read(0x39); 
	SPI_CSN = 1;   
	SPI_CSN = 0;
    
	//disable auto-ack for all channels      
	spi_Send_Read(0x21);
	spi_Send_Read(0x00);     
	SPI_CSN = 1;    
	SPI_CSN = 0;
    
	//address width = 5 bytes  
  	spi_Send_Read(0x23);
	spi_Send_Read(0x03);    
    SPI_CSN = 1;    
    SPI_CSN = 0;
    
	//data rate = 1MB   
  	spi_Send_Read(0x26);
	spi_Send_Read(0x07);    
    SPI_CSN = 1;
  	SPI_CSN = 0;

	//4 byte payload  
 	spi_Send_Read(0x31);
	spi_Send_Read(0x04);    
    SPI_CSN = 1;    
    SPI_CSN = 0;

    //set channel 2 
   	spi_Send_Read(0x25);
	spi_Send_Read(0x02);    
    SPI_CSN = 1;     
    SPI_CSN = 0;

    //set address E7E7E7E7E7
    spi_Send_Read(0x30);
    for (j = 0; j < 5; j++)
 		spi_Send_Read(0xE7); 
    SPI_CSN = 1;  
    SPI_CSN = 0;
    
	//PWR_UP = 1   
 	spi_Send_Read(0x20);
	spi_Send_Read(0x3B);   
    SPI_CSN = 1;    
    SPI_CE = 1;     
}

void reset_RX(void)
{
    unsigned char i, j;
    unsigned char buffer[4];    
    
	//Read RX payload   
    SPI_CSN = 0;    
   	spi_Send_Read(0x61);    
    for (j = 0; j < 4; j++)
    {        
       	buffer[j] = spi_Send_Read(0);        
    }    
    SPI_CSN = 1;    
    
	//Flush RX FIFO    
    SPI_CSN = 0;    
 	spi_Send_Read(0xE2);    
    SPI_CSN = 1;
    SPI_CSN = 0;
 
	//reset int    
  	spi_Send_Read(0x27);
	spi_Send_Read(0x40);    
    SPI_CSN = 1;
}




unsigned char spi_Send_Read(unsigned char byte)
{
	SSPBUF = byte;	
	while(!DataRdySPI())
		;	
	return SSPBUF;
}	


void dly(unsigned int c)
{
	INTCONbits.TMR0IF = 0;
	WriteTimer0(c);
	while (INTCONbits.TMR0IF == 0)
		;


}

I changed (used) the SPI function that I made (and worked for communicating between the 2 PICs) and also the "dly" function I removed and used the delays I always use.

I balded the parts that I removed or changed
 

Just convert the Arduino C++ code to C code. I mean the Arduino Mirf and RF24 library codes to C and use it.
 

Just convert the Arduino C++ code to C code. I mean the Arduino Mirf and RF24 library codes to C and use it.

Dear Milan,

I looked at all the codes out there for Arduino, RasPi, PICs, Atmel, all of them, and for some reason , the logic of these libraries is not clicking in my brain (usually I'm good at looking at code and manipulating it) but with this nRF ... I'm blank.

What I need is someone to help me get a working code for the above (in the simplest form possible - I know the nRF libs out there vary in what functions of the nRF they implement) and then I know that I will be able to reverse the whole thing into pieces, but I truly need someone to help me with the code. As I said, I have been at this for months now and no progress !!!
 

Have you seen nRF24L01 library at libstock.com ?
 

Yes, that's the library. You can easily convert it to Hi-Tech C, C18 or XC8 code.
 

Yes, that's the library. You can easily convert it to Hi-Tech C, C18 or XC8 code.

As I mentioned, I looked at them and for some reason converting any of the codes is not working with me - and easy is a relative thing ;-)

I have been at this (if I put together all the hours I researched it) I would say 2 weeks now (that 14 x 24 hours .. that's 336 hours straight ... reminds me the first time I tried to get my Nexus-S DVB card to run on linux 10 years ago ... and that took a full week to get it running)
 
OK ... I found a new library (this one writte for AVR https://github.com/kehribar/nrf24L01_plus)

the nRF24L01.h I guess is the basic one found in many libraries:
Code:
/* Memory Map */
#define CONFIG      0x00
#define EN_AA       0x01
#define EN_RXADDR   0x02
#define SETUP_AW    0x03
#define SETUP_RETR  0x04
#define RF_CH       0x05
#define RF_SETUP    0x06
#define STATUS      0x07
#define OBSERVE_TX  0x08
#define CD          0x09
#define RX_ADDR_P0  0x0A
#define RX_ADDR_P1  0x0B
#define RX_ADDR_P2  0x0C
#define RX_ADDR_P3  0x0D
#define RX_ADDR_P4  0x0E
#define RX_ADDR_P5  0x0F
#define TX_ADDR     0x10
#define RX_PW_P0    0x11
#define RX_PW_P1    0x12
#define RX_PW_P2    0x13
#define RX_PW_P3    0x14
#define RX_PW_P4    0x15
#define RX_PW_P5    0x16
#define FIFO_STATUS 0x17
#define DYNPD       0x1C

/* Bit Mnemonics */

/* configuratio nregister */
#define MASK_RX_DR  6
#define MASK_TX_DS  5
#define MASK_MAX_RT 4
#define EN_CRC      3
#define CRCO        2
#define PWR_UP      1
#define PRIM_RX     0

/* enable auto acknowledgment */
#define ENAA_P5     5
#define ENAA_P4     4
#define ENAA_P3     3
#define ENAA_P2     2
#define ENAA_P1     1
#define ENAA_P0     0

/* enable rx addresses */
#define ERX_P5      5
#define ERX_P4      4
#define ERX_P3      3
#define ERX_P2      2
#define ERX_P1      1
#define ERX_P0      0

/* setup of address width */
#define AW          0 /* 2 bits */

/* setup of auto re-transmission */
#define ARD         4 /* 4 bits */
#define ARC         0 /* 4 bits */

/* RF setup register */
#define PLL_LOCK    4
#define RF_DR       3
#define RF_PWR      1 /* 2 bits */   

/* general status register */
#define RX_DR       6
#define TX_DS       5
#define MAX_RT      4
#define RX_P_NO     1 /* 3 bits */
#define TX_FULL     0

/* transmit observe register */
#define PLOS_CNT    4 /* 4 bits */
#define ARC_CNT     0 /* 4 bits */

/* fifo status */
#define TX_REUSE    6
#define FIFO_FULL   5
#define TX_EMPTY    4
#define RX_FULL     1
#define RX_EMPTY    0

/* dynamic length */
#define DPL_P0      0
#define DPL_P1      1
#define DPL_P2      2
#define DPL_P3      3
#define DPL_P4      4
#define DPL_P5      5

/* Instruction Mnemonics */
#define R_REGISTER    0x00 /* last 4 bits will indicate reg. address */
#define W_REGISTER    0x20 /* last 4 bits will indicate reg. address */
#define REGISTER_MASK 0x1F
#define R_RX_PAYLOAD  0x61
#define W_TX_PAYLOAD  0xA0
#define FLUSH_TX      0xE1
#define FLUSH_RX      0xE2
#define REUSE_TX_PL   0xE3
#define ACTIVATE      0x50 
#define R_RX_PL_WID   0x60
#define NOP           0xFF

now here is where it gets always tricky for me. This is my main.c
Code:
#include <xc.h>

// CONFIG1
#pragma config FOSC = INTRC_NOCLKOUT, WDTE = OFF, PWRTE = OFF, MCLRE = OFF
#pragma config CP = OFF, CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
#pragma config LVP = OFF, DEBUG = OFF
// CONFIG2
#pragma config BOR4V = BOR40V, WRT = OFF

// Set Clock Freq. & Delays
#ifndef _XTAL_FREQ
    #define _XTAL_FREQ 20000000
    #define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/20000000.0)))
    #define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/20000.0)))
#endif

#include "nrf24.h"

// Defines
#define LED		RA0
#define PB		RA1


void main(){

    int i;
    uint8_t temp;
    uint8_t q = 0;
    uint8_t data_array[4];
    uint8_t tx_address[5] = {0xE7,0xE7,0xE7,0xE7,0xE7};
    uint8_t rx_address[5] = {0xD7,0xD7,0xD7,0xD7,0xD7};

    ANSEL = 0;
    TRISA = 0;
    LED = 0;

    
    /* init hardware pins */
    nrf24_init();

    /* Set the device addresses */
    nrf24_tx_address(tx_address);
    nrf24_rx_address(rx_address);

    /* Channel #2 , payload length: 4 */
    nrf24_config(2,4);

    while(1){
        /* Fill the data buffer */
        data_array[0] = 0x00;
        data_array[1] = 0xAA;
        data_array[2] = 0x55;
        data_array[3] = q++;

        /* Automatically goes to TX mode */
        nrf24_send(data_array);

        /* Wait for transmission to end */
        while(nrf24_isSending());

        /* Make analysis on last tranmission attempt */
        temp = nrf24_lastMessageStatus();

        if(temp == NRF24_TRANSMISSON_OK)
        {
            for (i = 0; i < 5; i++)
            {
                LED = 1;
                __delay_ms(200);
                LED = 0;
                __delay_ms(200);
            }
//            xprintf("> Tranmission went OK\r\n");
        }
        else if(temp == NRF24_MESSAGE_LOST)
        {
/*
            for (i = 0; i < 10; i++)
            {
                LED = 1;
                __delay_ms(50);
                LED = 0;
                __delay_ms(50);
            }
//            xprintf("> Message is lost ...\r\n");
 */
        }

        /* Retranmission count indicates the tranmission quality */
        temp = nrf24_retransmissionCount();
//		xprintf("> Retranmission count: %d\r\n",temp);

        /* Optionally, go back to RX mode ... */
        nrf24_powerUpRx();

        /* Or you might want to power down after TX */
        // nrf24_powerDown();

        /* Wait a little ... */
        __delay_ms(10000);
    }
}

this is the nrf24.h
Code:
#ifndef NRF24
#define NRF24

#include "nRF24L01.h"
#include <stdint.h>

#define LOW 0
#define HIGH 1

#define nrf24_ADDR_LEN 5
#define nrf24_CONFIG ((1<<EN_CRC)|(0<<CRCO))

#define NRF24_TRANSMISSON_OK 0
#define NRF24_MESSAGE_LOST   1

/* adjustment functions */
void    nrf24_init();
void    nrf24_rx_address(uint8_t* adr);
void    nrf24_tx_address(uint8_t* adr);
void    nrf24_config(uint8_t channel, uint8_t pay_length);

/* state check functions */
uint8_t nrf24_dataReady();
uint8_t nrf24_isSending();
uint8_t nrf24_getStatus();
uint8_t nrf24_rxFifoEmpty();

/* core TX / RX functions */
void    nrf24_send(uint8_t* value);
void    nrf24_getData(uint8_t* data);

/* use in dynamic length mode */
uint8_t nrf24_payloadLength();

/* post transmission analysis */
uint8_t nrf24_lastMessageStatus();
uint8_t nrf24_retransmissionCount();

/* Returns the payload length */
uint8_t nrf24_payload_length();

/* power management */
void    nrf24_powerUpRx();
void    nrf24_powerUpTx();
void    nrf24_powerDown();

/* low level interface ... */
uint8_t spi_transfer(uint8_t tx);
void    nrf24_transmitSync(uint8_t* dataout,uint8_t len);
void    nrf24_transferSync(uint8_t* dataout,uint8_t* datain,uint8_t len);
void    nrf24_configRegister(uint8_t reg, uint8_t value);
void    nrf24_readRegister(uint8_t reg, uint8_t* value, uint8_t len);
void    nrf24_writeRegister(uint8_t reg, uint8_t* value, uint8_t len);

/* -------------------------------------------------------------------------- */
/* You should implement the platform spesific functions in your code */
/* -------------------------------------------------------------------------- */

/* -------------------------------------------------------------------------- */
/* In this function you should do the following things:
 *    - Set MISO pin input
 *    - Set MOSI pin output
 *    - Set SCK pin output
 *    - Set CSN pin output
 *    - Set CE pin output     */
/* -------------------------------------------------------------------------- */
extern void nrf24_setupPins();

/* -------------------------------------------------------------------------- */
/* nrf24 CE pin control function
 *    - state:1 => Pin HIGH
 *    - state:0 => Pin LOW     */
/* -------------------------------------------------------------------------- */
extern void nrf24_ce_digitalWrite(uint8_t state);

/* -------------------------------------------------------------------------- */
/* nrf24 CE pin control function
 *    - state:1 => Pin HIGH
 *    - state:0 => Pin LOW     */
/* -------------------------------------------------------------------------- */
extern void nrf24_csn_digitalWrite(uint8_t state);

/* -------------------------------------------------------------------------- */
/* nrf24 SCK pin control function
 *    - state:1 => Pin HIGH
 *    - state:0 => Pin LOW     */
/* -------------------------------------------------------------------------- */
extern void nrf24_sck_digitalWrite(uint8_t state);

/* -------------------------------------------------------------------------- */
/* nrf24 MOSI pin control function
 *    - state:1 => Pin HIGH
 *    - state:0 => Pin LOW     */
/* -------------------------------------------------------------------------- */
extern void nrf24_mosi_digitalWrite(uint8_t state);

/* -------------------------------------------------------------------------- */
/* nrf24 MISO pin read function
/* - returns: Non-zero if the pin is high */
/* -------------------------------------------------------------------------- */
extern uint8_t nrf24_miso_digitalRead();

#endif

and finally the nrf24.c
Code:
#include <xc.h>
#include "nrf24.h"

uint8_t payload_len;

#define set_bit(reg,bit) reg |= (1<<bit)
#define clr_bit(reg,bit) reg &= ~(1<<bit)
#define check_bit(reg,bit) (reg&(1<<bit))

/* ------------------------------------------------------------------------- */
void nrf24_setupPins()
{
    set_bit(RC1,0); // CE output
    set_bit(RC2,1); // CSN output
    set_bit(RC3,2); // SCK output
    set_bit(RC5,3); // MOSI output
    clr_bit(RC4,4); // MISO input
}
/* ------------------------------------------------------------------------- */
void nrf24_ce_digitalWrite(uint8_t state)
{
    if(state)
    {
        set_bit(PORTC,0);
    }
    else
    {
        clr_bit(PORTC,0);
    }
}
/* ------------------------------------------------------------------------- */
void nrf24_csn_digitalWrite(uint8_t state)
{
    if(state)
    {
        set_bit(PORTC,1);
    }
    else
    {
        clr_bit(PORTC,1);
    }
}
/* ------------------------------------------------------------------------- */
void nrf24_sck_digitalWrite(uint8_t state)
{
    if(state)
    {
        set_bit(PORTC,2);
    }
    else
    {
        clr_bit(PORTC,2);
    }
}
/* ------------------------------------------------------------------------- */
void nrf24_mosi_digitalWrite(uint8_t state)
{
    if(state)
    {
        set_bit(PORTC,3);
    }
    else
    {
        clr_bit(PORTC,3);
    }
}
/* ------------------------------------------------------------------------- */
uint8_t nrf24_miso_digitalRead()
{
    return check_bit(PORTC,4);
}
/* ------------------------------------------------------------------------- */

/* init the hardware pins */
void nrf24_init() 
{
    nrf24_setupPins();
    nrf24_ce_digitalWrite(LOW);
    nrf24_csn_digitalWrite(HIGH);    
}

/* configure the module */
void nrf24_config(uint8_t channel, uint8_t pay_length)
{
    /* Use static payload length ... */
    payload_len = pay_length;

    // Set RF channel
    nrf24_configRegister(RF_CH,channel);

    // Set length of incoming payload 
    nrf24_configRegister(RX_PW_P0, 0x00); // Auto-ACK pipe ...
    nrf24_configRegister(RX_PW_P1, payload_len); // Data payload pipe
    nrf24_configRegister(RX_PW_P2, 0x00); // Pipe not used 
    nrf24_configRegister(RX_PW_P3, 0x00); // Pipe not used 
    nrf24_configRegister(RX_PW_P4, 0x00); // Pipe not used 
    nrf24_configRegister(RX_PW_P5, 0x00); // Pipe not used 

    // 1 Mbps, TX gain: 0dbm
    nrf24_configRegister(RF_SETUP, (0<<RF_DR)|((0x03)<<RF_PWR));

    // CRC enable, 1 byte CRC length
    nrf24_configRegister(CONFIG,nrf24_CONFIG);

    // Auto Acknowledgment
    nrf24_configRegister(EN_AA,(1<<ENAA_P0)|(1<<ENAA_P1)|(0<<ENAA_P2)|(0<<ENAA_P3)|(0<<ENAA_P4)|(0<<ENAA_P5));

    // Enable RX addresses
    nrf24_configRegister(EN_RXADDR,(1<<ERX_P0)|(1<<ERX_P1)|(0<<ERX_P2)|(0<<ERX_P3)|(0<<ERX_P4)|(0<<ERX_P5));

    // Auto retransmit delay: 1000 us and Up to 15 retransmit trials
    nrf24_configRegister(SETUP_RETR,(0x04<<ARD)|(0x0F<<ARC));

    // Dynamic length configurations: No dynamic length
    nrf24_configRegister(DYNPD,(0<<DPL_P0)|(0<<DPL_P1)|(0<<DPL_P2)|(0<<DPL_P3)|(0<<DPL_P4)|(0<<DPL_P5));

    // Start listening
    nrf24_powerUpRx();
}

/* Set the RX address */
void nrf24_rx_address(uint8_t * adr) 
{
    nrf24_ce_digitalWrite(LOW);
    nrf24_writeRegister(RX_ADDR_P1,adr,nrf24_ADDR_LEN);
    nrf24_ce_digitalWrite(HIGH);
}

/* Returns the payload length */
uint8_t nrf24_payload_length()
{
    return payload_len;
}

/* Set the TX address */
void nrf24_tx_address(uint8_t* adr)
{
    /* RX_ADDR_P0 must be set to the sending addr for auto ack to work. */
    nrf24_writeRegister(RX_ADDR_P0,adr,nrf24_ADDR_LEN);
    nrf24_writeRegister(TX_ADDR,adr,nrf24_ADDR_LEN);
}

/* Checks if data is available for reading */
/* Returns 1 if data is ready ... */
uint8_t nrf24_dataReady() 
{
    // See note in getData() function - just checking RX_DR isn't good enough
    uint8_t status = nrf24_getStatus();

    // We can short circuit on RX_DR, but if it's not set, we still need
    // to check the FIFO for any pending packets
    if ( status & (1 << RX_DR) ) 
    {
        return 1;
    }

    return !nrf24_rxFifoEmpty();;
}

/* Checks if receive FIFO is empty or not */
uint8_t nrf24_rxFifoEmpty()
{
    uint8_t fifoStatus;

    nrf24_readRegister(FIFO_STATUS,&fifoStatus,1);
    
    return (fifoStatus & (1 << RX_EMPTY));
}

/* Returns the length of data waiting in the RX fifo */
uint8_t nrf24_payloadLength()
{
    uint8_t status;
    nrf24_csn_digitalWrite(LOW);
    spi_transfer(R_RX_PL_WID);
    status = spi_transfer(0x00);
    nrf24_csn_digitalWrite(HIGH);
    return status;
}

/* Reads payload bytes into data array */
void nrf24_getData(uint8_t* data) 
{
    /* Pull down chip select */
    nrf24_csn_digitalWrite(LOW);                               

    /* Send cmd to read rx payload */
    spi_transfer( R_RX_PAYLOAD );
    
    /* Read payload */
    nrf24_transferSync(data,data,payload_len);
    
    /* Pull up chip select */
    nrf24_csn_digitalWrite(HIGH);

    /* Reset status register */
    nrf24_configRegister(STATUS,(1<<RX_DR));   
}

/* Returns the number of retransmissions occured for the last message */
uint8_t nrf24_retransmissionCount()
{
    uint8_t rv;
    nrf24_readRegister(OBSERVE_TX,&rv,1);
    rv = rv & 0x0F;
    return rv;
}

// Sends a data package to the default address. Be sure to send the correct
// amount of bytes as configured as payload on the receiver.
void nrf24_send(uint8_t* value) 
{    
    /* Go to Standby-I first */
    nrf24_ce_digitalWrite(LOW);
     
    /* Set to transmitter mode , Power up if needed */
    nrf24_powerUpTx();

    /* Do we really need to flush TX fifo each time ? */
    #if 1
        /* Pull down chip select */
        nrf24_csn_digitalWrite(LOW);           

        /* Write cmd to flush transmit FIFO */
        spi_transfer(FLUSH_TX);     

        /* Pull up chip select */
        nrf24_csn_digitalWrite(HIGH);                    
    #endif 

    /* Pull down chip select */
    nrf24_csn_digitalWrite(LOW);

    /* Write cmd to write payload */
    spi_transfer(W_TX_PAYLOAD);

    /* Write payload */
    nrf24_transmitSync(value,payload_len);   

    /* Pull up chip select */
    nrf24_csn_digitalWrite(HIGH);

    /* Start the transmission */
    nrf24_ce_digitalWrite(HIGH);    
}

uint8_t nrf24_isSending()
{
    uint8_t status;

    /* read the current status */
    status = nrf24_getStatus();
                
    /* if sending successful (TX_DS) or max retries exceded (MAX_RT). */
    if((status & ((1 << TX_DS)  | (1 << MAX_RT))))
    {        
        return 0; /* false */
    }

    return 1; /* true */

}

uint8_t nrf24_getStatus()
{
    uint8_t rv;
    nrf24_csn_digitalWrite(LOW);
    rv = spi_transfer(NOP);
    nrf24_csn_digitalWrite(HIGH);
    return rv;
}

uint8_t nrf24_lastMessageStatus()
{
    uint8_t rv;

    rv = nrf24_getStatus();

    /* Transmission went OK */
    if((rv & ((1 << TX_DS))))
    {
        return NRF24_TRANSMISSON_OK;
    }
    /* Maximum retransmission count is reached */
    /* Last message probably went missing ... */
    else if((rv & ((1 << MAX_RT))))
    {
        return NRF24_MESSAGE_LOST;
    }  
    /* Probably still sending ... */
    else
    {
        return 0xFF;
    }
}

void nrf24_powerUpRx()
{     
    nrf24_csn_digitalWrite(LOW);
    spi_transfer(FLUSH_RX);
    nrf24_csn_digitalWrite(HIGH);

    nrf24_configRegister(STATUS,(1<<RX_DR)|(1<<TX_DS)|(1<<MAX_RT)); 

    nrf24_ce_digitalWrite(LOW);    
    nrf24_configRegister(CONFIG,nrf24_CONFIG|((1<<PWR_UP)|(1<<PRIM_RX)));    
    nrf24_ce_digitalWrite(HIGH);
}

void nrf24_powerUpTx()
{
    nrf24_configRegister(STATUS,(1<<RX_DR)|(1<<TX_DS)|(1<<MAX_RT)); 

    nrf24_configRegister(CONFIG,nrf24_CONFIG|((1<<PWR_UP)|(0<<PRIM_RX)));
}

void nrf24_powerDown()
{
    nrf24_ce_digitalWrite(LOW);
    nrf24_configRegister(CONFIG,nrf24_CONFIG);
}

/* software spi routine */
uint8_t spi_transfer(uint8_t tx)
{
    uint8_t i = 0;
    uint8_t rx = 0;    

    nrf24_sck_digitalWrite(LOW);

    for(i=0;i<8;i++)
    {

        if(tx & (1<<(7-i)))
        {
            nrf24_mosi_digitalWrite(HIGH);            
        }
        else
        {
            nrf24_mosi_digitalWrite(LOW);
        }

        nrf24_sck_digitalWrite(HIGH);        

        rx = rx << 1;
        if(nrf24_miso_digitalRead())
        {
            rx |= 0x01;
        }

        nrf24_sck_digitalWrite(LOW);                

    }

    return rx;
}

/* send and receive multiple bytes over SPI */
void nrf24_transferSync(uint8_t* dataout,uint8_t* datain,uint8_t len)
{
    uint8_t i;

    for(i=0;i<len;i++)
    {
        datain[i] = spi_transfer(dataout[i]);
    }

}

/* send multiple bytes over SPI */
void nrf24_transmitSync(uint8_t* dataout,uint8_t len)
{
    uint8_t i;
    
    for(i=0;i<len;i++)
    {
        spi_transfer(dataout[i]);
    }

}

/* Clocks only one byte into the given nrf24 register */
void nrf24_configRegister(uint8_t reg, uint8_t value)
{
    nrf24_csn_digitalWrite(LOW);
    spi_transfer(W_REGISTER | (REGISTER_MASK & reg));
    spi_transfer(value);
    nrf24_csn_digitalWrite(HIGH);
}

/* Read single register from nrf24 */
void nrf24_readRegister(uint8_t reg, uint8_t* value, uint8_t len)
{
    nrf24_csn_digitalWrite(LOW);
    spi_transfer(R_REGISTER | (REGISTER_MASK & reg));
    nrf24_transferSync(value,value,len);
    nrf24_csn_digitalWrite(HIGH);
}

/* Write to a single register of nrf24 */
void nrf24_writeRegister(uint8_t reg, uint8_t* value, uint8_t len) 
{
    nrf24_csn_digitalWrite(LOW);
    spi_transfer(W_REGISTER | (REGISTER_MASK & reg));
    nrf24_transmitSync(value,len);
    nrf24_csn_digitalWrite(HIGH);
}

the original code had the following which I modified for my PIC (to us PORTC) although the code does not use hardware SPI:

Code:
#include <avr/io.h>

    #define set_bit(reg,bit) reg |= (1<<bit)
    #define clr_bit(reg,bit) reg &= ~(1<<bit)
    #define check_bit(reg,bit) (reg&(1<<bit))

    /* ------------------------------------------------------------------------- */
    void nrf24_setupPins()
    {
        set_bit(DDRA,0); // CE output
        set_bit(DDRA,1); // CSN output
        set_bit(DDRA,2); // SCK output
        set_bit(DDRA,3); // MOSI output
        clr_bit(DDRA,4); // MISO input
    }
    /* ------------------------------------------------------------------------- */
    void nrf24_ce_digitalWrite(uint8_t state)
    {
        if(state)
        {
            set_bit(PORTA,0);
        }
        else
        {
            clr_bit(PORTA,0);
        }
    }
    /* ------------------------------------------------------------------------- */
    void nrf24_csn_digitalWrite(uint8_t state)
    {
        if(state)
        {
            set_bit(PORTA,1);
        }
        else
        {
            clr_bit(PORTA,1);
        }
    }
    /* ------------------------------------------------------------------------- */
    void nrf24_sck_digitalWrite(uint8_t state)
    {
        if(state)
        {
            set_bit(PORTA,2);
        }
        else
        {
            clr_bit(PORTA,2);
        }
    }
    /* ------------------------------------------------------------------------- */
    void nrf24_mosi_digitalWrite(uint8_t state)
    {
        if(state)
        {
            set_bit(PORTA,3);
        }
        else
        {
            clr_bit(PORTA,3);
        }
    }
    /* ------------------------------------------------------------------------- */
    uint8_t nrf24_miso_digitalRead()
    {
        return check_bit(PINA,4);
    }
    /* ------------------------------------------------------------------------- */

did i modify the code right?
 
Which Compiler are you using ? Please Zip and post the complete project files so that it can be compiled and checked for error and also it will be easy to modify them.
 
Im using MPLab XC8 (v1.20) and I attached the files, and as far as compiling, it does that with no problems, but when I run it, I don't get what it should be, which in the case of the attached documents show the payload on an LCD (not even sure if they are communicating right to start with)

Thanks
 

Attachments

  • nRF.rar
    325.3 KB · Views: 126
OK... found this code (which uses software SPI) but would like to get some feedback on it. On the TX side, Im using LEDs to debug (kind of not the best way, but its what I know how to do for now). So I put a "LED Blinking" function after each step to see where my code hangs, and it goes till the 5th point and then into the:
Code:
        /* Wait for transmission to end */
        while(nrf24_isSending());
        LED_Blink(10);
and doesn't do that 6th blink?!

(the code was posted by "asking" and I modified it for the PIC16F886)

here is the TX side (its a bit long):
Code:
/*
* Project:         nRF Test TX
* File:            main.c
*
* Created on October 19, 2014, 3:14 PM
*
*/


#include <xc.h>

// CONFIG1
#pragma config FOSC = INTRC_NOCLKOUT, WDTE = OFF, PWRTE = OFF, MCLRE = OFF
#pragma config CP = OFF, CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
#pragma config LVP = OFF, DEBUG = OFF
// CONFIG2
#pragma config BOR4V = BOR40V, WRT = OFF

// Set Clock Freq. & Delays
#ifndef _XTAL_FREQ
#define _XTAL_FREQ 20000000
#define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/20000000.0)))
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/20000.0)))
#endif

#include "stdint.h"
/* Memory Map */
#define CONFIG      0x00
#define EN_AA       0x01
#define EN_RXADDR   0x02
#define SETUP_AW    0x03
#define SETUP_RETR  0x04
#define RF_CH       0x05
#define RF_SETUP    0x06
#define STATUS      0x07
#define OBSERVE_TX  0x08
#define CD          0x09
#define RX_ADDR_P0  0x0A
#define RX_ADDR_P1  0x0B
#define RX_ADDR_P2  0x0C
#define RX_ADDR_P3  0x0D
#define RX_ADDR_P4  0x0E
#define RX_ADDR_P5  0x0F
#define TX_ADDR     0x10
#define RX_PW_P0    0x11
#define RX_PW_P1    0x12
#define RX_PW_P2    0x13
#define RX_PW_P3    0x14
#define RX_PW_P4    0x15
#define RX_PW_P5    0x16
#define FIFO_STATUS 0x17
#define DYNPD       0x1C
/* Bit Mnemonics */
/* configuratio nregister */
#define MASK_RX_DR  6
#define MASK_TX_DS  5
#define MASK_MAX_RT 4
#define EN_CRC      3
#define CRCO        2
#define PWR_UP      1
#define PRIM_RX     0
/* enable auto acknowledgment */
#define ENAA_P5     5
#define ENAA_P4     4
#define ENAA_P3     3
#define ENAA_P2     2
#define ENAA_P1     1
#define ENAA_P0     0
/* enable rx addresses */
#define ERX_P5      5
#define ERX_P4      4
#define ERX_P3      3
#define ERX_P2      2
#define ERX_P1      1
#define ERX_P0      0
/* setup of address width */
#define AW          0 /* 2 bits */
/* setup of auto re-transmission */
#define ARD         4 /* 4 bits */
#define ARC         0 /* 4 bits */
/* RF setup register */
#define PLL_LOCK    4
#define RF_DR_HIGH  3
#define RF_PWR      1 /* 2 bits */
/* general status register */
#define RX_DR       6
#define TX_DS       5
#define MAX_RT      4
#define RX_P_NO     1 /* 3 bits */
#define TX_FULL     0
/* transmit observe register */
#define PLOS_CNT    4 /* 4 bits */
#define ARC_CNT     0 /* 4 bits */
/* fifo status */
#define TX_REUSE    6
#define FIFO_FULL   5
#define TX_EMPTY    4
#define RX_FULL     1
#define RX_EMPTY    0
/* dynamic length */
#define DPL_P0      0
#define DPL_P1      1
#define DPL_P2      2
#define DPL_P3      3
#define DPL_P4      4
#define DPL_P5      5
/* Instruction Mnemonics */
#define R_REGISTER    0x00 /* last 4 bits will indicate reg. address */
#define W_REGISTER    0x20 /* last 4 bits will indicate reg. address */
#define REGISTER_MASK 0x1F
#define R_RX_PAYLOAD  0x61
#define W_TX_PAYLOAD  0xA0
#define FLUSH_TX      0xE1
#define FLUSH_RX      0xE2
#define REUSE_TX_PL   0xE3
#define ACTIVATE      0x50
#define R_RX_PL_WID   0x60
#define NOP1          0xFF
/// hardware spi pin defined
#define LED_PIN      RA1        // led test
#define CS_Pin       RB0        //set port as output
#define CE_Pin       RB4        //set port as output
#define SCK_Pin      RB1        //set port as output
#define Mosi_Pin     RB2        //set port as output
#define Miso_Pin     RB3        //set port as input
#define HIGH         1
#define LOW          0
//#ifndef NRF24
#define NRF24
uint8_t PTX;
uint8_t payload;
uint8_t channel;
uint8_t nrf24_rxFifoEmpty();
uint8_t nrf24_getStatus();
#define nrf24_ADDR_LEN 5
#define nrf24_CONFIG ((1<<EN_CRC)|(0<<CRCO))
#define NRF24_TRANSMISSON_OK 0
#define NRF24_MESSAGE_LOST   1

void LED_Blink(int fc){
    int i;
    for(i=0;i<fc;i++){
        LED_PIN = 0;
        __delay_ms(100);
        LED_PIN = 1;
        __delay_ms(100);
    }
}
void nrf24_ce_digitalwrite(uint8_t state){
    if (state)
    {
        CE_Pin = 1;
    }
    else
    {
        CE_Pin = 0;
    }
}
void nrf24_csn_digitalwrite(uint8_t state){
    if (state)
    {
        CS_Pin = 1;
    }
    else
    {
        CS_Pin = 0;
    }
}
void nrf24_sck_digitalwrite(uint8_t state){
    if (state)
    {
        SCK_Pin = 1;
    }
    else
    {
        SCK_Pin = 0;
    }
}
void nrf24_mosi_digitalwrite( uint8_t state){
    if (state)
    {
        Mosi_Pin = 1;
    }
    else
    {
        Mosi_Pin = 0;
    }
}
uint8_t nrf24_miso_digitalread(){
    return 1;
}
//Clocks only one byte uint8_to the given nrf24 register */
/* software spi routine */
uint8_t spi_transfer(uint8_t tx){
    uint8_t i = 0;
    uint8_t rs = 0;
    nrf24_sck_digitalwrite(LOW);
    for(i=0;i<8;i++)
    {
        if(tx & 0x80) // msbit first spi standard
        {
            nrf24_mosi_digitalwrite(HIGH);
        }
        else
        {
            nrf24_mosi_digitalwrite(LOW);
        }
        nrf24_sck_digitalwrite(HIGH);
        tx = tx << 1;
        if(Miso_Pin == 1)
        {
            rs |= 0x01;
        }
        nrf24_sck_digitalwrite(LOW);
    }
    return rs;
}
void nrf24_configRegister(uint8_t reg, uint8_t value){
    nrf24_csn_digitalwrite(LOW);
    spi_transfer(W_REGISTER | (REGISTER_MASK & reg));
    spi_transfer(value);
    nrf24_csn_digitalwrite(HIGH);
}
/* send and receive multiple bytes over SPI */ // checked with mirf
void nrf24_transferSync(uint8_t  *dataout,uint8_t *datain,uint8_t len){
    uint8_t i;
    for(i=0;i<len;i++){
        datain[i] = spi_transfer(dataout[i]);
    }
}
//send multiple bytes over SPI // checked with mirf
void nrf24_transmitSync(uint8_t *dataout,uint8_t len){
    uint8_t i;
    for(i=0;i<len;i++){
        spi_transfer(dataout[i]);
    }
}
// init the hardware pins
void nrf24_init(){
    ANSEL = 0;
    TRISB = 0b00001000;
    TRISA = 0b00000000;
//    CMCON  |= 7;
    C1ON = 0;
    C2ON = 0;
    nrf24_ce_digitalwrite(LOW);
    nrf24_csn_digitalwrite(HIGH);
}
// checked with mirf
void nrf24_powerUpRx(){
    PTX = 0;
    nrf24_csn_digitalwrite(LOW);
    nrf24_configRegister(CONFIG,nrf24_CONFIG|((1<<PWR_UP)|(1<<PRIM_RX)));
    nrf24_csn_digitalwrite(HIGH);
    nrf24_configRegister(STATUS,(1<<TX_DS)|(1<<MAX_RT));
}
// checked with mirf
void nrf24_flushRx() {
    nrf24_csn_digitalwrite(LOW);
    spi_transfer(FLUSH_RX);
    nrf24_csn_digitalwrite(HIGH);
}
// Sets the important registers in the MiRF module and powers the module
// in receiving mode
// NB: channel and payload must be set now.
// check with mirf
void nrf24_config(){
    // Set RF channel
    nrf24_configRegister(RF_CH,channel);
    // Set length of incoming payload
    nrf24_configRegister(RX_PW_P0, payload);
    nrf24_configRegister(RX_PW_P1, payload);
    // start receiver
    nrf24_flushRx();
    nrf24_powerUpRx();// Start listening
}
/* Read single register from nrf24 */
//checked with mirf
void nrf24_readRegister(uint8_t reg,uint8_t *value,uint8_t len) {
    nrf24_csn_digitalwrite(LOW);
    spi_transfer(R_REGISTER | (REGISTER_MASK & reg));
    nrf24_transferSync(value,value,len);
    nrf24_csn_digitalwrite(HIGH);
}
/* Write to a single register of nrf24 */
void nrf24_writeRegister(uint8_t reg,uint8_t *value,uint8_t len){
// Writes an array of bytes into inte the MiRF registers.
    nrf24_csn_digitalwrite(LOW);
    spi_transfer(W_REGISTER | (REGISTER_MASK & reg));
    nrf24_transmitSync(value,len);
    nrf24_csn_digitalwrite(HIGH);
}
// checked with mirf
void nrf24_powerUpTx(){
    PTX = 1;
    nrf24_configRegister(CONFIG,nrf24_CONFIG|((1<<PWR_UP)|(0<<PRIM_RX)));
}
// check with mirf
void nrf24_powerDown(){
    nrf24_ce_digitalwrite(LOW);
    nrf24_configRegister(CONFIG,nrf24_CONFIG);
}
/* Set the RX address */
// check with mirf
void nrf24_rx_address(uint8_t* adr){
    nrf24_ce_digitalwrite(LOW);
    nrf24_writeRegister(RX_ADDR_P1,adr,nrf24_ADDR_LEN);
    nrf24_ce_digitalwrite(HIGH);
}
/* Set the TX address */
// check with mirf
void nrf24_tx_address(uint8_t* adr){
    /* RX_ADDR_P0 must be set to the sending addr for auto ack to work. */
    nrf24_writeRegister(RX_ADDR_P0,adr,nrf24_ADDR_LEN);
    nrf24_writeRegister(TX_ADDR,adr,nrf24_ADDR_LEN);
}
/* Checks if data is available for reading */
/* Returns 1 if data is ready ... */
// check with mirf
uint8_t nrf24_dataReady(){
    // checks if data is available for reading
    // See note in getData() function - just checking RX_DR isn't good enough
    uint8_t status = nrf24_getStatus();
    // We can short circuit on RX_DR, but if it's not set, we still need
    // to check the FIFO for any pending packets
    if ( status & (1 << RX_DR) ) return 1;
        return !nrf24_rxFifoEmpty();;
}
/* Checks if receive FIFO is empty or not */
// check with mirf
uint8_t nrf24_rxFifoEmpty(){
    uint8_t fifoStatus;
    nrf24_readRegister(FIFO_STATUS,&fifoStatus,sizeof(fifoStatus));
    return (fifoStatus & (1 << RX_EMPTY));
}
/* Reads payload bytes uint8_to data array */
// check with mirf
void nrf24_getData(uint8_t *data1){
    /* Pull down chip select */
    nrf24_csn_digitalwrite(LOW);
    /* Send cmd to read rx payload */
    spi_transfer(R_RX_PAYLOAD);
    /* Read payload */
    nrf24_transferSync(data1,data1,payload);
    /* Pull up chip select */
    nrf24_csn_digitalwrite(HIGH);
    /* Reset status register */
    nrf24_configRegister(STATUS,(1<<RX_DR));
}

// Sends a data package to the default address. Be sure to send the correct
// amount of bytes as configured as payload on the receiver.
// check with mirf
void nrf24_send(uint8_t* value){
    uint8_t status;
    status = nrf24_getStatus();
    while (PTX) {
        status = nrf24_getStatus();
        if((status & ((1 << TX_DS)  | (1 << MAX_RT)))){
            PTX = 0;
            break;
        }
    }
    // Wait until last paket is send
    /* Go to Standby-I first */
    nrf24_ce_digitalwrite(LOW);
    /* Set to transmitter mode , Power up if needed */
    nrf24_powerUpTx();
    nrf24_csn_digitalwrite(LOW);
    spi_transfer(FLUSH_TX);
    nrf24_csn_digitalwrite(HIGH);

    /* Pull down chip select */
    nrf24_csn_digitalwrite(LOW);
    /* Write cmd to write payload */
    spi_transfer(W_TX_PAYLOAD);
    /* Write payload */
    nrf24_transmitSync(value,payload);
    /* Pull up chip select */
    nrf24_csn_digitalwrite(HIGH);
    /* Start the transmission */
    nrf24_ce_digitalwrite(HIGH);
}
/**
* isSending.
*
* Test if chip is still sending.
* When sending has finished return chip to listening.
*
*/
// CHECK with mirf
uint8_t nrf24_isSending(){
    uint8_t status;
    if(PTX){
        /* read the current status */
        status = nrf24_getStatus();
        /* if sending successful (TX_DS) or max retries exceded (MAX_RT). */
        if((status & ((1 << TX_DS)  | (1 << MAX_RT))))
        {
            nrf24_powerUpRx();
            return 0; /* false */
        }
        return 1; /* true */
    }
    return 0; /* false */
}
// checked with mirf
uint8_t nrf24_getStatus(){
    uint8_t rv;
    nrf24_readRegister(STATUS,&rv,1);
    return rv;
}
//before main initilization
uint8_t temp;
uint8_t q = 0;
uint8_t data_array[4];
uint8_t tx_address[5] = {0xE8,0xE8,0xF0,0xFC,0xE1};  // on receiver this should be rx_address
uint8_t rx_address[5] = {0xE8,0xE8,0xF0,0xFC,0xD1};  // on receiver this should be tx_address
uint8_t temp1,temp2;
void main() {

    /* init hardware pins */
    nrf24_init();
    LED_Blink(5);                                       //1
    __delay_ms(2000);

    // Channel #2 , payload length: 4 
    nrf24_config(72,4);
    LED_Blink(3);                                       //2
    __delay_ms(2000);
    // Set the device addresses
    nrf24_tx_address(tx_address);
    nrf24_rx_address(rx_address);

    while(1)
    {

        LED_Blink(4);                                   //3
        __delay_ms(2000);
        //LED_PIN = HIGH;
        /* Fill the data buffer */
        data_array[0] = 111;
        data_array[1] = 0X00;
        data_array[2] = 0x00;
        data_array[3] = 0X00;
        LED_Blink(5);                                   //4
        __delay_ms(2000);
        /* Automatically goes to TX mode */
        nrf24_send(data_array);
        LED_Blink(5);                                   //5
        __delay_ms(10);
        /* Wait for transmission to end */
        while(nrf24_isSending());
        LED_Blink(10);
        //  __delay_ms(2);
        /* Optionally, go back to RX mode ... */
        nrf24_powerUpRx();
        /* Or you might want to power down after TX */
        //	 nrf24_powerDown();
        /* Wait a little ... */
        //__delay_ms(10);
        //LED_PIN = LOW;
        LED_Blink(10);
        __delay_ms(500);
    }
}

and here is the RX side:
Code:
/*
* Project:         nRF Test RX
* File:            main.c
*
* Created on October 19, 2014, 3:14 PM
*
*/


#include <xc.h>

// CONFIG1
#pragma config FOSC = INTRC_NOCLKOUT, WDTE = OFF, PWRTE = OFF, MCLRE = OFF
#pragma config CP = OFF, CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
#pragma config LVP = OFF, DEBUG = OFF
// CONFIG2
#pragma config BOR4V = BOR40V, WRT = OFF

// Set Clock Freq. & Delays
#ifndef _XTAL_FREQ
#define _XTAL_FREQ 20000000
#define __delay_us(x) _delay((unsigned long)((x)*(_XTAL_FREQ/20000000.0)))
#define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/20000.0)))
#endif

#include "stdint.h"
/* Memory Map */
#define CONFIG      0x00
#define EN_AA       0x01
#define EN_RXADDR   0x02
#define SETUP_AW    0x03
#define SETUP_RETR  0x04
#define RF_CH       0x05
#define RF_SETUP    0x06
#define STATUS      0x07
#define OBSERVE_TX  0x08
#define CD          0x09
#define RX_ADDR_P0  0x0A
#define RX_ADDR_P1  0x0B
#define RX_ADDR_P2  0x0C
#define RX_ADDR_P3  0x0D
#define RX_ADDR_P4  0x0E
#define RX_ADDR_P5  0x0F
#define TX_ADDR     0x10
#define RX_PW_P0    0x11
#define RX_PW_P1    0x12
#define RX_PW_P2    0x13
#define RX_PW_P3    0x14
#define RX_PW_P4    0x15
#define RX_PW_P5    0x16
#define FIFO_STATUS 0x17
#define DYNPD       0x1C
/* Bit Mnemonics */
/* configuratio nregister */
#define MASK_RX_DR  6
#define MASK_TX_DS  5
#define MASK_MAX_RT 4
#define EN_CRC      3
#define CRCO        2
#define PWR_UP      1
#define PRIM_RX     0
/* enable auto acknowledgment */
#define ENAA_P5     5
#define ENAA_P4     4
#define ENAA_P3     3
#define ENAA_P2     2
#define ENAA_P1     1
#define ENAA_P0     0
/* enable rx addresses */
#define ERX_P5      5
#define ERX_P4      4
#define ERX_P3      3
#define ERX_P2      2
#define ERX_P1      1
#define ERX_P0      0
/* setup of address width */
#define AW          0 /* 2 bits */
/* setup of auto re-transmission */
#define ARD         4 /* 4 bits */
#define ARC         0 /* 4 bits */
/* RF setup register */
#define PLL_LOCK    4
#define RF_DR_HIGH  3
#define RF_PWR      1 /* 2 bits */
/* general status register */
#define RX_DR       6
#define TX_DS       5
#define MAX_RT      4
#define RX_P_NO     1 /* 3 bits */
#define TX_FULL     0
/* transmit observe register */
#define PLOS_CNT    4 /* 4 bits */
#define ARC_CNT     0 /* 4 bits */
/* fifo status */
#define TX_REUSE    6
#define FIFO_FULL   5
#define TX_EMPTY    4
#define RX_FULL     1
#define RX_EMPTY    0
/* dynamic length */
#define DPL_P0      0
#define DPL_P1      1
#define DPL_P2      2
#define DPL_P3      3
#define DPL_P4      4
#define DPL_P5      5
/* Instruction Mnemonics */
#define R_REGISTER    0x00 /* last 4 bits will indicate reg. address */
#define W_REGISTER    0x20 /* last 4 bits will indicate reg. address */
#define REGISTER_MASK 0x1F
#define R_RX_PAYLOAD  0x61
#define W_TX_PAYLOAD  0xA0
#define FLUSH_TX      0xE1
#define FLUSH_RX      0xE2
#define REUSE_TX_PL   0xE3
#define ACTIVATE      0x50
#define R_RX_PL_WID   0x60
#define NOP1          0xFF
/// hardware spi pin defined
#define LED_PIN      RA1    // led test
#define LED_PIN2     RA2    // led test
#define CS_Pin       RB0    // set port as output
#define CE_Pin       RB4    // set port as output
#define SCK_Pin      RB1    // set port as output
#define Mosi_Pin     RB2    // set port as output
#define Miso_Pin     RB3    // set port as input
#define HIGH         1
#define LOW          0
//#ifndef NRF24
#define NRF24
uint8_t PTX;
uint8_t payload;
uint8_t channel;
uint8_t nrf24_rxFifoEmpty();
uint8_t nrf24_getStatus();
#define nrf24_ADDR_LEN 5
#define nrf24_CONFIG ((1<<EN_CRC)|(0<<CRCO))
#define NRF24_TRANSMISSON_OK 0
#define NRF24_MESSAGE_LOST   1
void nrf24_ce_digitalwrite(uint8_t state){
    if (state)
    {
        CE_Pin = 1;
    }
    else
    {
        CE_Pin = 0;
    }
}
void nrf24_csn_digitalwrite(uint8_t state){
    if (state)
    {
        CS_Pin = 1;
    }
    else
    {
        CS_Pin = 0;
    }
}
void nrf24_sck_digitalwrite(uint8_t state){
    if (state)
    {
        SCK_Pin = 1;
    }
    else
    {
        SCK_Pin = 0;
    }
}
void nrf24_mosi_digitalwrite( uint8_t state){
    if (state)
    {
        Mosi_Pin = 1;
    }
    else
    {
        Mosi_Pin = 0;
    }
}
uint8_t nrf24_miso_digitalread(){
    return 1;
}
//Clocks only one byte uint8_to the given nrf24 register */
/* software spi routine */
uint8_t spi_transfer(uint8_t tx){
    uint8_t i = 0;
    uint8_t rs = 0;
    nrf24_sck_digitalwrite(LOW);
    for(i=0;i<8;i++)
    {
        if(tx & 0x80) // msbit first spi standard
        {
            nrf24_mosi_digitalwrite(HIGH);
        }
        else
        {
            nrf24_mosi_digitalwrite(LOW);
        }
        nrf24_sck_digitalwrite(HIGH);
        tx = tx << 1;
        if(Miso_Pin == 1)
        {
            rs |= 0x01;
        }
        nrf24_sck_digitalwrite(LOW);
    }
    return rs;
}
void nrf24_configRegister(uint8_t reg, uint8_t value){
    nrf24_csn_digitalwrite(LOW);
    spi_transfer(W_REGISTER | (REGISTER_MASK & reg));
    spi_transfer(value);
    nrf24_csn_digitalwrite(HIGH);
}
/* send and receive multiple bytes over SPI */ // checked with mirf
void nrf24_transferSync(uint8_t  *dataout,uint8_t *datain,uint8_t len){
    uint8_t i;
    for(i=0;i<len;i++){
        datain[i] = spi_transfer(dataout[i]);
    }
}
//send multiple bytes over SPI // checked with mirf
void nrf24_transmitSync(uint8_t *dataout,uint8_t len){
    uint8_t i;
    for(i=0;i<len;i++){
        spi_transfer(dataout[i]);
    }
}
// init the hardware pins
void nrf24_init(){
    ANSEL = 0;
    TRISB = 0b00001000;
    TRISA = 0b00000000;
    C1ON = 0;
    C2ON = 0;
    nrf24_ce_digitalwrite(LOW);
    nrf24_csn_digitalwrite(HIGH);
}
void nrf24_powerUpRx(){
    PTX = 0;
    nrf24_csn_digitalwrite(LOW);
    nrf24_configRegister(CONFIG,nrf24_CONFIG|((1<<PWR_UP)|(1<<PRIM_RX)));
    nrf24_csn_digitalwrite(HIGH);
    nrf24_configRegister(STATUS,(1<<TX_DS)|(1<<MAX_RT));
}
void nrf24_flushRx(){
    nrf24_csn_digitalwrite(LOW);
    spi_transfer(FLUSH_RX);
    nrf24_csn_digitalwrite(HIGH);
}
// Sets the important registers in the MiRF module and powers the module
// in receiving mode
// NB: channel and payload must be set now.
void nrf24_config(){
    /* Use static payload length ... */
    //  payload_len = pay_length;
    // 1 Mbps, TX gain: 0dbm
    ////////// added by me ////////
    nrf24_configRegister(RF_SETUP, (0<<RF_DR_HIGH)|((0x03)<<RF_PWR));
    // CRC enable, 1 byte CRC length
    nrf24_configRegister(CONFIG,nrf24_CONFIG);
    // Auto Acknowledgment
    nrf24_configRegister(EN_AA,(1<<ENAA_P0)|(1<<ENAA_P1)|(0<<ENAA_P2)|(0<<ENAA_P3)|(0<<ENAA_P4)|(0<<ENAA_P5));
    // Enable RX addresses
    nrf24_configRegister(EN_RXADDR,(1<<ERX_P0)|(1<<ERX_P1)|(0<<ERX_P2)|(0<<ERX_P3)|(0<<ERX_P4)|(0<<ERX_P5));
    // Auto retransmit delay: 1000 us and Up to 15 retransmit trials
    nrf24_configRegister(SETUP_RETR,(0x04<<ARD)|(0x0F<<ARC));
    // Dynamic length configurations: No dynamic length
    nrf24_configRegister(DYNPD,(1<<DPL_P0)|(1<<DPL_P1)|(1<<DPL_P2)|(1<<DPL_P3)|(1<<DPL_P4)|(1<<DPL_P5));
    ////////////////MIRF SETTINGS/////////////////////////////
    // Set RF channel
    nrf24_configRegister(RF_CH,channel);
    // Set length of incoming payload
    nrf24_configRegister(RX_PW_P0, payload);
    nrf24_configRegister(RX_PW_P1, payload);
    // start receiver
    nrf24_flushRx();
    nrf24_powerUpRx();// Start listening
}
/* Read single register from nrf24 */
void nrf24_readRegister(uint8_t reg,uint8_t *value,uint8_t len){
    nrf24_csn_digitalwrite(LOW);
    spi_transfer(R_REGISTER | (REGISTER_MASK & reg));
    nrf24_transferSync(value,value,len);
    nrf24_csn_digitalwrite(HIGH);
}
/* Write to a single register of nrf24 */
void nrf24_writeRegister(uint8_t reg,uint8_t *value,uint8_t len){
// Writes an array of bytes into inte the MiRF registers.
    nrf24_csn_digitalwrite(LOW);
    spi_transfer(W_REGISTER | (REGISTER_MASK & reg));
    nrf24_transmitSync(value,len);
    nrf24_csn_digitalwrite(HIGH);
}
void nrf24_powerUpTx(){
    PTX = 1;
    nrf24_configRegister(CONFIG,nrf24_CONFIG|((1<<PWR_UP)|(0<<PRIM_RX)));
}
void nrf24_powerDown(){
    nrf24_ce_digitalwrite(LOW);
    nrf24_configRegister(CONFIG,nrf24_CONFIG);
}
/* Set the RX address */
void nrf24_rx_address(uint8_t* adr){
    nrf24_ce_digitalwrite(LOW);
    nrf24_writeRegister(RX_ADDR_P0,adr,nrf24_ADDR_LEN);
    nrf24_ce_digitalwrite(HIGH);
}
/* Set the TX address */
void nrf24_tx_address(uint8_t* adr){
    /* RX_ADDR_P0 must be set to the sending addr for auto ack to work. */
    nrf24_writeRegister(RX_ADDR_P1,adr,nrf24_ADDR_LEN);
    nrf24_writeRegister(TX_ADDR,adr,nrf24_ADDR_LEN);
}
/* Checks if data is available for reading */
/* Returns 1 if data is ready ... */
uint8_t nrf24_dataReady(){
    // checks if data is available for reading

    // See note in getData() function - just checking RX_DR isn't good enough
    uint8_t status = nrf24_getStatus();
    // We can short circuit on RX_DR, but if it's not set, we still need
    // to check the FIFO for any pending packets
    if ( status & (1 << RX_DR) ) return 1;
    return !nrf24_rxFifoEmpty();;
}
/* Checks if receive FIFO is empty or not */
uint8_t nrf24_rxFifoEmpty(){
    uint8_t fifoStatus;
    nrf24_readRegister(FIFO_STATUS,&fifoStatus,sizeof(fifoStatus));
    return (fifoStatus & (1 << RX_EMPTY));
}
/* Reads payload bytes uint8_to data array */
void nrf24_getData(uint8_t *data1){
    /* Pull down chip select */
    nrf24_csn_digitalwrite(LOW);
    /* Send cmd to read rx payload */
    spi_transfer(R_RX_PAYLOAD);
    /* Read payload */
    nrf24_transferSync(data1,data1,payload);
    /* Pull up chip select */
    nrf24_csn_digitalwrite(HIGH);
    /* Reset status register */
    nrf24_configRegister(STATUS,(1<<RX_DR));
}
// amount of bytes as configured as payload on the receiver.
void nrf24_send(uint8_t* value){
    uint8_t status;
    status = nrf24_getStatus();
    while (PTX){
        status = nrf24_getStatus();
        if((status & ((1 << TX_DS)  | (1 << MAX_RT)))){
            PTX = 0;
            break;
        }
    }
    // Wait until last paket is send
    /* Go to Standby-I first */
    nrf24_ce_digitalwrite(LOW);
    /* Set to transmitter mode , Power up if needed */
    nrf24_powerUpTx();
    nrf24_csn_digitalwrite(LOW);
    spi_transfer(FLUSH_TX);
    nrf24_csn_digitalwrite(HIGH);

    /* Pull down chip select */
    nrf24_csn_digitalwrite(LOW);
    /* Write cmd to write payload */
    spi_transfer(W_TX_PAYLOAD);
    /* Write payload */
    nrf24_transmitSync(value,payload);
    /* Pull up chip select */
    nrf24_csn_digitalwrite(HIGH);
    /* Start the transmission */
    nrf24_ce_digitalwrite(HIGH);
}
/**
* isSending.
*
* Test if chip is still sending.
* When sending has finished return chip to listening.
*
*/
uint8_t nrf24_isSending(){
    uint8_t status;
    if(PTX){
        /* read the current status */
        status = nrf24_getStatus();
        /* if sending successful (TX_DS) or max retries exceded (MAX_RT). */
        if((status & ((1 << TX_DS)  | (1 << MAX_RT))))
        {
            nrf24_powerUpRx();
            return 0; /* false */
        }
        return 1; /* true */
    }
    return 0; /* false */
}
uint8_t nrf24_getStatus(){
    uint8_t rv;
    nrf24_readRegister(STATUS,&rv,1);
    return rv;
}
//before main initilization
uint8_t temp;
uint8_t q = 0;
uint8_t data_array[4];
uint8_t tx_address[5] = {0xE8,0xE8,0xF0,0xFC,0xE1};  // on receiver this should be rx_address
uint8_t rx_address[5] = {0xE8,0xE8,0xF0,0xF0,0xE1};  // on receiver this should be tx_address //E8E8F0F0E1
//uint8_t readRegister;
void main() {
    /* init hardware pins */
    nrf24_init();
    LED_PIN2 = HIGH;
    /* Channel #2 , payload length: 4 */
    nrf24_config(72,4);
    /* Set the device addresses */
    nrf24_tx_address(tx_address);
    nrf24_rx_address(rx_address);
    nrf24_powerUpRx();
    while(1){
        //if(nrf24_dataReady();)

        nrf24_getData(data_array);
        if(data_array[0] == 111)
        {
            LED_PIN = HIGH;
        }
        else
        {
            LED_PIN = LOW;
        }
    }
}

hope someone could help out .... thank you all
 

I don't work with microchip PIC
but I can suggest you to use Nordic semiconductor
application note as a basic framework
for getting this chip to work. I used all other libraries
and failed. I modified this application library for my work
with AVR controller and I managed to make this chip work.
You would need to change the code to adapt it to pic as this is meant for 8051 variants.

https://www.nordicsemi.com/eng/nordic/download_resource/9619/7/34114842
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top