#include "mcc_generated_files/mcc.h"
#include "nrf24l01.h"
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#define _XTAL_FREQ 8000000
/*
Main application
*/
void Initialize(void);
void InitializeIO(void);
void ToggleLED(void); //toggle the current state of the on-board LED
void main(void)
{
unsigned char data; //register to hold letter sent and received
unsigned int count; //counter for for loop
// Initialize the device
Initialize(); //initialize IO, UART, SPI, set up nRF24L01 as TX
while (1)
{
data = 4; //get data from UART
nrf24l01_write_tx_payload(&data, 1, true); //transmit received char over RF
//wait until the packet has been sent or the maximum number of retries has been reached
while(!(nrf24l01_irq_pin_active() && nrf24l01_irq_tx_ds_active()));
nrf24l01_irq_clear_all(); //clear all interrupts in the 24L01
nrf24l01_set_as_rx(true); //change the device to an RX to get the character back from the other 24L01
//wait a while to see if we get the data back (change the loop maximum and the lower if
// argument (should be loop maximum - 1) to lengthen or shorten this time frame
for(count = 0; count < 20000; count++)
{
//check to see if the data has been received. if so, get the data and exit the loop.
// if the loop is at its last count, assume the packet has been lost and set the data
// to go to the UART to "?". If neither of these is true, keep looping.
if((nrf24l01_irq_pin_active() && nrf24l01_irq_rx_dr_active()))
{
nrf24l01_read_rx_payload(&data, 1); //get the payload into data
break;
}
//if loop is on its last iteration, assume packet has been lost.
if(count == 19999)
data = '?';
}
nrf24l01_irq_clear_all(); //clear interrupts again
__delay_us(130);
nrf24l01_set_as_tx(); //resume normal operation as a TX
ToggleLED(); //toggle the on-board LED as visual indication that the loop has completed
}
}
void Initialize(void)
{
SYSTEM_Initialize();
InitializeIO(); //set up IO (directions and functions)
OpenSPI(SPI_FOSC_16, MODE_00, SMPMID); //open SPI1
nrf24l01_initialize_debug(false, 1, false); //initialize the 24L01 to the debug configuration as TX, 1 data byte, and auto-ack disabled
}
//initialize IO pins
void InitializeIO(void)
{
PORTAbits.RA0 = 1; //turn on LED
}
//toggles on-board LED
void ToggleLED(void)
{
PORTAbits.RA0 = ~PORTAbits.RA0; //invert the bit that controls the LED
}
/**
End of File
*/
#include "mcc_generated_files/mcc.h"
#include "nrf24l01.h"
#include <stdint.h>
#include <stdbool.h>
#include <spi.h>
#include <stddef.h>
#define _XTAL_FREQ 8000000
/*
Main application
*/
void Initialize(void);
void InitializeIO(void);
void ToggleLED(void); //toggle the current state of the on-board LED
void main(void)
{
unsigned char data; //register to hold letter sent and received
// Initialize the device
Initialize(); //initialize IO, UART, SPI, set up nRF24L01 as TX
while (1)
{
while(!(nrf24l01_irq_pin_active() && nrf24l01_irq_rx_dr_active()));
nrf24l01_read_rx_payload(&data, 1); //read the packet into data
nrf24l01_irq_clear_all(); //clear all interrupts in the 24L01
__delay_us(130); //wait for the other 24L01 to come from standby to RX
nrf24l01_set_as_tx(); //change the device to a TX to send back from the other 24L01
nrf24l01_write_tx_payload(&data, 1, true); //transmit received char over RF
//wait until the packet has been sent
while(!(nrf24l01_irq_pin_active() && nrf24l01_irq_tx_ds_active()));
nrf24l01_irq_clear_all(); //clear interrupts again
nrf24l01_set_as_rx(true); //resume normal operation as an RX
ToggleLED(); //toggle the on-board LED as visual indication that the loop has completed
}
}
void Initialize(void)
{
SYSTEM_Initialize();
InitializeIO(); //set up IO (directions and functions)
//
//OpenSPI(SPI_FOSC_16, MODE_00, SMPMID); //open SPI1
nrf24l01_initialize_debug(true, 1, false); //initialize the 24L01 to the debug configuration as TX, 1 data byte, and auto-ack disabled
}
//initialize IO pins
void InitializeIO(void)
{
PORTAbits.RA0 = 1; //turn on LED
}
//toggles on-board LED
void ToggleLED(void)
{
PORTAbits.RA0 = ~PORTAbits.RA0; //invert the bit that controls the LED
}
/**
End of File
*/
#include "nrf24l01.h"
#include "mcc_generated_files/mcc.h"
#include <xc.h> // include processor files - each processor file is guarded.
//Arguments except opt_rx_standby_mode fill the actual register they are named
// after. Registers that do not need to be initialized are not included here.
//The argument opt_rx_active_mode is only used if the user is initializing the
// 24L01 as a receiver. If the argument is false, the receiver will remain in
// standby mode and not monitor for packets. If the argument is true, the CE
// pin will be set and the 24L01 will monitor for packets. In TX mode, the value
// of this argument is insignificant.
//If the user wants to leave any 1-byte register in its default state, simply put
// as that register's argument nrf24l01_<reg>_DEFAULT_VAL, where <reg> is the register
// name.
//If the user wants to leave any of the 5-byte registers RX_ADDR_P0, RX_ADDR_P1, or
// TX_ADDR in its default state, simply put NULL in the argument for that address value.
#define _XTAL_FREQ 8000000
void nrf24l01_initialize(unsigned char config,
unsigned char opt_rx_active_mode,
unsigned char en_aa,
unsigned char en_rxaddr,
unsigned char setup_aw,
unsigned char setup_retr,
unsigned char rf_ch,
unsigned char rf_setup,
unsigned char * rx_addr_p0,
unsigned char * rx_addr_p1,
unsigned char rx_addr_p2,
unsigned char rx_addr_p3,
unsigned char rx_addr_p4,
unsigned char rx_addr_p5,
unsigned char * tx_addr,
unsigned char rx_pw_p0,
unsigned char rx_pw_p1,
unsigned char rx_pw_p2,
unsigned char rx_pw_p3,
unsigned char rx_pw_p4,
unsigned char rx_pw_p5)
{
unsigned char data[5];
data[0] = en_aa;
nrf24l01_write_register(nrf24l01_EN_AA, data, 1);
data[0] = en_rxaddr;
nrf24l01_write_register(nrf24l01_EN_RXADDR, data, 1);
data[0] = setup_aw;
nrf24l01_write_register(nrf24l01_SETUP_AW, data, 1);
data[0] = setup_retr;
nrf24l01_write_register(nrf24l01_SETUP_RETR, data, 1);
data[0] = rf_ch;
nrf24l01_write_register(nrf24l01_RF_CH, data, 1);
data[0] = rf_setup;
nrf24l01_write_register(nrf24l01_RF_SETUP, data, 1);
if(rx_addr_p0 != NULL)
nrf24l01_set_rx_addr(rx_addr_p0, 5, 0);
else
{
data[0] = nrf24l01_RX_ADDR_P0_B0_DEFAULT_VAL;
data[1] = nrf24l01_RX_ADDR_P0_B1_DEFAULT_VAL;
data[2] = nrf24l01_RX_ADDR_P0_B2_DEFAULT_VAL;
data[3] = nrf24l01_RX_ADDR_P0_B3_DEFAULT_VAL;
data[4] = nrf24l01_RX_ADDR_P0_B4_DEFAULT_VAL;
nrf24l01_set_rx_addr(data, 5, 0);
}
if(rx_addr_p1 != NULL)
nrf24l01_set_rx_addr(rx_addr_p1, 5, 1);
else
{
data[0] = nrf24l01_RX_ADDR_P1_B0_DEFAULT_VAL;
data[1] = nrf24l01_RX_ADDR_P1_B1_DEFAULT_VAL;
data[2] = nrf24l01_RX_ADDR_P1_B2_DEFAULT_VAL;
data[3] = nrf24l01_RX_ADDR_P1_B3_DEFAULT_VAL;
data[4] = nrf24l01_RX_ADDR_P1_B4_DEFAULT_VAL;
nrf24l01_set_rx_addr(data, 5, 1);
}
data[0] = rx_addr_p2;
nrf24l01_set_rx_addr(data, 1, 2);
data[0] = rx_addr_p3;
nrf24l01_set_rx_addr(data, 1, 3);
data[0] = rx_addr_p4;
nrf24l01_set_rx_addr(data, 1, 4);
data[0] = rx_addr_p5;
nrf24l01_set_rx_addr(data, 1, 5);
if(tx_addr != NULL)
nrf24l01_set_tx_addr(tx_addr, 5);
else
{
data[0] = nrf24l01_TX_ADDR_B0_DEFAULT_VAL;
data[1] = nrf24l01_TX_ADDR_B1_DEFAULT_VAL;
data[2] = nrf24l01_TX_ADDR_B2_DEFAULT_VAL;
data[3] = nrf24l01_TX_ADDR_B3_DEFAULT_VAL;
data[4] = nrf24l01_TX_ADDR_B4_DEFAULT_VAL;
nrf24l01_set_tx_addr(data, 5);
}
data[0] = rx_pw_p0;
nrf24l01_write_register(nrf24l01_RX_PW_P0, data, 1);
data[0] = rx_pw_p1;
nrf24l01_write_register(nrf24l01_RX_PW_P1, data, 1);
data[0] = rx_pw_p2;
nrf24l01_write_register(nrf24l01_RX_PW_P2, data, 1);
data[0] = rx_pw_p3;
nrf24l01_write_register(nrf24l01_RX_PW_P3, data, 1);
data[0] = rx_pw_p4;
nrf24l01_write_register(nrf24l01_RX_PW_P4, data, 1);
data[0] = rx_pw_p5;
nrf24l01_write_register(nrf24l01_RX_PW_P5, data, 1);
if((config & nrf24l01_CONFIG_PWR_UP) != 0)
nrf24l01_power_up_param(opt_rx_active_mode, config);
else
nrf24l01_power_down_param(config);
}
//initializes the 24L01 to all default values except the PWR_UP and PRIM_RX bits
//this function also disables the auto-ack feature on the chip (EN_AA register is 0)
//bool rx is true if the device should be a receiver and false if it should be
// a transmitter.
//unsigned char payload_width is the payload width for pipe 0. All other pipes
// are left in their default (disabled) state.
//bool enable_auto_ack controls the auto ack feature on pipe 0. If true, auto-ack will
// be enabled. If false, auto-ack is disabled.
void nrf24l01_initialize_debug(bool rx, unsigned char p0_payload_width, bool enable_auto_ack)
{
unsigned char config;
unsigned char en_aa;
config = nrf24l01_CONFIG_DEFAULT_VAL | nrf24l01_CONFIG_PWR_UP;
if(enable_auto_ack != false)
en_aa = nrf24l01_EN_AA_ENAA_P0;
else
en_aa = nrf24l01_EN_AA_ENAA_NONE;
if(rx == true)
config = config | nrf24l01_CONFIG_PRIM_RX;
nrf24l01_initialize(config,
true,
en_aa,
nrf24l01_EN_RXADDR_DEFAULT_VAL,
nrf24l01_SETUP_AW_DEFAULT_VAL,
nrf24l01_SETUP_RETR_DEFAULT_VAL,
nrf24l01_RF_CH_DEFAULT_VAL,
nrf24l01_RF_SETUP_DEFAULT_VAL,
NULL,
NULL,
nrf24l01_RX_ADDR_P2_DEFAULT_VAL,
nrf24l01_RX_ADDR_P3_DEFAULT_VAL,
nrf24l01_RX_ADDR_P4_DEFAULT_VAL,
nrf24l01_RX_ADDR_P5_DEFAULT_VAL,
NULL,
p0_payload_width,
nrf24l01_RX_PW_P1_DEFAULT_VAL,
nrf24l01_RX_PW_P2_DEFAULT_VAL,
nrf24l01_RX_PW_P3_DEFAULT_VAL,
nrf24l01_RX_PW_P4_DEFAULT_VAL,
nrf24l01_RX_PW_P5_DEFAULT_VAL);
}
//initializes only the CONFIG register and pipe 0's payload width
//the primary purpose of this function is to allow users with microcontrollers with
// extremely small program memories to still be able to init their 24L01. This code
// should have a smaller footprint than the above init functions.
//when using this method, the 24L01 MUST have its default configuration loaded
// in all registers to work. It is recommended that the device be reset or
// have its power cycled immediately before this code is run.
//in normal circumstances, the user should use nrf24l01_initialize() rather than this
// function, since this function does not set all of the register values.
void nrf24l01_initialize_debug_lite(bool rx, unsigned char p0_payload_width)
{
unsigned char config;
config = nrf24l01_CONFIG_DEFAULT_VAL;
if(rx != false)
config |= nrf24l01_CONFIG_PRIM_RX;
nrf24l01_write_register(nrf24l01_RX_PW_P0, &p0_payload_width, 1);
nrf24l01_power_up_param(true, config);
}
//powers up the 24L01 with all necessary delays
//this function takes the existing contents of the CONFIG register and sets the PWR_UP
//the argument rx_active_mode is only used if the user is setting up the
// 24L01 as a receiver. If the argument is false, the receiver will remain in
// standby mode and not monitor for packets. If the argument is true, the CE
// pin will be set and the 24L01 will monitor for packets. In TX mode, the value
// of this argument is insignificant.
//note: if the read value of the CONFIG register already has the PWR_UP bit set, this function
// exits in order to not make an unecessary register write.
void nrf24l01_power_up(bool rx_active_mode)
{
unsigned char config;
nrf24l01_read_register(nrf24l01_CONFIG, &config, 1);
if((config & nrf24l01_CONFIG_PWR_UP) != 0)
return;
config |= nrf24l01_CONFIG_PWR_UP;
nrf24l01_write_register(nrf24l01_CONFIG, &config, 1);
__delay_us(1500);
if((config & nrf24l01_CONFIG_PRIM_RX) == 0)
nrf24l01_clear_ce();
else
{
if(rx_active_mode != false)
nrf24l01_set_ce();
else
nrf24l01_clear_ce();
}
}
//powers up the 24L01 with all necessary delays
//this function allows the user to set the contents of the CONFIG register, but the function
// sets the PWR_UP bit in the CONFIG register, so the user does not need to.
//the argument rx_active_mode is only used if the user is setting up the
// 24L01 as a receiver. If the argument is false, the receiver will remain in
// standby mode and not monitor for packets. If the argument is true, the CE
// pin will be set and the 24L01 will monitor for packets. In TX mode, the value
// of this argument is insignificant.
void nrf24l01_power_up_param(bool rx_active_mode, unsigned char config)
{
unsigned char test, test2;
config |= nrf24l01_CONFIG_PWR_UP;
nrf24l01_write_register(nrf24l01_CONFIG, &config, 1);
__delay_us(1500);
if((config & nrf24l01_CONFIG_PRIM_RX) == 0)
nrf24l01_clear_ce();
else
{
if(rx_active_mode != false)
nrf24l01_set_ce();
else
nrf24l01_clear_ce();
}
}
//powers down the 24L01
//this function takes the existing contents of the CONFIG register and simply
// clears the PWR_UP bit in the CONFIG register.
//note: if the read value of the CONFIG register already has the PWR_UP bit cleared, this
// function exits in order to not make an unecessary register write.
void nrf24l01_power_down()
{
unsigned char config;
nrf24l01_read_register(nrf24l01_CONFIG, &config, 1);
if((config & nrf24l01_CONFIG_PWR_UP) == 0)
return;
config &= (~nrf24l01_CONFIG_PWR_UP);
nrf24l01_write_register(nrf24l01_CONFIG, &config, 1);
nrf24l01_clear_ce();
}
//powers down the 24L01
//this function allows the user to set the contents of the CONFIG register, but the function
// clears the PWR_UP bit in the CONFIG register, so the user does not need to.
void nrf24l01_power_down_param(unsigned char config)
{
config &= (~nrf24l01_CONFIG_PWR_UP);
nrf24l01_write_register(nrf24l01_CONFIG, &config, 1);
nrf24l01_clear_ce();
}
//sets up the 24L01 as a receiver with all necessary delays
//this function takes the existing contents of the CONFIG register and sets the PRIM_RX
// bit in the CONFIG register.
//if the argument rx_active_mode is false, the receiver will remain in standby mode
// and not monitor for packets. If the argument is true, the CE pin will be set
// and the 24L01 will monitor for packets.
//note: if the read value of the CONFIG register already has the PRIM_RX bit set, this function
// exits in order to not make an unecessary register write.
void nrf24l01_set_as_rx(bool rx_active_mode)
{
unsigned char config;
unsigned char status;
status = nrf24l01_read_register(0, &config, 1);
if((config & nrf24l01_CONFIG_PRIM_RX) != 0)
return;
config |= nrf24l01_CONFIG_PRIM_RX;
nrf24l01_write_register(nrf24l01_CONFIG, &config, 1);
if(rx_active_mode != false)
nrf24l01_set_ce();
else
nrf24l01_clear_ce();
}
//sets up the 24L01 as a receiver with all necessary delays
//this function allows the user to set the contents of the CONFIG register, but the function
// sets the PRIM_RX bit in the CONFIG register, so the user does not need to.
//if the argument rx_active_mode is false, the receiver will remain in standby mode
// and not monitor for packets. If the argument is true, the CE pin will be set
// and the 24L01 will monitor for packets.
void nrf24l01_set_as_rx_param(bool rx_active_mode, unsigned char config)
{
config |= nrf24l01_CONFIG_PRIM_RX;
if((config & nrf24l01_CONFIG_PWR_UP) != 0)
nrf24l01_power_up_param(rx_active_mode, config);
else
nrf24l01_power_down_param(config);
}
//takes a 24L01 that is already in RX standby mode and puts it in active RX mode
void nrf24l01_rx_standby_to_active()
{
nrf24l01_set_ce();
}
//takes a 24L01 that is already in active RX mode and puts it in RX standy mode
void nrf24l01_rx_active_to_standby()
{
nrf24l01_clear_ce();
}
//sets up the 24L01 as a transmitter
//this function takes the existing contents of the CONFIG register and simply
// clears the PRIM_RX bit in the CONFIG register.
//note: if the read value of the CONFIG register already has the PRIM_RX bit cleared, this
// function exits in order to not make an unecessary register write.
void nrf24l01_set_as_tx()
{
unsigned char config;
nrf24l01_read_register(nrf24l01_CONFIG, &config, 1);
if((config & nrf24l01_CONFIG_PRIM_RX) == 0)
return;
config &= (~nrf24l01_CONFIG_PRIM_RX);
nrf24l01_write_register(nrf24l01_CONFIG, &config, 1);
nrf24l01_clear_ce();
}
//sets up the 24L01 as a transmitter
//this function allows the user to set the contents of the CONFIG register, but the function
// clears the PRIM_RX bit in the CONFIG register, so the user does not need to.
void nrf24l01_set_as_tx_param(unsigned char config)
{
config &= ~(nrf24l01_CONFIG_PRIM_RX);
if((config & nrf24l01_CONFIG_PWR_UP) != 0)
nrf24l01_power_up_param(false, config);
else
nrf24l01_power_down_param(config);
}
//executes the W_REGISTER SPI operation
//unsigned char regnumber indicates the register number assigned by the nrf24l01 specification.
// For regnumber values, see section titled "register definitions" in nrf24l01.h.
//unsigned char * data should be of size 1 for all register writes except for RX_ADDR_P0, RX_ADDR_P1,
// and TX_ADDR. The size of data should be set according to the user-specified size of the address
// length for the register the address is being sent to.
//unsigned int len is always the size of unsigned char * data. For example, if data is declared as
// data[6], len should equal 6.
//returns the value of the STATUS register
unsigned char nrf24l01_write_register(unsigned char regnumber, unsigned char * data, unsigned int len)
{
return nrf24l01_execute_command(nrf24l01_W_REGISTER | (regnumber & nrf24l01_W_REGISTER_DATA), data, len, false);
}
//executes the R_REGISTER SPI operation
//unsigned char regnumber indicates the register number assigned by the nrf24l01 specification.
// For regnumber values, see section titled "register definitions" in nrf24l01.h.
//unsigned char * data should be of size 1 for all register writes except for RX_ADDR_P0, RX_ADDR_P1,
// and TX_ADDR. The size of data should be set according to the user-specified size of the address
// length for the register the address is being read from.
//unsigned int len is always the size of unsigned char * data. For example, if data is declared as
// data[6], len = 6.
//returns the value of the STATUS register
unsigned char nrf24l01_read_register(unsigned char regnumber, unsigned char * data, unsigned int len)
{
return nrf24l01_execute_command(regnumber & nrf24l01_R_REGISTER_DATA, data, len, true);
}
//executes the W_TX_PAYLOAD operation
//unsigned char * data is the actual payload to be sent to the nrf24l01.
//unsigned int len is the length of the payload being sent (this should be sized
// according to the payload length specified by the receiving nrf24l01).
//if bool transmit is true, the nrf24l01 immediately transmits the data in the payload.
// if false, the user must use the nrf24l01_transmit() function to send the payload.
//returns the value of the STATUS register
unsigned char nrf24l01_write_tx_payload(unsigned char * data, unsigned int len, bool transmit)
{
unsigned char status;
status = nrf24l01_execute_command(nrf24l01_W_TX_PAYLOAD, data, len, false);
if(transmit == true)
nrf24l01_transmit();
return status;
}
//executes the R_RX_PAYLOAD instruction
//unsigned char * data is the actual payload that has been received by the nrf24l01.
// The user must size data according to the payload width specified to the nrf24l01.
// This variable is filled by this function, so individual byte values need not be
// initialized by the user.
//unsigned int len is the length of the payload being clocked out of the nrf24l01 (this
// should be sized according to the payload length specified to the nrf24l01).
//returns the value of the STATUS register
unsigned char nrf24l01_read_rx_payload(unsigned char * data, unsigned int len)
{
unsigned char status;
nrf24l01_clear_ce();
status = nrf24l01_execute_command(nrf24l01_R_RX_PAYLOAD, data, len, true);
nrf24l01_set_ce();
return status;
}
//executes the FLUSH_TX SPI operation
//this funciton empties the contents of the TX FIFO
//returns the value of the STATUS register
unsigned char nrf24l01_flush_tx()
{
return nrf24l01_execute_command(nrf24l01_FLUSH_TX, NULL, 0, true);
}
//executes the FLUSH_RX SPI operation
//this funciton empties the contents of the RX FIFO
//returns the value of the STATUS register
unsigned char nrf24l01_flush_rx()
{
return nrf24l01_execute_command(nrf24l01_FLUSH_RX, NULL, 0, true);
}
//executes the REUSE_TX_PL SPI operation
//this funciton allows the user to constantly send a packet repeatedly when issued.
//returns the value of the STATUS register
unsigned char nrf24l01_reuse_tx_pl()
{
return nrf24l01_execute_command(nrf24l01_REUSE_TX_PL, NULL, 0, true);
}
//executes the FLUSH_TX SPI operation
//this funciton does nothing
//returns the value of the STATUS register
unsigned char nrf24l01_nop()
{
return nrf24l01_execute_command(nrf24l01_NOP, NULL, 0, true);
}
//transmits the current tx payload
void nrf24l01_transmit()
{
nrf24l01_set_ce();
__delay_us(10);
nrf24l01_clear_ce();
}
//clears the pin on the host microcontroller that is attached to the 24l01's CE pin
void nrf24l01_clear_ce()
{
nrf24l01_CE_IOREGISTER &= ~nrf24l01_CE_PINMASK;
}
//sets the pin on the host microcontroller that is attached to the 24l01's CE pin
void nrf24l01_set_ce()
{
nrf24l01_CE_IOREGISTER |= nrf24l01_CE_PINMASK;
}
//returns true if CE is high, false if not
bool nrf24l01_ce_pin_active()
{
if((nrf24l01_CE_IOREGISTER & nrf24l01_CE_PINMASK) != 0)
return true;
else
return false;
}
//sets the pin on the host microcontroller that is attached to the 24l01's CSN pin
void nrf24l01_clear_csn()
{
nrf24l01_CSN_IOREGISTER &= ~nrf24l01_CSN_PINMASK;
}
//clears the pin on the host microcontroller that is attached to the 24l01's CSN pin
void nrf24l01_set_csn()
{
nrf24l01_CSN_IOREGISTER |= nrf24l01_CSN_PINMASK;
}
//returns true if CSN is high, false if not
bool nrf24l01_csn_pin_active()
{
if((nrf24l01_CSN_IOREGISTER & nrf24l01_CSN_PINMASK) != 0)
return true;
else
return false;
}
//sets the TX address in the TX_ADDR register
//unsigned char * address is the actual address to be used. It should be sized
// according to the tx_addr length specified to the nrf24l01.
//unsigned int len is the length of the address. Its value should be specified
// according to the tx_addr length specified to the nrf24l01.
void nrf24l01_set_tx_addr(unsigned char * address, unsigned int len)
{
nrf24l01_write_register(nrf24l01_TX_ADDR, address, len);
}
//sets the RX address in the RX_ADDR register that is offset by rxpipenum
//unsigned char * address is the actual address to be used. It should be sized
// according to the rx_addr length that is being filled.
//unsigned int len is the length of the address. Its value should be specified
// according to the rx_addr length specified to the nrf24l01.
//unsigned char rxpipenum is the pipe number (zero to five) whose address is being
// specified. If an invalid address (greater than five) is supplied, the function
// does nothing.
void nrf24l01_set_rx_addr(unsigned char * address, unsigned int len, unsigned char rxpipenum)
{
if(rxpipenum > 5)
return;
nrf24l01_write_register(nrf24l01_RX_ADDR_P0 + rxpipenum, address, len);
}
//sets the RX payload width on the pipe offset by rxpipenum
//unsigned char payloadwidth is the length of the payload for the pipe referenced in
// rxpipenum. It must be less than or equal to 32. If an invalid payload width is
// specified, the function does nothing.
//unsigned char rxpipenum is the pipe number (zero to five) whose address is being
// specified. If an invalid address (greater than five) is supplied, the function
// does nothing.
void nrf24l01_set_rx_pw(unsigned char payloadwidth, unsigned char rxpipenum)
{
if((rxpipenum > 5) || (payloadwidth > 32))
return;
nrf24l01_write_register(nrf24l01_RX_PW_P0 + rxpipenum, &payloadwidth, 1);
}
//gets the RX payload width on the pipe offset by rxpipenum
//unsigned char rxpipenum is the pipe number (zero to five) whose address is being
// specified. If an invalid address (greater than five) is supplied, the function
// does nothing.
unsigned char nrf24l01_get_rx_pw(unsigned char rxpipenum)
{
unsigned char data;
if((rxpipenum > 5))
return 0;
nrf24l01_read_register(nrf24l01_RX_PW_P0 + rxpipenum, &data, 1);
return data;
}
//returns the value of the CONFIG register
unsigned char nrf24l01_get_config()
{
unsigned char data;
nrf24l01_read_register(nrf24l01_CONFIG, &data, 1);
return data;
}
//sets the value of the CONFIG register
void nrf24l01_set_config(unsigned char config)
{
nrf24l01_write_register(nrf24l01_CONFIG, &config, 1);
}
//returns the current RF channel in RF_CH register
unsigned char nrf24l01_get_rf_ch()
{
unsigned char data;
nrf24l01_read_register(nrf24l01_RF_CH, &data, 1);
return data;
}
//unsigned char channel is the channel to be changed to.
void nrf24l01_set_rf_ch(unsigned char channel)
{
unsigned char data;
data = channel & ~nrf24l01_RF_CH_RESERVED;
nrf24l01_write_register(nrf24l01_RF_CH, &data, 1);
}
//returns the value of the OBSERVE_TX register
unsigned char nrf24l01_get_observe_tx()
{
unsigned char data;
nrf24l01_read_register(nrf24l01_OBSERVE_TX, &data, 1);
return data;
}
//returns the current PLOS_CNT value in OBSERVE_TX register
unsigned char nrf24l01_get_plos_cnt()
{
unsigned char data;
nrf24l01_read_register(nrf24l01_OBSERVE_TX, &data, 1);
return ((data & nrf24l01_OBSERVE_TX_PLOS_CNT) >> 4);
}
//clears the PLOS_CNT field of the OBSERVE_TX register
//this function makes a read of the current value of RF_CH and
// simply writes it back to the register, clearing PLOS_CNT
void nrf24l01_clear_plos_cnt()
{
unsigned char data;
nrf24l01_read_register(nrf24l01_RF_CH, &data, 1);
nrf24l01_write_register(nrf24l01_RF_CH, &data, 1);
}
//clears the PLOS_CNT field of the OBSERVE_TX register
//this function allows the user to set the RF_CH register by using
// the argument in the function during the PLOS_CNT clearing process
void nrf24l01_clear_plos_cnt_param(unsigned char rf_ch)
{
nrf24l01_write_register(nrf24l01_RF_CH, &rf_ch, 1);
}
//returns the current ARC_CNT value in OBSERVE_TX register
unsigned char nrf24l01_get_arc_cnt()
{
unsigned char data;
nrf24l01_read_register(nrf24l01_OBSERVE_TX, &data, 1);
return (data & nrf24l01_OBSERVE_TX_ARC_CNT);
}
//returns true if auto-ack is enabled on the pipe that is offset by rxpipenum
//unsigned char rxpipenum is the pipe number (zero to five) whose address is being
// specified. If an invalid address (greater than five) is supplied, the function
// returns false.
bool nrf24l01_aa_enabled(unsigned char rxpipenum)
{
unsigned char data;
if(rxpipenum > 5)
return false;
nrf24l01_read_register(nrf24l01_EN_AA, &data, 1);
return (data & (0x01 << rxpipenum));
}
//enables auto-ack is enabled on the pipe that is offset by rxpipenum
//unsigned char rxpipenum is the pipe number (zero to five) whose address is being
// does nothing.
void nrf24l01_aa_enable(unsigned char rxpipenum)
{
unsigned char data;
if(rxpipenum > 5)
return;
nrf24l01_read_register(nrf24l01_EN_AA, &data, 1);
if((data & (0x01 << rxpipenum)) != 0)
return;
data |= 0x01 << rxpipenum;
nrf24l01_write_register(nrf24l01_EN_AA, &data, 1);
}
//disables auto-ack is enabled on the pipe that is offset by rxpipenum
//unsigned char rxpipenum is the pipe number (zero to five) whose address is being
// does nothing.
void nrf24l01_aa_disable(unsigned char rxpipenum)
{
unsigned char data;
if(rxpipenum > 5)
return;
nrf24l01_read_register(nrf24l01_EN_AA, &data, 1);
if((data & (0x01 << rxpipenum)) == 0)
return;
data &= ~(0x01 << rxpipenum);
nrf24l01_write_register(nrf24l01_EN_AA, &data, 1);
}
//returns true if the pipe is enabled that is offset by rxpipenum
//unsigned char rxpipenum is the pipe number (zero to five) whose address is being
// specified. If an invalid address (greater than five) is supplied, the function
// returns false.
bool nrf24l01_rx_pipe_enabled(unsigned char rxpipenum)
{
unsigned char data;
if((rxpipenum > 5))
return false;
nrf24l01_read_register(nrf24l01_EN_RXADDR, &data, 1);
return (data & (0x01 << rxpipenum));
}
//enables the pipe that is offset by rxpipenum
//unsigned char rxpipenum is the pipe number (zero to five) whose address is being
// specified. If an invalid address (greater than five) is supplied, the function
// does nothing.
void nrf24l01_rx_pipe_enable(unsigned char rxpipenum)
{
unsigned char data;
if(rxpipenum > 5)
return;
nrf24l01_read_register(nrf24l01_EN_RXADDR, &data, 1);
if((data & (0x01 << rxpipenum)) != 0)
return;
data |= 0x01 << rxpipenum;
nrf24l01_write_register(nrf24l01_EN_RXADDR, &data, 1);
}
//disables the pipe that is offset by rxpipenum
//unsigned char rxpipenum is the pipe number (zero to five) whose address is being
// specified. If an invalid address (greater than five) is supplied, the function
// does nothing.
void nrf24l01_rx_pipe_disable(unsigned char rxpipenum)
{
unsigned char data;
if(rxpipenum > 5)
return;
nrf24l01_read_register(nrf24l01_EN_RXADDR, &data, 1);
if((data & (0x01 << rxpipenum)) == 0)
return;
data &= ~(0x01 << rxpipenum);
nrf24l01_write_register(nrf24l01_EN_RXADDR, &data, 1);
}
//returns the status of the CD register (true if carrier detect [CD] is
// active, false if not)
bool nrf24l01_cd_active()
{
unsigned char data;
nrf24l01_read_register(nrf24l01_CD, &data, 1);
return data;
}
//returns the value of the FIFO_STATUS register
unsigned char nrf24l01_get_fifo_status()
{
unsigned char data;
nrf24l01_read_register(nrf24l01_FIFO_STATUS, &data, 1);
return data;
}
//return the value of the status register
unsigned char nrf24l01_get_status()
{
return nrf24l01_nop();
}
//returns true if TX_REUSE bit in FIFO_STATUS register is set, false otherwise
bool nrf24l01_fifo_tx_reuse()
{
unsigned char data;
nrf24l01_read_register(nrf24l01_FIFO_STATUS, &data, 1);
return (bool)(data & nrf24l01_FIFO_STATUS_TX_REUSE);
}
//returns true if TX_FULL bit in FIFO_STATUS register is set, false otherwise
bool nrf24l01_fifo_tx_full()
{
unsigned char data;
nrf24l01_read_register(nrf24l01_FIFO_STATUS, &data, 1);
return (bool)(data & nrf24l01_FIFO_STATUS_TX_FULL);
}
//returns true if TX_EMPTY bit in FIFO_STATUS register is set, false otherwise
bool nrf24l01_fifo_tx_empty()
{
unsigned char data;
nrf24l01_read_register(nrf24l01_FIFO_STATUS, &data, 1);
return (bool)(data & nrf24l01_FIFO_STATUS_TX_EMPTY);
}
//returns true if RX_FULL bit in FIFO_STATUS register is set, false otherwise
bool nrf24l01_fifo_rx_full()
{
unsigned char data;
nrf24l01_read_register(nrf24l01_FIFO_STATUS, &data, 1);
return (bool)(data & nrf24l01_FIFO_STATUS_RX_FULL);
}
//returns true if RX_EMPTYE bit in FIFO_STATUS register is set, false otherwise
bool nrf24l01_fifo_rx_empty()
{
unsigned char data;
nrf24l01_read_register(nrf24l01_FIFO_STATUS, &data, 1);
return (bool)(data & nrf24l01_FIFO_STATUS_RX_EMPTY);
}
//returns true if IRQ pin is low, false otherwise
bool nrf24l01_irq_pin_active()
{
if((nrf24l01_IRQ_IOREGISTER & nrf24l01_IRQ_PINMASK) != 0)
return false;
else
return true;
}
//returns true if RX_DR interrupt is active, false otherwise
bool nrf24l01_irq_rx_dr_active()
{
return (nrf24l01_get_status() & nrf24l01_STATUS_RX_DR);
}
//returns true if TX_DS interrupt is active, false otherwise
bool nrf24l01_irq_tx_ds_active()
{
return (nrf24l01_get_status() & nrf24l01_STATUS_TX_DS);
}
//returns true if MAX_RT interrupt is active, false otherwise
bool nrf24l01_irq_max_rt_active()
{
return (nrf24l01_get_status() & nrf24l01_STATUS_MAX_RT);
}
//clear all interrupts in the status register
void nrf24l01_irq_clear_all()
{
unsigned char data = nrf24l01_STATUS_RX_DR | nrf24l01_STATUS_TX_DS | nrf24l01_STATUS_MAX_RT;
nrf24l01_write_register(nrf24l01_STATUS, &data, 1);
}
//clears only the RX_DR interrupt
void nrf24l01_irq_clear_rx_dr()
{
unsigned char data = nrf24l01_STATUS_RX_DR;
nrf24l01_write_register(nrf24l01_STATUS, &data, 1);
}
//clears only the TX_DS interrupt
void nrf24l01_irq_clear_tx_ds()
{
unsigned char data = nrf24l01_STATUS_TX_DS;
nrf24l01_write_register(nrf24l01_STATUS, &data, 1);
}
//clears only the MAX_RT interrupt
void nrf24l01_irq_clear_max_rt()
{
unsigned char data = nrf24l01_STATUS_MAX_RT;
nrf24l01_write_register(nrf24l01_STATUS, &data, 1);
}
//returns the current pipe in the 24L01's STATUS register
unsigned char nrf24l01_get_rx_pipe()
{
return nrf24l01_get_rx_pipe_from_status(nrf24l01_get_status());
}
unsigned char nrf24l01_get_rx_pipe_from_status(unsigned char status)
{
return ((status & 0xE) >> 1);
}
//flush both fifos and clear interrupts
void nrf24l01_clear_flush()
{
nrf24l01_flush_rx();
nrf24l01_flush_tx();
nrf24l01_irq_clear_all();
}
//unsigned char * data must be at least 35 bytes long
void nrf24l01_get_all_registers(unsigned char * data)
{
unsigned int outer;
unsigned int inner;
unsigned int dataloc = 0;
unsigned char buffer[5];
for(outer = 0; outer <= 0x17; outer++)
{
nrf24l01_read_register(outer, buffer, 5);
for(inner = 0; inner < 5; inner++)
{
if(inner >= 1 && (outer != 0x0A && outer != 0x0B && outer != 0x10))
break;
data[dataloc] = buffer[inner];
dataloc++;
}
}
}
//low-level spi send function for library use
//the user should not call this function directly, but rather use one of the 8 SPI data instructions
unsigned char nrf24l01_execute_command(unsigned char instruction, unsigned char * data, unsigned int len, bool copydata)
{
unsigned char status;
nrf24l01_clear_csn();
status = instruction;
nrf24l01_spi_send_read(&status, 1, true);
nrf24l01_spi_send_read(data, len, copydata);
nrf24l01_set_csn();
return status;
}
//low-level spi send function for library use
//the user should not call this function directly, but rather use one of the 8 SPI data instructions
void nrf24l01_spi_send_read(unsigned char * data, unsigned int len, bool copydata)
{
unsigned int count;
unsigned char tempbyte;
for(count = 0; count < len; count++)
{
if(copydata != false)
data[count] = spi_send_read_byte(data[count]);
else
{
tempbyte = data[count];
spi_send_read_byte(tempbyte);
}
}
}
#ifndef NRF24L01_H_
#define NRF24L01_H_
#include <xc.h> // include processor files - each processor file is guarded.
#include "mcc_generated_files/mcc.h"
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#ifndef bool
#define bool unsigned char
#endif
#ifndef false
#define false 0
#endif
#ifndef true
#define true !false
#endif
/////////////////////////////////////////////////////////////////////////////////
// SPI function requirements
//
// The user must define a function to send one byte of data and also return the
// resulting byte of data data through the SPI port. The function used here
// has the function prototype
//
// unsigned char spi_send_read_byte(unsigned char byte);
//
// This function should take the argument unsigned char byte and send it through
// the SPI port to the 24L01. Then, it should wait until the 24L01 has returned
// its response over SPI. This received byte should be the return value of the
// function.
//
// You should also change the include file name below to whatever the name of your
// SPI include file is.
//////////////////////////////////////////////////////////////////////////////////
#define spi_send_read_byte(byte) spi1_send_read_byte(byte)
/////////////////////////////////////////////////////////////////////////////////
// Delay function requirements
//
// The user must define a function that delays for the specified number of
// microseconds. This function needs to be as precise as possible, and the use
// of a timer module within your microcontroller is highly recommended. The
// function used here has the prototype
//
// void delay_us(unsigned int microseconds);
//
// You should also change the include file name below to whatever the name of your
// delay include file is.
//////////////////////////////////////////////////////////////////////////////////
// IO pin definitions
//
// Below you will find several definitions and includes. The first is an #include
// for your microcontroller's include file to allow you to use register names
// rather than numbers. The next three are to allow you to control the pins on
// the 24L01 that aren't automatically handled by SPI. These are CE, CSN, and
// IRQ.
//
// The general format of these defines is a define for the IO register the pin is
// attached to. The second define is a mask for the pin. For example, say that
// your CE pin is tied to an IO port with the register name IOPORT1. Also, let's
// say that the IO port is 8-bits wide, and you have attached the pin to pin 0 of
// the port. Then your define would look like this:
//
// #define nrf24l01_CE_IOREGISTER IOPORT1
// #define nrf24l01_CE_PINMASK 0x01
//
// If you have defines in your include file for individual IO pins, you could use
// this define in this file, as well. Using the previous example, assume that in
// your microcontroller's include file, pin 0 of IOPORT1 has a define like this
//
// #define IOPORT1_PIN0 0x01
//
// Then, you could make your defines for the CE pin in this file look like this:
//
// #define nrf24l01_CE_IOREGISTER IOPORT1
// #define nrf24l01_CE_PINMASK IOPORT1_PIN0
//
// You should also change the include file name below to whatever the name of your
// processor's register definition include file is.
/////////////////////////////////////////////////////////////////////////////////////
//defines for uC pins CE pin is connected to
//This is used so that the routines can send TX payload data and
// properly initialize the nrf24l01 in TX and RX states.
//Change these definitions (and then recompile) to suit your particular application.
#define nrf24l01_CE_IOREGISTER PORTC
#define nrf24l01_CE_PINMASK 0x02
//defines for uC pins CSN pin is connected to
//This is used so that the routines can send properly operate the SPI interface
// on the nrf24l01.
//Change these definitions (and then recompile) to suit your particular application.
#define nrf24l01_CSN_IOREGISTER PORTC
#define nrf24l01_CSN_PINMASK 0x04
//defines for uC pins IRQ pin is connected to
//This is used so that the routines can poll for IRQ or create an ISR.
//Change these definitions (and then recompile) to suit your particular application.
#define nrf24l01_IRQ_IOREGISTER PORTB
#define nrf24l01_IRQ_PINMASK 0x01
////////////////////////////////////////////////////////////////////////////////////
// SPI commands
//
// The following are defines for all of the commands and data masks on the SPI
// interface.
////////////////////////////////////////////////////////////////////////////////////
//SPI command defines
#define nrf24l01_R_REGISTER 0x00
#define nrf24l01_W_REGISTER 0x20
#define nrf24l01_R_RX_PAYLOAD 0x61
#define nrf24l01_W_TX_PAYLOAD 0xA0
#define nrf24l01_FLUSH_TX 0xE1
#define nrf24l01_FLUSH_RX 0xE2
#define nrf24l01_REUSE_TX_PL 0xE3
#define nrf24l01_NOP 0xFF
//SPI command data mask defines
#define nrf24l01_R_REGISTER_DATA 0x1F
#define nrf24l01_W_REGISTER_DATA 0x1F
////////////////////////////////////////////////////////////////////////////////////
// Register definitions
//
// Below are the defines for each register's address in the 24L01.
////////////////////////////////////////////////////////////////////////////////////
#define nrf24l01_CONFIG 0x00
#define nrf24l01_EN_AA 0x01
#define nrf24l01_EN_RXADDR 0x02
#define nrf24l01_SETUP_AW 0x03
#define nrf24l01_SETUP_RETR 0x04
#define nrf24l01_RF_CH 0x05
#define nrf24l01_RF_SETUP 0x06
#define nrf24l01_STATUS 0x07
#define nrf24l01_OBSERVE_TX 0x08
#define nrf24l01_CD 0x09
#define nrf24l01_RX_ADDR_P0 0x0A
#define nrf24l01_RX_ADDR_P1 0x0B
#define nrf24l01_RX_ADDR_P2 0x0C
#define nrf24l01_RX_ADDR_P3 0x0D
#define nrf24l01_RX_ADDR_P4 0x0E
#define nrf24l01_RX_ADDR_P5 0x0F
#define nrf24l01_TX_ADDR 0x10
#define nrf24l01_RX_PW_P0 0x11
#define nrf24l01_RX_PW_P1 0x12
#define nrf24l01_RX_PW_P2 0x13
#define nrf24l01_RX_PW_P3 0x14
#define nrf24l01_RX_PW_P4 0x15
#define nrf24l01_RX_PW_P5 0x16
#define nrf24l01_FIFO_STATUS 0x17
////////////////////////////////////////////////////////////////////////////////////
// Default register values
//
// Below are the defines for each register's default value in the 24L01. Multi-byte
// registers use notation B<X>, where "B" represents "byte" and <X> is the byte
// number.
////////////////////////////////////////////////////////////////////////////////////
#define nrf24l01_CONFIG_DEFAULT_VAL 0x08
#define nrf24l01_EN_AA_DEFAULT_VAL 0x3F
#define nrf24l01_EN_RXADDR_DEFAULT_VAL 0x03
#define nrf24l01_SETUP_AW_DEFAULT_VAL 0x03
#define nrf24l01_SETUP_RETR_DEFAULT_VAL 0x03
#define nrf24l01_RF_CH_DEFAULT_VAL 0x02
#define nrf24l01_RF_SETUP_DEFAULT_VAL 0x0F
#define nrf24l01_STATUS_DEFAULT_VAL 0x0E
#define nrf24l01_OBSERVE_TX_DEFAULT_VAL 0x00
#define nrf24l01_CD_DEFAULT_VAL 0x00
#define nrf24l01_RX_ADDR_P0_B0_DEFAULT_VAL 0xE7
#define nrf24l01_RX_ADDR_P0_B1_DEFAULT_VAL 0xE7
#define nrf24l01_RX_ADDR_P0_B2_DEFAULT_VAL 0xE7
#define nrf24l01_RX_ADDR_P0_B3_DEFAULT_VAL 0xE7
#define nrf24l01_RX_ADDR_P0_B4_DEFAULT_VAL 0xE7
#define nrf24l01_RX_ADDR_P1_B0_DEFAULT_VAL 0xC2
#define nrf24l01_RX_ADDR_P1_B1_DEFAULT_VAL 0xC2
#define nrf24l01_RX_ADDR_P1_B2_DEFAULT_VAL 0xC2
#define nrf24l01_RX_ADDR_P1_B3_DEFAULT_VAL 0xC2
#define nrf24l01_RX_ADDR_P1_B4_DEFAULT_VAL 0xC2
#define nrf24l01_RX_ADDR_P2_DEFAULT_VAL 0xC3
#define nrf24l01_RX_ADDR_P3_DEFAULT_VAL 0xC4
#define nrf24l01_RX_ADDR_P4_DEFAULT_VAL 0xC5
#define nrf24l01_RX_ADDR_P5_DEFAULT_VAL 0xC6
#define nrf24l01_TX_ADDR_B0_DEFAULT_VAL 0xE7
#define nrf24l01_TX_ADDR_B1_DEFAULT_VAL 0xE7
#define nrf24l01_TX_ADDR_B2_DEFAULT_VAL 0xE7
#define nrf24l01_TX_ADDR_B3_DEFAULT_VAL 0xE7
#define nrf24l01_TX_ADDR_B4_DEFAULT_VAL 0xE7
#define nrf24l01_RX_PW_P0_DEFAULT_VAL 0x00
#define nrf24l01_RX_PW_P1_DEFAULT_VAL 0x00
#define nrf24l01_RX_PW_P2_DEFAULT_VAL 0x00
#define nrf24l01_RX_PW_P3_DEFAULT_VAL 0x00
#define nrf24l01_RX_PW_P4_DEFAULT_VAL 0x00
#define nrf24l01_RX_PW_P5_DEFAULT_VAL 0x00
#define nrf24l01_FIFO_STATUS_DEFAULT_VAL 0x11
////////////////////////////////////////////////////////////////////////////////////
// Register bitwise definitions
//
// Below are the defines for each register's bitwise fields in the 24L01.
////////////////////////////////////////////////////////////////////////////////////
//CONFIG register bitwise definitions
#define nrf24l01_CONFIG_RESERVED 0x80
#define nrf24l01_CONFIG_MASK_RX_DR 0x40
#define nrf24l01_CONFIG_MASK_TX_DS 0x20
#define nrf24l01_CONFIG_MASK_MAX_RT 0x10
#define nrf24l01_CONFIG_EN_CRC 0x08
#define nrf24l01_CONFIG_CRCO 0x04
#define nrf24l01_CONFIG_PWR_UP 0x02
#define nrf24l01_CONFIG_PRIM_RX 0x01
//EN_AA register bitwise definitions
#define nrf24l01_EN_AA_RESERVED 0xC0
#define nrf24l01_EN_AA_ENAA_ALL 0x3F
#define nrf24l01_EN_AA_ENAA_P5 0x20
#define nrf24l01_EN_AA_ENAA_P4 0x10
#define nrf24l01_EN_AA_ENAA_P3 0x08
#define nrf24l01_EN_AA_ENAA_P2 0x04
#define nrf24l01_EN_AA_ENAA_P1 0x02
#define nrf24l01_EN_AA_ENAA_P0 0x01
#define nrf24l01_EN_AA_ENAA_NONE 0x00
//EN_RXADDR register bitwise definitions
#define nrf24l01_EN_RXADDR_RESERVED 0xC0
#define nrf24l01_EN_RXADDR_ERX_ALL 0x3F
#define nrf24l01_EN_RXADDR_ERX_P5 0x20
#define nrf24l01_EN_RXADDR_ERX_P4 0x10
#define nrf24l01_EN_RXADDR_ERX_P3 0x08
#define nrf24l01_EN_RXADDR_ERX_P2 0x04
#define nrf24l01_EN_RXADDR_ERX_P1 0x02
#define nrf24l01_EN_RXADDR_ERX_P0 0x01
#define nrf24l01_EN_RXADDR_ERX_NONE 0x00
//SETUP_AW register bitwise definitions
#define nrf24l01_SETUP_AW_RESERVED 0xFC
#define nrf24l01_SETUP_AW 0x03
#define nrf24l01_SETUP_AW_5BYTES 0x03
#define nrf24l01_SETUP_AW_4BYTES 0x02
#define nrf24l01_SETUP_AW_3BYTES 0x01
#define nrf24l01_SETUP_AW_ILLEGAL 0x00
//SETUP_RETR register bitwise definitions
#define nrf24l01_SETUP_RETR_ARD 0xF0
#define nrf24l01_SETUP_RETR_ARD_4000 0xF0
#define nrf24l01_SETUP_RETR_ARD_3750 0xE0
#define nrf24l01_SETUP_RETR_ARD_3500 0xD0
#define nrf24l01_SETUP_RETR_ARD_3250 0xC0
#define nrf24l01_SETUP_RETR_ARD_3000 0xB0
#define nrf24l01_SETUP_RETR_ARD_2750 0xA0
#define nrf24l01_SETUP_RETR_ARD_2500 0x90
#define nrf24l01_SETUP_RETR_ARD_2250 0x80
#define nrf24l01_SETUP_RETR_ARD_2000 0x70
#define nrf24l01_SETUP_RETR_ARD_1750 0x60
#define nrf24l01_SETUP_RETR_ARD_1500 0x50
#define nrf24l01_SETUP_RETR_ARD_1250 0x40
#define nrf24l01_SETUP_RETR_ARD_1000 0x30
#define nrf24l01_SETUP_RETR_ARD_750 0x20
#define nrf24l01_SETUP_RETR_ARD_500 0x10
#define nrf24l01_SETUP_RETR_ARD_250 0x00
#define nrf24l01_SETUP_RETR_ARC 0x0F
#define nrf24l01_SETUP_RETR_ARC_15 0x0F
#define nrf24l01_SETUP_RETR_ARC_14 0x0E
#define nrf24l01_SETUP_RETR_ARC_13 0x0D
#define nrf24l01_SETUP_RETR_ARC_12 0x0C
#define nrf24l01_SETUP_RETR_ARC_11 0x0B
#define nrf24l01_SETUP_RETR_ARC_10 0x0A
#define nrf24l01_SETUP_RETR_ARC_9 0x09
#define nrf24l01_SETUP_RETR_ARC_8 0x08
#define nrf24l01_SETUP_RETR_ARC_7 0x07
#define nrf24l01_SETUP_RETR_ARC_6 0x06
#define nrf24l01_SETUP_RETR_ARC_5 0x05
#define nrf24l01_SETUP_RETR_ARC_4 0x04
#define nrf24l01_SETUP_RETR_ARC_3 0x03
#define nrf24l01_SETUP_RETR_ARC_2 0x02
#define nrf24l01_SETUP_RETR_ARC_1 0x01
#define nrf24l01_SETUP_RETR_ARC_0 0x00
//RF_CH register bitwise definitions
#define nrf24l01_RF_CH_RESERVED 0x80
//RF_SETUP register bitwise definitions
#define nrf24l01_RF_SETUP_RESERVED 0xE0
#define nrf24l01_RF_SETUP_PLL_LOCK 0x10
#define nrf24l01_RF_SETUP_RF_DR 0x08
#define nrf24l01_RF_SETUP_RF_PWR 0x06
#define nrf24l01_RF_SETUP_RF_PWR_0 0x06
#define nrf24l01_RF_SETUP_RF_PWR_6 0x04
#define nrf24l01_RF_SETUP_RF_PWR_12 0x02
#define nrf24l01_RF_SETUP_RF_PWR_18 0x00
#define nrf24l01_RF_SETUP_LNA_HCURR 0x01
//STATUS register bitwise definitions
#define nrf24l01_STATUS_RESERVED 0x80
#define nrf24l01_STATUS_RX_DR 0x40
#define nrf24l01_STATUS_TX_DS 0x20
#define nrf24l01_STATUS_MAX_RT 0x10
#define nrf24l01_STATUS_RX_P_NO 0x0E
#define nrf24l01_STATUS_RX_P_NO_RX_FIFO_NOT_EMPTY 0x0E
#define nrf24l01_STATUS_RX_P_NO_UNUSED 0x0C
#define nrf24l01_STATUS_RX_P_NO_5 0x0A
#define nrf24l01_STATUS_RX_P_NO_4 0x08
#define nrf24l01_STATUS_RX_P_NO_3 0x06
#define nrf24l01_STATUS_RX_P_NO_2 0x04
#define nrf24l01_STATUS_RX_P_NO_1 0x02
#define nrf24l01_STATUS_RX_P_NO_0 0x00
#define nrf24l01_STATUS_TX_FULL 0x01
//OBSERVE_TX register bitwise definitions
#define nrf24l01_OBSERVE_TX_PLOS_CNT 0xF0
#define nrf24l01_OBSERVE_TX_ARC_CNT 0x0F
//CD register bitwise definitions
#define nrf24l01_CD_RESERVED 0xFE
#define nrf24l01_CD_CD 0x01
//RX_PW_P0 register bitwise definitions
#define nrf24l01_RX_PW_P0_RESERVED 0xC0
//RX_PW_P0 register bitwise definitions
#define nrf24l01_RX_PW_P0_RESERVED 0xC0
//RX_PW_P1 register bitwise definitions
#define nrf24l01_RX_PW_P1_RESERVED 0xC0
//RX_PW_P2 register bitwise definitions
#define nrf24l01_RX_PW_P2_RESERVED 0xC0
//RX_PW_P3 register bitwise definitions
#define nrf24l01_RX_PW_P3_RESERVED 0xC0
//RX_PW_P4 register bitwise definitions
#define nrf24l01_RX_PW_P4_RESERVED 0xC0
//RX_PW_P5 register bitwise definitions
#define nrf24l01_RX_PW_P5_RESERVED 0xC0
//FIFO_STATUS register bitwise definitions
#define nrf24l01_FIFO_STATUS_RESERVED 0x8C
#define nrf24l01_FIFO_STATUS_TX_REUSE 0x40
#define nrf24l01_FIFO_STATUS_TX_FULL 0x20
#define nrf24l01_FIFO_STATUS_TX_EMPTY 0x10
#define nrf24l01_FIFO_STATUS_RX_FULL 0x02
#define nrf24l01_FIFO_STATUS_RX_EMPTY 0x01
////////////////////////////////////////////////////////////////////////////////////
// Function declarations
//
// Below are all function definitions contained in the library. Please see
// nrf24l01.c for comments regarding the usage of each function.
////////////////////////////////////////////////////////////////////////////////////
//initialization functions
void nrf24l01_initialize(unsigned char config,
unsigned char opt_rx_standby_mode,
unsigned char en_aa,
unsigned char en_rxaddr,
unsigned char setup_aw,
unsigned char setup_retr,
unsigned char rf_ch,
unsigned char rf_setup,
unsigned char * rx_addr_p0,
unsigned char * rx_addr_p1,
unsigned char rx_addr_p2,
unsigned char rx_addr_p3,
unsigned char rx_addr_p4,
unsigned char rx_addr_p5,
unsigned char * tx_addr,
unsigned char rx_pw_p0,
unsigned char rx_pw_p1,
unsigned char rx_pw_p2,
unsigned char rx_pw_p3,
unsigned char rx_pw_p4,
unsigned char rx_pw_p5);
void nrf24l01_initialize_debug(bool rx, unsigned char p0_payload_width, bool enable_auto_ack);
void nrf24l01_initialize_debug_lite(bool rx, unsigned char p0_payload_width);
//power-up, power-down functions
void nrf24l01_power_up(bool rx_active_mode);
void nrf24l01_power_up_param(bool rx_active_mode, unsigned char config);
void nrf24l01_power_down(void);
void nrf24l01_power_down_param(unsigned char config);
//SPI commands defined by the spec
//for regnumber values, see section above titled "register definitions"
//all functions return the STATUS register
unsigned char nrf24l01_write_register(unsigned char regnumber, unsigned char * data, unsigned int len);
unsigned char nrf24l01_read_register(unsigned char regnumber, unsigned char * data, unsigned int len);
unsigned char nrf24l01_write_tx_payload(unsigned char * data, unsigned int len, bool transmit);
unsigned char nrf24l01_read_rx_payload(unsigned char * data, unsigned int len);
unsigned char nrf24l01_flush_tx(void);
unsigned char nrf24l01_flush_rx(void);
unsigned char nrf24l01_reuse_tx_pl(void);
unsigned char nrf24l01_nop(void);
//RX/TX setting functions
void nrf24l01_set_as_rx(bool rx_active_mode);
void nrf24l01_set_as_rx_param(bool rx_active_mode, unsigned char config);
void nrf24l01_rx_standby_to_active(void);
void nrf24l01_rx_active_to_standby(void);
void nrf24l01_set_as_tx(void);
void nrf24l01_set_as_tx_param(unsigned char config);
//register-oriented get/set functions for commonly-used registers during operation
unsigned char nrf24l01_get_config(void);
void nrf24l01_set_config(unsigned char config);
unsigned char nrf24l01_get_rf_ch(void);
void nrf24l01_set_rf_ch(unsigned char channel);
unsigned char nrf24l01_get_status(void);
unsigned char nrf24l01_get_observe_tx(void);
void nrf24l01_set_rx_addr(unsigned char * address, unsigned int len, unsigned char rxpipenum);
void nrf24l01_set_tx_addr(unsigned char * address, unsigned int len);
void nrf24l01_set_rx_pw(unsigned char payloadwidth, unsigned char rxpipenum);
unsigned char nrf24l01_get_rx_pw(unsigned char rxpipenum);
unsigned char nrf24l01_get_fifo_status(void);
//auto-ack and pipe-related functions
bool nrf24l01_aa_enabled(unsigned char rxpipenum);
void nrf24l01_aa_enable(unsigned char rxpipenum);
void nrf24l01_aa_disable(unsigned char rxpipenum);
bool nrf24l01_rx_pipe_enabled(unsigned char rxpipenum);
void nrf24l01_rx_pipe_enable(unsigned char rxpipenum);
void nrf24l01_rx_pipe_disable(unsigned char rxpipenum);
unsigned char nrf24l01_get_plos_cnt(void);
void nrf24l01_clear_plos_cnt(void);
void nrf24l01_clear_plos_cnt_param(unsigned char rf_ch);
unsigned char nrf24l01_get_arc_cnt(void);
//utility functions
bool nrf24l01_cd_active(void);
void nrf24l01_clear_flush(void);
unsigned char nrf24l01_get_rx_pipe(void);
unsigned char nrf24l01_get_rx_pipe_from_status(unsigned char status);
void nrf24l01_get_all_registers(unsigned char * data);
//interrupt check/clear functions
bool nrf24l01_irq_pin_active(void);
bool nrf24l01_irq_rx_dr_active(void);
bool nrf24l01_irq_tx_ds_active(void);
bool nrf24l01_irq_max_rt_active(void);
void nrf24l01_irq_clear_all(void);
void nrf24l01_irq_clear_rx_dr(void);
void nrf24l01_irq_clear_tx_ds(void);
void nrf24l01_irq_clear_max_rt(void);
//FIFO_STATUS check functions
bool nrf24l01_fifo_tx_reuse(void);
bool nrf24l01_fifo_tx_full(void);
bool nrf24l01_fifo_tx_empty(void);
bool nrf24l01_fifo_rx_full(void);
bool nrf24l01_fifo_rx_empty(void);
//IO interface-related functions
void nrf24l01_transmit(void);
void nrf24l01_clear_ce(void);
void nrf24l01_set_ce(void);
void nrf24l01_clear_csn(void);
void nrf24l01_set_csn(void);
bool nrf24l01_ce_pin_active(void);
bool nrf24l01_csn_pin_active(void);
//low-level functions for library use only
unsigned char nrf24l01_execute_command(unsigned char instruction, unsigned char * data, unsigned int len, bool copydata);
void nrf24l01_spi_send_read(unsigned char * data, unsigned int len, bool copydata);
#endif /*NRF24L01_H_*/
unsigned char spi1_send_read_byte(unsigned char byte)
{
SSP1BUF = byte;
while(!DataRdySPI());
return SSP1BUF;
}
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?