RF link problems with nRF24L01+ to pic18f45k20

Find out how to setup your programmer's software and how to solve many common problems.

Moderator: phalanx

Post Reply
CornMill
Posts: 1
Joined: Tue Feb 21, 2012 9:11 pm

RF link problems with nRF24L01+ to pic18f45k20

Post by CornMill » Tue Feb 21, 2012 10:30 pm

We are currently having problems setting a communication link between two nrf24L01+ modules using pic18f45k20 microcontollers. We currently only trying to send out 1 byte at this time and unsuccessful at doing so. Here is my source code. If anyone can see apparent problems or coding issues on how it is being please help.

Any help would be appreciated.

Also, i need help setting up the internal oscillator to run 8 MHz.

[#include <p18f45k20.h>
#include <spi.h>


//NOTE: You must manually select the XT oscillator option
// and disable the watchdog timer in the MPLAB config menu

#pragma config FOSC = INTIO7
#pragma config FCMEN=OFF
#pragma config BOREN=OFF
#pragma config WDTEN=OFF
#pragma config PBADEN=OFF
#pragma config STVREN=OFF
#pragma config DEBUG=OFF

#define Clock_8MHz
#define Baud_9600
#define TX_IRQ PORTCbits.RC0 //input
#define TX_CE PORTCbits.RC1
#define TX_CSN PORTCbits.RC2
#define TX_SCK PORTCbits.RC3
#define TX_MOSI PORTCbits.RC4
#define TX_MISO PORTCbits.RC5 //input

#define RED_LED PORTBbits.RB0
#define WHITE_LED PORTBbits.RB1


//prototypes
void pause(unsigned char msec);
void init_pic(void);
void nop(void);
void AtoD_init(void);
void Configure_Transmitter(void);
void Transmit_Data(unsigned int);
unsigned int Receive_Data(unsigned int);
void Single_Command_to_Transmitter(unsigned int);
void Transmit_Init(void);
int AtoD_Read_Hi(void);
int AtoD_Read_Lo(void);
void Init_Uart(void);
unsigned int UartReceive(void);
void UartTransmit(unsigned char);


void main()
{
unsigned int x, y, z = 0;
int data = 0;
init_pic();
Transmit_Init();
Init_Uart();


for(x=0;x<10;x++)
{
PORTDbits.RD0 = 1;
pause(25);
PORTDbits.RD0 = 0;
pause(25);
}
while(1)
{
Transmit_Data('U');
pause(50);
}


}

//----------------------------------PORT Initializations -----------------------------
void init_pic()
{
TRISB = 0;
TRISC = 0b10100001; //RC4: Tx_MISO (Input), RC7: Serial Rx (Input)
TRISD = 0;
TRISA = 1;
OSCCON = 0x62;
}

//################################################################################################################
// -----------Initialize UART-----------
void Init_Uart()
{
TXSTA = 0x20; //enable transmit
RCSTAbits.SPEN = 1; //enable serial port
//RCSTA
RCSTAbits.SPEN=1;
RCSTAbits.CREN=1; //Enable Receiver (RX)
TRISCbits.TRISC7 = 1; //Rx as an input
SPBRG = 15;
}

// ----------------Serial Data Transfer-----------------
void UartTransmit(unsigned char Tx_Data)
{
while (!PIR1bits.TXIF);
TXREG = Tx_Data; //load the value to be transmitted
}
// ---------------Serial Data Receive------------------
unsigned int UartReceive()
{
unsigned int Rec_Flag;
while(!PIR1bits.RCIF); //Wait for a byte

return RCREG;
}
//####################################################################################################################



// (not being used) ----------------SPI Write/Read Function-------------
unsigned char SPI(unsigned char myByte)
{
SSPBUF= myByte;
while(!SSPSTATbits.BF);
return SSPBUF;
}



//####################################################################################################################

// ----------------Initialize Transmitter--------------
void Transmit_Init(void)
{
TX_CE = 0;
TX_CSN = 1;
TX_SCK = 0;
nop();


TX_CSN = 0;
Single_Command_to_Transmitter(0x20);
Single_Command_to_Transmitter(0x38); // Tx Mode
TX_CSN = 1;

TX_CSN = 0;
Single_Command_to_Transmitter(0x24); //auto retransmit off
Single_Command_to_Transmitter(0x00);
TX_CSN = 1;

TX_CSN = 0;
Single_Command_to_Transmitter(0x23);
Single_Command_to_Transmitter(0x03); //address width = 5 bytes
TX_CSN = 1;

TX_CSN = 0;
Single_Command_to_Transmitter(0x26);
Single_Command_to_Transmitter(0x07); //data rate = 1MB, 0dBm
TX_CSN = 1;

TX_CSN = 0;
Single_Command_to_Transmitter(0x25);
Single_Command_to_Transmitter(0x02); // Channel 2
TX_CSN = 1;

TX_CSN = 0;
Single_Command_to_Transmitter(0x30); //set address E7E7E7E7E7, also default...
Single_Command_to_Transmitter(0xE7);
Single_Command_to_Transmitter(0xE7);
Single_Command_to_Transmitter(0xE7);
Single_Command_to_Transmitter(0xE7);
Single_Command_to_Transmitter(0xE7);
TX_CSN = 1;

TX_CSN = 0;
Single_Command_to_Transmitter(0x21);
Single_Command_to_Transmitter(0x00); //disable auto-ack, RX mode
TX_CSN = 1;
}


// ----------------------Transmit Data---------------------------
void Transmit_Data(unsigned int Tx_signal)
{
TX_CSN=0;
Single_Command_to_Transmitter(0x27);
Single_Command_to_Transmitter(0x7E); //Clears buffer
TX_CSN=1;

TX_CSN=0;
Single_Command_to_Transmitter(0x20);
Single_Command_to_Transmitter(0x3A); //PWR_UP = 1, Tx mode
TX_CSN=1;

TX_CSN=0;
Single_Command_to_Transmitter(0xE1); //Clear TX FIFO
TX_CSN=1;

TX_CSN = 0;
Single_Command_to_Transmitter(0xA0); //Write Tx Payload (the write operation always starts with byte 0)
Single_Command_to_Transmitter(Tx_signal); // transmit signal
TX_CSN = 1;


TX_CE = 0; // Begin to pulse CE to start the transmission process
pause(2);
TX_CE = 1;
}

//####################################################################################################################

void Single_Command_to_Transmitter(unsigned int x)
{
unsigned int k, data;

data = x;
for(k=0; k<8; k++)
{
if((data&0x80)!= 0)
{
TX_MOSI = 1;
}
else
TX_MOSI = 0;

TX_SCK = 1;
TX_SCK = 0;
data <<= 1;
}

}



//---------------------------------Pause Function------------------------------------------
void pause(unsigned char msec)
{
unsigned char loop1, loop2;

for (loop1=0; loop1<msec; loop1++)
{
for (loop2=0; loop2<120; loop2++)
{
nop();
}
}
}
void nop(void)
{
}]

