NRF24L01 Interfacing With 8051
NRF24L01 Interfacing With 8051
Xbee
by SLR
In our previous tutorial, we have seen a gas detection sensor interfacing with 8051. NRF24L01
interfacing with 8051 tutorial is intended to enable wireless data transfer for 8051. So to do that, we
will interface nRF24L10 with 8051. This will enable us to transfer the data wirelessly (by air) between
two 8051 boards using NRF24L01.
NRF24L0
Before start coding, we will see something about NRF24L01 to get some idea.
The nRF24L01 is a wireless transceiver module, meaning each module can both send as well as
receive data. They operate at the frequency of 2.4GHz, which falls under the ISM band, and hence it
is legal to use in almost all countries for engineering applications. The modules when operated
efficiently can cover a distance of 100 meters (200 feet) which makes it a great choice for all wireless
remote-controlled projects.
The module operates at 3.3V hence can be easily used with 3.2V systems or 5V systems. Each
module has an address range of 125 and each module can communicate with 6 other modules
hence it is possible to have multiple wireless units communicating with each other in a
particular area. Hence mesh networks or other types of networks are possible using this module.
So if you are looking for a wireless module with the above properties then this module would
be an ideal choice for you.
These modules are very cheap, smaller in size, and have a lot of specifications. Some of the
specifications of these modules are as follows,
nRF24L01 Features
Pin Pin
Abbreviation Function
Number Name
This pin has to be kept high always, else it will disable the
4 CSN Ship Select Not
SPI
Master Out Slave Connected to MOSI pin of MCU, for the module to receive
6 MOSI
In data from the MCU
Master In Slave Connected to MISO pin of MCU, for the module to send
7 MISO
Out data from the MCU
The NRF24L01 module works with the help of SPI communications. These modules can
either be used with a 3.3V microcontroller or a 5V microcontroller but they should have an SPI
port. Since 8051 doesn’t have the SPI, we are going to implement the SPI using the bit-banging
method.
And SPI will be having just 4 lines but here it has one more line extra called CE pin to enable
reception, transmission, and put the device into standby mode.
Write Register
Read Register
One status register is there (0x07). You can read the status of the transaction.
In this tutorial, we are going to use one setup for transmitter purpose and another for receiver
purpose. The concept is much simple. When we send something through the serial port in the
transmitter, that will be transmitted over the air. Since we are using the same address for both
TX and RX, RX will receive the data from the air and print the data through the serial port.
Connection
We have added only the NRF24L01 related source code. You can get the full project’s code
from GitHub.
nRF24L01.h
#include<intrins.h>
#include<reg51.h>
#include"SERIAL.H"
sbit CE = P1^4; //this signal is active high and is used to activate the chip in RX or TX mode
//Commands
#define NOP 0xFF //No operation, might be used to read status register
//Register Address
#define TX_ADDR 0x10 //Transmit address. Used for a PTX device only
#define TX_PLOAD_WIDTH 1
#define TX_ADD_WIDTH 5
sbit RX_DR=ack^6;
sbit TX_DS=ack^5;
sbit MAX_RT=ack^4;
unsigned char spi_W(unsigned char); //Write byte and read the status
unsigned char spi_WREG(unsigned char,unsigned char); //Write byte to REG and Read Status
unsigned char spi_WBUF(unsigned char reg,unsigned char *buff ,unsigned char count); //Write the
no of char to REG
unsigned char spi_RREG(unsigned char); //Read the REG that have one byte
void spi_RBUF(unsigned char reg,unsigned char count); //Read the REG that have more than one
byte
void spi_delay()
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
void get_status(void)
ack=0;
ack=spi_RREG(STATUS);
void clear_irq()
void nRF_config()
#ifdef TX_mode
#endif
#ifdef RX_mode
CE=0;
spi_WREG(W_REG|CONFIG,0x0F); //Set PWR_UP bit, enable CRC(2 bytes) & Prim:RX. RX_DR enabled
CE=1;
#endif
int sp;
buffer=buf;
for(sp=0;sp<=7;sp++)
buffer=buffer<<1;
SCK=1;
SCK=0;
return buffer;
{
unsigned char stat;
return stat;
unsigned char spi_WBUF(unsigned char reg,unsigned char *buff ,unsigned char count)
CSN=0;
stat=spi_W(reg);
for(sp=0;sp<count;sp++)
spi_W(buff[sp]);
CSN=1;
return stat;
#ifdef TX_mode
clear_irq();
CE=0;
spi_WREG(W_REG|CONFIG,0x0E); //Set PWR_UP bit, enable CRC(2 bytes) & Prim:TX. MAX_RT &
TX_DS enabled
CE=1;
spi_delay();
CE=0;
get_status();
if(MAX_RT)
return 0;
if(TX_DS)
return 1;
return stat;
#endif
CSN=0;
spi_W(reg);
rd=spi_W(0);
CSN=1;
return rd;
#ifdef RX_mode
stat=spi_W(reg);
for(sp=0;sp<count;sp++)
read_buf[sp]=spi_W(0);
read_buf[sp]='\0';
spi_WREG(FLUSH_RX,NOP);
do
get_status();
}while(RX_DR==0);
if(RX_DR)
clear_irq();
get_status();
if(ack ==0)
spi_RBUF(R_RX_PL,TX_PLOAD_WIDTH);
spi_delay();
return read_buf;
#endif
RX Code
We have added only the NRF24L01 related source code. You can get the full project’s code from
GitHub.
nRF24L01.h
#include<intrins.h>
#include<reg51.h>
#include"SERIAL.H"
sbit CE = P1^4; //this signal is active high and is used to activate the chip in RX or TX mode
//Commands
#define NOP 0xFF //No operation, might be used to read status register
//Register Address
#define TX_ADDR 0x10 //Transmit address. Used for a PTX device only
#define TX_PLOAD_WIDTH 1
#define TX_ADD_WIDTH 5
sbit RX_DR=ack^6;
sbit TX_DS=ack^5;
sbit MAX_RT=ack^4;
unsigned char spi_W(unsigned char); //Write byte and read the status
unsigned char spi_WREG(unsigned char,unsigned char); //Write byte to REG and Read Status
unsigned char spi_WBUF(unsigned char reg,unsigned char *buff ,unsigned char count); //Write the
no of char to REG
unsigned char spi_RREG(unsigned char); //Read the REG that have one byte
void spi_RBUF(unsigned char reg,unsigned char count); //Read the REG that have more than one
byte
unsigned char TX_PL(const unsigned char *payload); //Transmit payload
void spi_delay()
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
void get_status(void)
ack=0;
ack=spi_RREG(STATUS);
void clear_irq()
void nRF_config()
#ifdef TX_mode
#endif
#ifdef RX_mode
CE=0;
CE=1;
#endif
int sp;
buffer=buf;
for(sp=0;sp<=7;sp++)
buffer=buffer<<1;
SCK=1;
SCK=0;
return buffer;
return stat;
unsigned char spi_WBUF(unsigned char reg,unsigned char *buff ,unsigned char count)
CSN=0;
stat=spi_W(reg);
for(sp=0;sp<count;sp++)
spi_W(buff[sp]);
CSN=1;
return stat;
#ifdef TX_mode
clear_irq();
CE=0;
spi_delay();
CE=0;
get_status();
if(MAX_RT)
return 0;
if(TX_DS)
return 1;
return stat;
#endif
CSN=0;
spi_W(reg);
rd=spi_W(0);
CSN=1;
return rd;
#ifdef RX_mode
stat=spi_W(reg);
for(sp=0;sp<count;sp++)
read_buf[sp]=spi_W(0);
read_buf[sp]='\0';
CSN = 1; // Set CSN high again
spi_WREG(FLUSH_RX,NOP);
do
get_status();
}while(RX_DR==0);
if(RX_DR)
clear_irq();
get_status();
if(ack ==0)
spi_RBUF(R_RX_PL,TX_PLOAD_WIDTH);
spi_delay();
return read_buf;
#endif