iza92
Posts: 2
Joined: Thu Jul 03, 2014 7:58 am

Re: RF link problems with nRF24L01+ to pic18f45k20

Post by iza92 » Tue Jul 15, 2014 2:25 am

Hey,
I am trying to do the same thing for RFM69 from HopeRF. did you manage to make it work after all?

Thanks

okayid
Posts: 6
Joined: Mon Sep 15, 2014 2:24 pm

Re: RF link problems with nRF24L01+ to pic18f45k20

Post by okayid » Fri Sep 19, 2014 11:28 am

I've posted my working code for 18LF14K22 and NRF24L01+ using ENHANCED SHOCKBURST and ACK PAYLOAD.
Have a look through it.Maybe it will give you a few ideas for setting up the hardware SPI module ect.
MPLABX v2.15 XC8



// This source does not use peripherial libraries for maximum flexibility.
// SELECT PTX OR PRX MODE AT BEGINNING OF MAIN().CHOOSE BETWEEN NRF24L01_INIT_TX() OR NRF24L01_INIT_RX().


// RB4/pin13 as input for SPI-SDI.
// RB6/pin11 as output for SPI-SCK.
// RC7/pin9 as output for SPI-SDO.
// RB5/pin12 as output for SPI-SS.
// nrf24l01 CSN PIN as RB7/pin12.Same as SPI SS pin.
// nrf24l01 CE PIN as RB7/pin10.
// nrf24l01 IRQ PIN as RA2/pin17.
//*************** #INCLUDE ********************************************************

#include <xc.h>

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

// CONFIG1H
#pragma config FOSC = IRC // Oscillator Selection bits (Internal RC oscillator)
#pragma config PLLEN = OFF // 4 X PLL Enable bit (PLL is under software control)
#pragma config PCLKEN = OFF // Primary Clock Enable bit (Primary clock is under software control)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

// CONFIG2L
#pragma config PWRTEN = ON // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = ON // Brown-out Reset Enable bits (Brown-out Reset enabled and controlled by software (SBOREN is enabled))
#pragma config BORV = 19 // Brown Out Reset Voltage bits (VBOR set to 1.9 V nominal)

// CONFIG2H
#pragma config WDTEN = OFF // Watchdog Timer Enable bit (WDT is controlled by SWDTEN bit of the WDTCON register)
#pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config HFOFST = OFF // HFINTOSC Fast Start-up bit (The system clock is held off until the HFINTOSC is stable.)
#pragma config MCLRE = OFF // MCLR Pin Enable bit (RA3 input pin enabled; MCLR disabled)

// CONFIG4L
#pragma config STVREN = OFF // Stack Full/Underflow Reset Enable bit (Stack full/underflow will not cause Reset)
#pragma config LVP = ON // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled)
#pragma config BBSIZ = OFF // Boot Block Size Select bit (1kW boot block size)
#pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

// CONFIG5L
#pragma config CP0 = OFF // Code Protection bit (Block 0 not code-protected)
#pragma config CP1 = OFF // Code Protection bit (Block 1 not code-protected)

// CONFIG5H
#pragma config CPB = OFF // Boot Block Code Protection bit (Boot block not code-protected)
#pragma config CPD = OFF // Data EEPROM Code Protection bit (Data EEPROM not code-protected)

// CONFIG6L
#pragma config WRT0 = OFF // Write Protection bit (Block 0 not write-protected)
#pragma config WRT1 = OFF // Write Protection bit (Block 1 not write-protected)

// CONFIG6H
#pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration registers not write-protected)
#pragma config WRTB = OFF // Boot Block Write Protection bit (Boot block not write-protected)
#pragma config WRTD = OFF // Data EEPROM Write Protection bit (Data EEPROM not write-protected)

// CONFIG7L
#pragma config EBTR0 = OFF // Table Read Protection bit (Block 0 not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF // Table Read Protection bit (Block 1 not protected from table reads executed in other blocks)

// CONFIG7H
#pragma config EBTRB = OFF // Boot Block Table Read Protection bit (Boot block not protected from table reads executed in other blocks)



//*************** #DEFINITIONS ****************************************************
#define _XTAL_FREQ 16000000
#define uint8 unsigned char /*unsigned char defined as uint8.*/
#define spi_ss_pin LATBbits.LATB5 /*define SPI SS pin as RB5/pin12.*/
#define green_led_pin LATAbits.LATA5 /*define pin2/RA5 for green led.*/
#define red_led_pin LATAbits.LATA4 /*define pin3/RA4 for red led.*/
// #DEFINE NRF24L01
#define rf24_tx_mode 0x00
#define rf24_rx_mode 0x01
#define csn_pin LATBbits.LATB5 /*define nrf24l01 CSN PIN as RB5/pin12.Same as SPI SS pin.*/
#define ce_pin LATBbits.LATB7 /*define nrf24l01 CE PIN as RB7/pin10.*/
#define irq_pin LATAbits.LATA2 /*define nrf24l01 IRQ PIN as RA2/pin17.*/
#define config_reg 0x00
#define en_aa_reg 0x01
#define en_rxaddr_reg 0x02
#define setup_aw_reg 0x03
#define setup_retr_reg 0x04
#define rf_ch_reg 0x05
#define rf_setup_reg 0x06
#define status_reg 0x07
#define observe_tx_reg 0x08
#define cd_reg 0x09
#define rx_addr_reg 0x0A
#define tx_addr_reg 0x10
#define rx_pw_p0_reg 0x11
#define rx_pw_p1_reg 0x12
//RX_PW_Px_REG up to P5(0x16)if needed.
#define fifo_status_reg 0x17
#define feature_reg 0x1D
#define dynpd_reg 0x1C
#define address_width 5 /*set address width in bytes (No. of bytes 3 , 4 or 5).*/
#define packet_width 7 /*set packet width in bytes = No. of data bytes in a packet.*/
#define rf24_channel 20


//*************** GLOBAL VARIABLE DECLARATIONS ************************************
volatile uint8 rf24_status; //holds most recent read from NRF24L01 status reg.Volatile-used in ISR.
volatile uint8 rf24_payload_read[packet_width]; //this array holds data bytes read from RX FIFO.
volatile uint8 rf24_payload_write[packet_width]; //this array holds data bytes to write to TX FIFO.
uint8 rf24_mode; //stores which mode NRF24L01+ is in.1=PRX MODE , 0=TRX MODE.
//*************** CONSTANT DECLARATIONS *******************************************
const uint8 nrf24l01_addr_1[address_width]={0b00000001,0b11000001,0b11000011,0b11000111,0b11001111};//Address 1 (5 bytes).
const uint8 nrf24l01_addr_2[address_width]={0b00000010,0b11000001,0b11000011,0b11000111,0b11001111};//Address 2 (5 bytes).
const uint8 nrf24l01_addr_3[address_width]={0b00000011,0b11000001,0b11000011,0b11000111,0b11001111};//Address 3 (5 bytes).
const uint8 nrf24l01_addr_4[address_width]={0b00000100,0b11000001,0b11000011,0b11000111,0b11001111};//Address 4 (5 bytes).
//more addresses can be added here. NB/ addresses are ordered LSB first as this is how they must be sent to NRF24L01+.
//once first full address has been loaded into NRF24L01+,only 1(LSB) byte needs to be sent to change address.

const uint8 rf24_test_data[packet_width]={0b1000000,0b11000000,0b11100000,0b11110000,0b11111000,0b11111100,0b11111110};
const uint8 dummy_byte = 0b10000001;

//*************** FUNCTION PROTOTYPES *********************************************
void init_pic(void); //sets up PIC ports + osc ect.
void init_spi_master(void); //inits HW SPI for com with NRF24l01+.
void init_interrupts(void); //sets up all interrupts used.
uint8 spi_tx_rx(uint8); //sends and receives data from SPI.
void init_nrf24l01_tx(void); //inits NRF24L01+ for TX mode using ESB.
void init_nrf24l01_rx(void); //inits NRF24L01+ for RX mode using ESB.
uint8 rf24_r_register(uint8); //reads NRF24L01 single data byte regs.
void rf24_w_register(uint8,uint8); //writes NRF24L01 single data byte regs.
void rf24_r_rx_payload(void); //reads NRF24L01 RX FIFO into RX BUFFER array.
void rf24_w_tx_payload(void); //writes TX BUFFER array into NRF24L01 TX FIFO.
void rf24_w_tx_address(const uint8*); //writes address number xx into NRF24L01 TX ADDRESS REG.
void rf24_change_tx_address(const uint8*); //changes TX ADDRESS to address number xx,LSB only.
void rf24_w_rx_address(const uint8*,uint8); //writes address number xx into NRF24L01 RX ADDRESS REG PIPE x.
void rf24_change_rx_address(const uint8*,uint8);//changes RX ADDRESS to address number xx PIPE x,LSB only.
void rf24_flush_tx(void); // clears NRF24L01 TX FIFO.
void rf24_flush_rx(void); // clears NRF24L01 RX FIFO.
void rf24_activate(void); //activates ACK_PL ,NO_ACK_PL & RX_PL_WID see Datasheet.
uint8 rf24_r_rx_pl_wid(void); //reads No. of BYTES in TOP PAYLOAD in RX FIFO.
void rf24_w_ack_payload(uint8); //writes ACK PAYLOAD to TX FIFO in RX MODE ESB.
void rf24_w_tx_payload_no_ack(void); //writes NO ACK PAYLOAD to TX FIFO in TX MODE.
void rf24_nop (void); //writes NOP instruction,fast way to read STATUS REG.
void rf24_clear_interrupt_flags(); //clears RX_DR , TX_DS & MAX_RT flags in STATUS REG.
void interrupt isr_function(void); //interrupt service routine prototype.

//*************** INITIALISATION FUNCTIONS ****************************************
void init_pic(void)
{
OSCCONbits.SCS=0b10; //use internal oscillator.
OSCCONbits.IRCF=0b111; //set internal oscillator to 16 MHz.
LATA=0; LATB=0; LATC=0; //clear all port latches for safe start up.
TRISA=0; TRISB=0; TRISC=0; //all ports outputs.all pins low-GND.
RCONbits.IPEN=0; //disable interrupt priority levels.
ANSELbits.ANSEL=0; //set ALL A2D pins as digital I/O.
ANSELHbits.ANSELH=0; //set ALL A2D pins as digital I/O (high byte).
CM1CON0bits.C1ON=0; //turn off comparator module 1.
CM2CON0bits.C2ON=0; //turn off comparator module 2.
VREFCON0bits.FVR1EN=0; //turn off voltage reference module.
TRISAbits.TRISA5=0; TRISAbits.TRISA4=0; //make RA5 + RA4 outputs for green+red leds.
}

void init_spi_master(void)
{
SSPCON1bits.SSPEN=0; //disable SPI module while setting up.
TRISBbits.TRISB4=1; //set RB4/pin13 as input for SPI-SDI.
TRISBbits.TRISB6=0; //set RB6/pin11 as output for SPI-SCK.
TRISCbits.TRISC7=0; //set RC7/pin9 as output for SPI-SDO.
TRISBbits.TRISB5=0; //set RB5/pin12 as output for SPI_SS.SS is active high.
SSPCON1bits.SSPM=0b0001; //set spi master mode,clock(SCK)=Fosc(16MHz)/16=1MHz.
SSPCON1bits.CKP=0; //SCK idle state = low , active state = high.
SSPSTATbits.CKE=1; //data transmitted on active to idle clock transition.
SSPSTATbits.SMP=0; //data sampled at middle of data output time.
PIR1bits.SSPIF=0; //clear SPI interrupt flag.
spi_ss_pin = 1; //make SPI SS/RB5/pin12 hi.SS pin=csn pin is active low.
SSPCON1bits.SSPEN=1; //enable SPI module.
}

void init_nrf24l01_tx(void)
{
rf24_mode = rf24_tx_mode; //stores which mode NRF24L01+ is in.1=PRX MODE , 0=TRX MODE.
TRISBbits.TRISB5=0; //make RB5 / PIN12 / CSN PIN an output for NRF24L01 CSN PIN.
TRISBbits.TRISB7=0; //make RB7 / PIN10 / CE PIN an output for NRF24L01 CE PIN.
TRISAbits.TRISA2=1; //make RA2 / PIN17 / IRQ PIN an input for interrupt.active low.
__delay_ms(10); //short power up delay (aprox 10mS). ce_pin = 0;
ce_pin = 0; //make CE pin low for standby mode.
csn_pin = 1; //make CSN pin high (CSN pin is active low).
rf24_w_register(config_reg, 0b01001110); //enable TX_DS & MAX_RT interrupts only,CRC-2bytes,power up,PTX mode.
__delay_us(1500); //NRF24L01 bootup delay (aprox 1.5mS).
rf24_w_register(en_rxaddr_reg,0b00000001); //enable RX address on PIPE 0.
rf24_w_register(en_aa_reg,0b00000001); //enable AUTO ACK on PIPE 0 , ESB.
rf24_activate(); //activates ACK_PL ,NO_ACK_PL & RX_PL_WID see Datasheet.
rf24_w_register(feature_reg,0b00000111); //enables DYNAMIC PAYLOAD - ACK PAYLOAD - NO ACK PAYLOAD.
rf24_w_register(dynpd_reg,0b00000001); //enable DYNAMIC PAYLOAD on PIPE 0.
rf24_w_register(setup_aw_reg,address_width); //set address width(No. of bytes in address).see #define.
rf24_w_register(setup_retr_reg,0b00101111); //wait 750uS before retransmit , 15 retransmits before MAX_RT.
rf24_w_register(rf_setup_reg,0b00000111); //all as reset values except AIR DATA RATA set to 1Mbps.
rf24_w_register(rf_ch_reg,rf24_channel); //set RF CHANNEL to CHANNEL 20 . See #define.
rf24_w_tx_address(nrf24l01_addr_1); //writes address 1 to NRF24L01 TX ADDRESS REG.see constant arrays.
rf24_w_rx_address(nrf24l01_addr_1,0); //writes address number 1 into NRF24L01 RX ADDRESS REG PIPE 0.""".
rf24_flush_tx(); // clears NRF24L01 TX FIFO.
rf24_flush_rx(); // clears NRF24L01 RX FIFO.
rf24_clear_interrupt_flags(); //clears RX_DR , TX_DS & MAX_RT flags in STATUS REG.
}

void init_nrf24l01_rx(void)
{
rf24_mode = rf24_rx_mode; //stores which mode NRF24L01+ is in.1=PRX MODE , 0=TRX MODE.
TRISBbits.TRISB5=0; //make RB5 / PIN12 / CSN PIN an output for NRF24L01 CSN PIN.
TRISBbits.TRISB7=0; //make RB7 / PIN10 / CE PIN an output for NRF24L01 CE PIN.
TRISAbits.TRISA2=1; //make RA2 / PIN17 / IRQ PIN an input for interrupt.active low.
__delay_ms(10); //short power up delay (aprox 10mS). ce_pin = 0;
ce_pin = 0; //make CE pin low for standby mode.
csn_pin = 1; //make CSN pin high (CSN pin is active low).
rf24_w_register(config_reg, 0b00111111); //enable RX_DR interrupt only,CRC-2bytes,power up,PRX mode.
__delay_us(1500); //NRF24L01 bootup delay (aprox 1.5mS).
rf24_w_register(en_rxaddr_reg,0b00000010); //enable RX address on PIPE 1.
rf24_w_register(en_aa_reg,0b00000010); //enable AUTO ACK on PIPE 1 , ESB.
rf24_activate(); //activates ACK_PL ,NO_ACK_PL & RX_PL_WID see Datasheet.
rf24_w_register(feature_reg,0b00000111); //enables DYNAMIC PAYLOAD - ACK PAYLOAD - NO ACK PAYLOAD.
rf24_w_register(dynpd_reg,0b00000010); //enable DYNAMIC PAYLOAD on PIPE 1.
rf24_w_register(setup_aw_reg,address_width); //set address width(No. of bytes in address).see #define.
rf24_w_register(rf_setup_reg,0b00000111); //all as reset values except AIR DATA RATA set to 1Mbps.
rf24_w_register(rf_ch_reg,rf24_channel); //set RF CHANNEL to CHANNEL 20 . See #define.
rf24_w_rx_address(nrf24l01_addr_1,1); //writes address number 1 into NRF24L01 RX ADDRESS REG PIPE 1.
rf24_flush_tx(); // clears NRF24L01 TX FIFO.
rf24_flush_rx(); // clears NRF24L01 RX FIFO.
rf24_clear_interrupt_flags(); //clears RX_DR , TX_DS & MAX_RT flags in STATUS REG.
ce_pin=1; //make CE PIN low.Turns on receiver and wait for incomming payload.
}

void init_interrupts(void)
{
PIR1bits.SSPIF=0; //clear SPI interrupt flag.
INTCON2bits.RABPU=0; //enable PULL UPS on port A & port B.
WPUAbits.WPUA2=1; //turn on PULL UP on RA2 for interrupt pin(active low).
INTCON2bits.INTEDG2=0; //trigger interrupt on RA2/INT2/PIN10/IRQ PIN falling edge.
INTCON3bits.INT2IF=0; //clear interrupt flag for RA2/INT2/PIN10/IRQ PIN.
INTCON3bits.INT2IE=1; //enable interrupts on RA2/INT2/PIN10/IRQ PIN.
INTCONbits.PEIE=1; //enable peripheral interrupts.
INTCONbits.GIE=1; //enable all interrupts.
}

//************* SERVICE FUNCTIONS *************************************************
uint8 spi_tx_rx(uint8 tx_data)
{
SSPBUF=tx_data; //load spi buffer with next TX value.
while(!PIR1bits.SSPIF); //wait for spi interrupt flag = RX buffer full.
PIR1bits.SSPIF=0; //reset/clear spi interrupt flag, also delay a few cycles.
return SSPBUF; //return value received by SPI buffer.
}

uint8 rf24_r_register(uint8 reg_num) //reads NRF24L01 single data byte regs.
{
uint8 reg_val; //declare local varaible.
csn_pin = 0; //make CSN pin low.
rf24_status = spi_tx_rx(reg_num | 0b00000000); //send REG READ+REG NUMBER.read in STATUS.
reg_val = spi_tx_rx(dummy_byte); //send DUMMY BYTE read in value of register.
csn_pin = 1; //make CSN pin high.
return reg_val; //return value read from register.
}

void rf24_w_register(uint8 reg_num,uint8 reg_val) //writes NRF24L01 single data byte regs.
{
csn_pin = 0; //make CSN pin low.
rf24_status = spi_tx_rx(reg_num | 0b00100000); //send REG WRITE+REG NUMBER.read in STATUS.
spi_tx_rx(reg_val); //send value to register.
csn_pin = 1; //make CSN pin high.
}

void rf24_r_rx_payload(void) //reads NRF24L01 RX FIFO into FIFO_READ_BUFFER array.
{
uint8 count; //declare varaible for counting.
csn_pin = 0; //make CSN pin low.
rf24_status = spi_tx_rx(0b01100001); //send RX PAYLOAD READ instruction.read in STATUS.
for (count = 0; count < packet_width; count++) //loop for No. of bytes in packet(packet_width).
rf24_payload_read[count]=spi_tx_rx(dummy_byte); //read one byte of data to RX FIFO.send dummy byte.
csn_pin = 1; //make CSN pin high.
}

void rf24_w_tx_payload(void) //writes TX BUFFER array into NRF24L01 TX FIFO.
{
uint8 count; //declare varaible for counting.
csn_pin = 0; //make CSN pin low.
rf24_status = spi_tx_rx(0b10100000); //send TX PAYLOAD WRITE instruction.read in STATUS.
for (count = 0; count < packet_width; count++) //loop for No. of bytes in packet(packet_width).
spi_tx_rx(rf24_payload_write[count]); //send one byte of data to TX FIFO.
csn_pin = 1; //make CSN pin high.
ce_pin = 1; //make CE pin high.
__delay_us(12); //wait at least 10uS.
ce_pin = 0; //make CE pin low again.
}

void rf24_w_tx_address(const uint8*address_num) //writes address number xx into NRF24L01 TX ADDRESS REG.
{
uint8 count; //declare varaible for counting.
csn_pin = 0; //make CSN pin low.
rf24_status = spi_tx_rx(tx_addr_reg|0b00100000); //send TX ADDRESS+write instruction .read in STATUS.
for (count = 0; count < address_width; count++) //loop for No. of bytes in address(address_width).
spi_tx_rx(address_num[count]); //send one address byte to address register.
csn_pin = 1; //make CSN pin high.
}

void rf24_change_tx_address(const uint8*address_num) //changes TX ADDRESS to address number xx,LSB only.
{ //ONLY USE THIS IF FULL TX ADDRESS HAS ALREADY BEEN SENT.
csn_pin = 0; //make CSN pin low.
rf24_status = spi_tx_rx(tx_addr_reg|0b00100000); //send TX ADDRESS+write instruction .read in STATUS.
spi_tx_rx(address_num[0]); //send LSB address byte only to address register.
csn_pin = 1; //make CSN pin high.
}

void rf24_w_rx_address(const uint8*address_num,uint8 pipe_num)//writes address number xx into RX ADDRESS REG PIPE x.
{
uint8 count; //declare varaible for counting.
csn_pin = 0; //make CSN pin low.
rf24_status = spi_tx_rx((rx_addr_reg+pipe_num)|0b00100000);//send RX ADDR+PIPE+write instruction .read in STATUS.
for (count = 0; count < address_width; count++) //loop for No. of bytes in address(address_width).
spi_tx_rx(address_num[count]); //send one address byte to address register.
csn_pin = 1; //make CSN pin high.
}

void rf24_change_rx_address(const uint8*address_num,uint8 pipe_num)//changes RX ADDRESS to address No. xx PIPE x,LSB only.
{ //ONLY USE THIS IF FULL RX ADDRESS HAS ALREADY BEEN SENT.
csn_pin = 0; //make CSN pin low.
rf24_status = spi_tx_rx((rx_addr_reg+pipe_num)|0b00100000);//send RX ADDR+pipe+write instruction .read in STATUS.
spi_tx_rx(address_num[0]); //send LSB address byte only to address register.
csn_pin = 1; //make CSN pin high.
}

void rf24_flush_tx(void) // clears NRF24L01 TX FIFO.
{
csn_pin = 0; //make CSN pin low.
rf24_status = spi_tx_rx(0b11100001); //flush(clear) TX FIFO.
csn_pin = 1; //make CSN pin high.
}

void rf24_flush_rx(void) // clears NRF24L01 RX FIFO.
{
csn_pin=0; //make CSN pin low.
rf24_status = spi_tx_rx(0b11100010); //flush(clear) RX FIFO..
csn_pin=1; //make CSN pin high.
}

void rf24_activate(void) //activates ACK_PL ,NO_ACK_PL & RX_PL_WID see Datasheet.
{ //THIS ACTIVATES/DEACTIVATE(toggles).RESET VAL=DEACTIVATED.
csn_pin=0; //make CSN pin low.
rf24_status = spi_tx_rx(0b0101000); //send ACTIVATE instruction.
spi_tx_rx(0x73); //followed by 73h. See Datasheet.
csn_pin=1; //make CSN pin high.
}

uint8 rf24_r_rx_pl_wid(void) //reads No. of BYTES in TOP PAYLOAD in RX FIFO.
{
uint8 rx_fifo_len; //declare local varaible.
csn_pin=0; //make CSN pin low.
rf24_status=spi_tx_rx(0b01100000); //send READ RX FIFO LENGTH(bytes) instruction.
rx_fifo_len = spi_tx_rx(dummy_byte); //send dummy byte read in RX FIFO LENGTH.
csn_pin=1; //make CSN pin high.
return rx_fifo_len; //return number of bytes in top RX FIFO.
}

void rf24_w_ack_payload(uint8 pipe_num) //writes ACK PAYLOAD+PIPE NUM to TX FIFO in RX MODE ESB.
{
uint8 count; //declare local varaible.
csn_pin=0; //make CSN pin low.
rf24_status = spi_tx_rx(0b10101000+pipe_num);//WRITE ACK PAYLOAD+PIPE NUM instruction.read in status.
for (count = 0; count < packet_width; count++) //loop for No. of bytes in packet(packet_width).
spi_tx_rx(rf24_payload_write[count]); //send one byte of data to TX FIFO (RX MODE ESB).
csn_pin = 1; //make CSN pin high.

}

void rf24_w_tx_payload_no_ack(void) //writes NO ACK PAYLOAD to TX FIFO in TX MODE ESB.
{
uint8 count; //declare varaible for counting.
csn_pin = 0; //make CSN pin low.
rf24_status = spi_tx_rx(0b1011000); //send TX PAYLOAD NO ACK WRITE instruction.read in STATUS.
for (count = 0; count < packet_width; count++) //loop for No. of bytes in packet(packet_width).
spi_tx_rx(rf24_payload_write[count]); //send one byte of data to TX FIFO (TX MODE ESB) NO ACK.
csn_pin = 1; //make CSN pin high.
ce_pin = 1; //make CE pin high.
__delay_us(12); //wait at least 10uS.
ce_pin = 0; //make CE pin low again.
}

void rf24_nop (void) //writes NOP instruction,fast way to read STATUS REG.
{
csn_pin=0; //make CSN pin low.
rf24_status = spi_tx_rx(0b11111111); //send NOP instruction,read in status.
csn_pin=1; //make CSN pin high.
}

void rf24_clear_interrupt_flags(void) //clears RX_DR , TX_DS & MAX_RT flags in STATUS REG.
{
rf24_nop(); //send NOP instruction,read in status.
rf24_w_register(status_reg,rf24_status|0b011100000);//clear interrupt flags in STATUS REG.
} //YES! WRITE 1 TO CLEAR INTERRUPT FLAG.

//*************** ISR FUNCTION *****************************************************************************

void interrupt isr_function(void)
{
if(INTCON3bits.INT2IF) //if interrupt flag for RA2/INT2/PIN10/IRQ PIN.
{
ce_pin=0; //make CE low.NRF24L01+ enters standby mode.
uint8 del_count; //declare local varaible for delay counting.
rf24_nop(); //send NOP instruction,read in status.

if (rf24_status & 0b01000000) //if RX_DR (data received)interrupt flag is set.
{ //NB. RX_DR is DISABLED in INIT_NRF24L01_TX().PRX ONLY.
ce_pin = 0; //change NRF24L01+(PRX) into standby mode from RX mode.
rf24_r_rx_payload(); //reads NRF24L01 RX FIFO into FIFO_READ_BUFFER array.
rf24_flush_rx(); //make sure all NRF24L01 RX FIFO PAYLOADS are cleared.
rf24_flush_tx(); //make sure all NRF24L01 TX FIFO PAYLOADS are cleared.
rf24_w_ack_payload(0b00000010); //writes ACK PAYLOAD+PIPE N0.1 to TX FIFO in RX MODE ESB
ce_pin = 1; //change NRF24L01+(PRX) into RX mode from standby,takes 130uS.

red_led_pin=0; green_led_pin=1; //red led off, green led on.
for(del_count=0;del_count<20;del_count++) __delay_ms(25); //wait 25mS x 20 = 0.5 Sec.
red_led_pin=0; green_led_pin=0; //both LED'S OFF.
}

if (rf24_status & 0b00100000) //if TX_DS (data sent)interrupt flag is set.
{ //NB. TX_DS is DISABLED in INIT_NRF24L01_RX().PTX ONLY.
rf24_r_rx_payload(); //reads NRF24L01 RX FIFO into FIFO_READ_BUFFER array.
rf24_flush_rx(); //make sure all NRF24L01 RX FIFO PAYLOADS are cleared.
rf24_flush_tx(); //make sure all NRF24L01 TX FIFO PAYLOADS are cleared.

red_led_pin=0; green_led_pin=1; //red led off, green led on.
for(del_count=0;del_count<20;del_count++) __delay_ms(25); //wait 25mS x 20 = 0.5 Sec.
red_led_pin=0; green_led_pin=0; //both LED'S OFF.
}

if (rf24_status & 0b00010000) //if MAX_RT (max retransmits)interrupt flag is set.
{ //NB. MAX_RT is DISABLED in INIT_NRF24L01_RX().PTX ONLY
rf24_flush_rx(); //make sure all NRF24L01 RX FIFO PAYLOADS are cleared.
rf24_flush_tx(); //make sure all NRF24L01 TX FIFO PAYLOADS are cleared.

red_led_pin=1; green_led_pin=0; //red led on, green led off.
for(del_count=0;del_count<20;del_count++) __delay_ms(25); //wait 25mS x 20 = 0.5 Sec.
red_led_pin=0; green_led_pin=0; //both LED'S OFF.

}

rf24_clear_interrupt_flags(); //clears RX_DR , TX_DS & MAX_RT flags in STATUS REG.
INTCON3bits.INT2IF=0; //clear interrupt flag for RA2/INT2/PIN10/IRQ PIN.
}
}

//################### START OF MAIN FUNCTION ############################################
int main (void)
{
uint8 del_count; //declare local variable for delay counting.
uint8 count; //declare local variable for loop counting.

init_pic(); //sets up PIC ports + osc ect.
init_spi_master(); //sets up hardware SPI for com with NRF24l01+.
//NB. Choose ONE of the following TWO for TX MODE or RX MODE. Comment out the one not used.
init_nrf24l01_tx(); //sets up NRF24L01+ in TX MODE using ENHANCED SHOCKBURST and DYNAMIC PAYLOAD.
//init_nrf24l01_rx(); //sets up NRF24L01+ in RX MODE using ENHANCED SHOCKBURST and DYNAMIC PAYLOAD.
init_interrupts(); //sets up and enables all used interrupts.

for (count=0;count<packet_width;count++)
rf24_payload_read[count]=0; //clear PAYLOAD READ ARRAY to 0.
for (count=0;count<packet_width;count++)
rf24_payload_write[count]=rf24_test_data[count];//load PAYLOAD WRITE ARRAY with TEST DATA ARRAY.

red_led_pin=1; green_led_pin=1; //red led on, green led on.All inits are complete.
for(del_count=0;del_count<20;del_count++) __delay_ms(25); //wait 25mS x 20 = 0.5 Sec.
red_led_pin=0; green_led_pin=0; //both LED'S OFF.


while(1)
{
if (rf24_mode == rf24_tx_mode)
rf24_w_tx_payload(); //writes PAYLOAD WRITE ARRAY array into NRF24L01 TX FIFO and transmits data.

red_led_pin=0; green_led_pin=1; //red led off, green led on.
for(del_count=0;del_count<4;del_count++) __delay_ms(25); //wait 25mS x 4 = 0.1 Sec.
red_led_pin=0; green_led_pin=0; //both LED'S OFF.

for(del_count=0;del_count<20;del_count++) __delay_ms(25); //wait 25mS x 20 = 0.5 Sec.

rf24_flush_rx(); //make sure all NRF24L01 RX FIFO PAYLOADS are cleared.
rf24_flush_tx(); //make sure all NRF24L01 TX FIFO PAYLOADS are cleared.
}
}

Post Reply