This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

What is the right configuration of registers for NRF24L01P (TX mode and RX mode)

After i test a lot of possible configurations for nrf24L01+ based on the documentation, i didn't come to the right setup for all the nRf24L01+ registers to send data from a module as an emitter and to receive as a receiver. here is the configurations i made for the initiation ( Transmitter)

config_transmiter();           // set as transmiter and power up
setRADDR();                    // address for pipe 1 
setTADDR();                    // same for receiver of pipe 0
rf_setup() ;
payload_size(8);               // 5 bytes
setRF_CH();                    // 2.431GHz
flushTX();                     // clear any data in TX FIFO
en_RXADDR(0x3F);
auto_ack(0x3F); 

address RX : 0x65646f4e32 address TX : 0x65646f4e31

( Receiver)

config_receiver();           // set as transmiter and power up
setSETUPAW();
setRADDR();                    // address for pipe 0 
setTADDR();                    // same for trasmiter
rf_setup() ;
payload_size(8);               // 5 bytes
setRF_CH();                    // 2.431GHz
flushRX();                     // clear any data in RX FIFO
en_RXADDR(0x3F);
auto_ack(0x3F);                // enable auto acknowledgment

address RX : 0x65646f4e31 address TX : 0x65646f4e31

Parents
  • Hi Mohamed

    When using the auto ACK (ESB) features of the nRF24L01+ you want to make sure that the TX and Pipe 0 address is the same on the PTX side. The reason for this is that the PTX uses pipe 0 to receive the acknowledgement sent by the PRX.

    Also, I can only see setSETUPAW(); referenced on the RX side. If you have a different address length on the TX and RX side then communication will fail.

    If you still have issues after checking these things, then it would help if you could write down the state of the configuration registers on both sides. Then I can look them over and see if I spot any more issues.

    Best regards
    Torbjørn

Reply
  • Hi Mohamed

    When using the auto ACK (ESB) features of the nRF24L01+ you want to make sure that the TX and Pipe 0 address is the same on the PTX side. The reason for this is that the PTX uses pipe 0 to receive the acknowledgement sent by the PRX.

    Also, I can only see setSETUPAW(); referenced on the RX side. If you have a different address length on the TX and RX side then communication will fail.

    If you still have issues after checking these things, then it would help if you could write down the state of the configuration registers on both sides. Then I can look them over and see if I spot any more issues.

    Best regards
    Torbjørn

Children
  • Here is all the config registers data generated with oscilloscope :

    Emitter RX_ADDR_P0 : 0xF0F0F0F0F0 TX_ADDR : 0xF0F0F0F0F0

    Register : 0x00 (CONFIG) 0x5A

    Register : 0x01 (EN_AA) 0x3F

    Register : 0x02 (EN_RXADDR) 0x03

    Register : 0x03 (SETUP_AW) 0x03

    Register : 0x04 (SETUP_RETR) 0x03

    Register : 0x05 (RF_CH) 0x1F

    Register : 0x06 (RF_SETUP) 0x0F

    Register : 0x07 (STATUS) 0x1E

    Register : 0x08 (OBSERVE_TX) 0x03

    Register : 0x09 (CD) 0x00

    Register : 0x0A (RX_ADDR_P0) 0xF0

    Register : 0x0B (RX_ADDR_P1) 0xC2

    Register : 0x0C (RX_ADDR_P2) 0xC3

    Register : 0x0D (RX_ADDR_P3) 0xC4

    Register : 0x0E (RX_ADDR_P4) 0xC5

    Register : 0x0F (RX_ADDR_P5) 0xC6

    Register : 0x10 (TX_ADDR) 0xF0

    Register : 0x11 (RX_PW_P0) 0x08

    Register : 0x12 (RX_PW_P1) 0x37

    Register : 0x13 (RX_PW_P2) 0x00

    Register : 0x14 (RX_PW_P3) 0x00

    Register : 0x15 (RX_PW_P4) 0x00

    Register : 0x16 (RX_PW_P5) 0x00

    Register : 0x17 (FIFO_STATUS) 0x11

    Register : 0x1C (DYNPD) 0x00

    Register : 0x1D (FEATURE) 0x00

    Receiver RX_ADDR_P0 : 0xF0F0F0F0F0 TX_ADDR : 0xF0F0F0F0F0

    0x00 CONFIG 0x3B

    0x01 EN_AA 0x3F

    0x02 EN_RXADDR 0x03

    0x03 SETUP_AW 0x03

    0x04 SETUP_RETR 0x03

    0x05 RF_CH 0x1F

    0x06 RF_SETUP 0x0F

    0x07 STATUS 0x0E

    0x08 OBSERVE_TX 0x00

    0x09 CD 0x00

    0x0A RX_ADDR_P0 0xF0

    0x0B RX_ADDR_P1 0xC2

    0x0C RX_ADDR_P2 0xC3

    0x0D RX_ADDR_P3 0xC4

    0x0E RX_ADDR_P4 0xC5

    0x0F RX_ADDR_P5 0xC6

    0x10 TX_ADDR 0xF0

    0x11 RX_PW_P0 0x08

    0x12 RX_PW_P1 0x00

    0x13 RX_PW_P2 0x00

    0x14 RX_PW_P3 0x00

    0x15 RX_PW_P4 0x00

    0x16 RX_PW_P5 0x00

    0x17 FIFO_STATUS 0x11

    0x1C DYNPD 0x00

    0x1D FEATURE 0x00

  • Hi Mohamed

    Your settings look good, except that you don't have the MAX_RT interrupt enabled on the PTX side. Since the MAX_RT interrupt occurs every time you don't receive an ACK from the PRX, this is something you should account for.

    That being said this shouldn't block communication completely. Could you share your source code, so I can have a look at how you send/receive packets, and process the radio interrupts?

  • Hi Torbjørn

    Thank you for your help here is my code on the emitter side and receiver side.

    /* Connection: Emitter.c Using : Mikroc mcu: PIC16F1827

    ChipSelect --> RA1;

    SDOpin --> RA0;

    SDIpin --> RB2;

    SCKpin --> RB5;

    IRQpin --> RB7;

    CEpin --> RB6;


    */

    ////////////////////////////////////////////////////////////////////////////////////////// ///////////

    sbit ChipSelect_dir at TRISA.B1 ;

    sbit ChipSelect at LATA.B1;

    sbit SDOpin_dir at TRISA.b0;

    sbit SDIpin_dir at TRISB.B2;

    sbit SCKpin_dir at TRISB.B5;

    sbit CEpin at LATB.B6;

    sbit CEpin_dir at TRISB.B6;

    sbit IRQ at LATB.B7;

    sbit IRQ_dir at TRISB.B7;

    char byte[8]={0,1,2,3,4,5,6,7};

    #define R_RX_PAYLOAD 0b01100001

    #define T_TX_PAYLOAD 0b10100000

    #define FLUSH_TX 0b11100001

    #define FLUSH_RX 0b11100010

    #define NOP 0b00000000

    #define RECEIVER 0b00111011

    #define TRANSMITER 0b01011010

    unsigned short int temp;

    void SPI_dubleMSSP_Init()

    {

     SSP2CON1 = 0x00;           // disable SPI 
     SDOpin_dir = 0;            //data out
     SDIpin_dir = 1;            //data in
     SCKpin_dir = 0;            //clock
     ChipSelect_dir = 0;        //ChipSelect
     CEpin_dir = 0;
     IRQ_dir=1;
     ChipSelect = 1;
     SSP2CON1=0b00100000; // set SPI master mode
     SSP2STAT=0b01000000;
    

    }

    short int SPI_dubleMSSP_write (short int addr)

    {

      SSP2BUF = addr;           // send data to the BUFFER
      while(!SSP2STAT.BF);      // wait for the tramsit/recieve to finish
      temp = SSP2BUF;           // clear the BF flag
      return temp;
    

    }

    short int SPI_dubleMSSP_read()

    {

      SSP2BUF = 0x00;           // send a dummy byte
      while(!SSP2STAT.BF);
      temp = SSP2BUF;
      return temp;
    

    }

    ////////////////////////////////////////////////////////////////////////////////////////// ///////////

    void config_receiver()

    {

     CEpin_dir = 0;                               // CE pin output
     ChipSelect = 0;
     SPI_dubleMSSP_write(0x20);                   // write CONFIG
     SPI_dubleMSSP_write(RECEIVER);             // reciever
     ChipSelect = 1;
    

    }

    void config_transmiter()

    {

     CEpin_dir = 0;                               // CE pin output
     ChipSelect = 0;
     SPI_dubleMSSP_write(0x20);                   // write CONFIG
     SPI_dubleMSSP_write(TRANSMITER);             // transmiter
     ChipSelect = 1;
    

    }

    void setRADDR()

    {

     ChipSelect = 0;
     SPI_dubleMSSP_write(0x2A);                   // write receiver address
     SPI_dubleMSSP_write(0xF0);                   // for pipe 0
     SPI_dubleMSSP_write(0xF0);                   // address: 0xF0F0F0F0F0
     SPI_dubleMSSP_write(0xF0);
     SPI_dubleMSSP_write(0xF0);
     SPI_dubleMSSP_write(0xF0);
     ChipSelect = 1;
    

    }

    void setTADDR()

    {

     ChipSelect = 0;
     SPI_dubleMSSP_write(0x30);                   // write transmiter adress
     SPI_dubleMSSP_write(0xF0);                   // same as receiver
     SPI_dubleMSSP_write(0xF0);                   // address: 0xF0F0F0F0F0
     SPI_dubleMSSP_write(0xF0);
     SPI_dubleMSSP_write(0xF0);
     SPI_dubleMSSP_write(0xF0);
     ChipSelect = 1;
    

    }

    void payload_size(short int x)

    {

     ChipSelect = 0;
     SPI_dubleMSSP_write(0x31);                   // setting the number of bytes (x)
     SPI_dubleMSSP_write(x);                      // in RX payload for pipe 0
     ChipSelect = 1;
    

    }

    void setRF_CH()

    {

     ChipSelect = 0;
     SPI_dubleMSSP_write(0x25);                   // RF Channel
     SPI_dubleMSSP_write(0x1F);                   // 2.4 + 0.031 = 2.431GHz
     ChipSelect = 1;
    

    }

    void flushRX()

    {

     ChipSelect = 0;
     SPI_dubleMSSP_write(FLUSH_RX);                   // Flush RX
     ChipSelect = 1;
    

    }

    void flushTX()

    {

     ChipSelect = 0;
     SPI_dubleMSSP_write(FLUSH_TX);                   // Flush TX
     ChipSelect = 1;
    

    }

    void auto_ack(short int x)

    {

     ChipSelect = 0;
     SPI_dubleMSSP_write(0x21);                   // write EN_AA
     SPI_dubleMSSP_write(x);                      // disable/enable auto-ack
     ChipSelect = 1;
    

    }

    void nRF_write_register(char reg, char pod)

    {

     ChipSelect = 0;
     SPI_dubleMSSP_write(reg);                    // registar which to write
     SPI_dubleMSSP_write(pod);                    // data to write  to registar
     ChipSelect = 1;
    

    }

    char nRF_read_register(char reg)

    {

     char pod;
     ChipSelect = 0;
     SPI_dubleMSSP_write(reg);
     pod = SPI_dubleMSSP_read();
     ChipSelect = 1;
     return pod;
    

    }

    void send_data(short int number_of_bytes)

    {

     int k;
     ChipSelect = 0;                              // announce the transmission
     SPI_dubleMSSP_write(T_TX_PAYLOAD);           // write the command byte
     for(k = 0; k < number_of_bytes; k++) SPI_dubleMSSP_write(byte[k]);
     ChipSelect = 1;
     CEpin = 1;
     delay_us(15);              // send the payload
     CEpin = 0;
    

    }

    void read_data(int x)

    {

     int k;
     ChipSelect = 0;
     SPI_dubleMSSP_write(R_RX_PAYLOAD);              // command byte (read data)
     for(k = 0; k < x; k++) byte[k] = SPI_dubleMSSP_read();
     ChipSelect = 1;
    

    }

    void read_address(char x)

    {

     ChipSelect = 0;
     SPI_dubleMSSP_write(x);
     SPI_dubleMSSP_write(NOP);           // 5 dummy bytes
     SPI_dubleMSSP_write(NOP);
     SPI_dubleMSSP_write(NOP);
     SPI_dubleMSSP_write(NOP);
     SPI_dubleMSSP_write(NOP);
     ChipSelect = 1;
    

    }

    void en_RXADDR(char x)

    {

     ChipSelect = 0;
     SPI_dubleMSSP_write(0x22);                   // write EN_RXADDR
     SPI_dubleMSSP_write(x);                      // disable/enable pipes
     ChipSelect = 1;
    

    }

    void wait_for_data() {

     CEpin = 1;                        //receive mode
     while(IRQ){}                      //waiting for IRQ to go low
     CEpin = 0;
    

    }

    void nRF_Config()

    {

     config_transmiter();           // set as receiver and power up
     setRADDR();                    // address for pipe 0 (oxF0F0F0F0)
     setTADDR();                    // same for transmitter
     payload_size(8);               // 8 bytes
     setRF_CH();                    // 2.431GHz
     flushTX();                     // clear any data in TX FIFO
     auto_ack(0x3F);                // enable auto acknowledgment
    

    }

    void main() {

    int j=0;
    OSCCON = 0b01110000;
    ANSELA = 0;
    TRISA = 0;
    PORTA = 0;
    ANSELB = 0;
    TRISB = 0;
    PORTB = 0;
    SPI_dubleMSSP_Init();                       // Initialize SPI
    nRF_Config();                               // Configure nRF24l01
    delay_ms(1000);
    
    while (1){ 
    
        byte[0] = 48;
        byte[1] = 49;
        byte[2] = 50;
        byte[3] = 51;
        byte[4] = 52;
        byte[5] = 53;
        byte[6] = 54;
        byte[7] = 55;
    
    
    
        send_data(8);
        delay_us(300);                // this delay is a MUST!
        flushTX();                    // flushing too soon disrupts data transfer!
        delay_us(250);
    
        
    
    }
    

    }

    /* **Connection: Receiver.c mcu: PIC16F1827 IDE : Mikroc ChipSelect --> RA1;

    SDOpin --> RA0;

    SDIpin --> RB2;

    SCKpin --> RB5;

    IRQpin --> RB7;

    CEpin --> RB6;


    */

    /////////////////////////////////////////////////////////////////////////////////////////////////////

    sbit ChipSelect_dir at TRISA.B1 ;

    sbit ChipSelect at LATA.B1;

    sbit SDOpin_dir at TRISA.b0;

    sbit SDIpin_dir at TRISB.B2;

    sbit SCKpin_dir at TRISB.B5;

    sbit CEpin at LATB.B6;

    sbit CEpin_dir at TRISB.B6;

    sbit IRQ at LATB.B7;

    sbit IRQ_dir at TRISB.B7;

    char byte[10]={0,0,0,0,0,0,0,0};

    #define R_RX_PAYLOAD 0b01100001

    #define T_TX_PAYLOAD 0b10100000

    #define FLUSH_TX 0b11100001

    #define FLUSH_RX 0b11100010

    #define NOP 0b00000000

    #define RECEIVER 0b00111011

    #define TRANSMITER 0b01011010

    unsigned short int temp;

    void SPI_dubleMSSP_Init()

    {

     SSP2CON1 = 0x00;           // disable SPI
     SDOpin_dir = 0;            //data out
     SDIpin_dir = 1;            //data in
     SCKpin_dir = 0;            //clock
     ChipSelect_dir = 0;        //ChipSelect
     CEpin_dir = 0;
     IRQ_dir=1;
     ChipSelect = 1;
     SSP2CON1=0b00100000; // set SPI master mode
     SSP2STAT=0b01000000;
    

    }

    char SPI_dubleMSSP_write (char addr)

    {

      SSP2BUF = addr;           // send data to the BUFFER
      while(!SSP2STAT.BF);      // wait for the tramsit/recieve to finish
      temp = SSP2BUF;           // clear the BF flag
      return temp;
    

    }

    short int SPI_dubleMSSP_read()

    {

      SSP2BUF = 0x00;           // send a dummy byte
      while(!SSP2STAT.BF);
      temp = SSP2BUF;
      return temp;
    

    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////

    void config_receiver()

    {

     CEpin_dir = 0;                               // CE pin output
     ChipSelect = 0;
     SPI_dubleMSSP_write(0x20);                   // write CONFIG
     SPI_dubleMSSP_write(RECEIVER);             // reciever
     ChipSelect = 1;
    

    }

    void config_transmiter()

    {

     CEpin_dir = 0;                               // CE pin output
     ChipSelect = 0;
     SPI_dubleMSSP_write(0x20);                   // write CONFIG
     SPI_dubleMSSP_write(TRANSMITER);             // transmiter
     ChipSelect = 1;
    

    }

    void setRADDR()

    {

     ChipSelect = 0;
     SPI_dubleMSSP_write(0x2A);                   // write receiver address
     SPI_dubleMSSP_write(0xF0);                   // for pipe 0
     SPI_dubleMSSP_write(0xF0);                   // address: 0xF0F0F0F0F0
     SPI_dubleMSSP_write(0xF0);
     SPI_dubleMSSP_write(0xF0);
     SPI_dubleMSSP_write(0xF0);
     ChipSelect = 1;
    

    }

    void setTADDR()

    {

     ChipSelect = 0;
     SPI_dubleMSSP_write(0x30);                   // write transmiter adress
     SPI_dubleMSSP_write(0xF0);                   // same as receiver
     SPI_dubleMSSP_write(0xF0);                   // address: 0xF0F0F0F0F0
     SPI_dubleMSSP_write(0xF0);
     SPI_dubleMSSP_write(0xF0);
     SPI_dubleMSSP_write(0xF0);
     ChipSelect = 1;
    

    }

    void payload_size(short int x)

    {

     ChipSelect = 0;
     SPI_dubleMSSP_write(0x31);                   // setting the number of bytes (x)
     SPI_dubleMSSP_write(x);                      // in RX payload for pipe 0
     ChipSelect = 1;
    

    }

    void setRF_CH()

    {

     ChipSelect = 0;
     SPI_dubleMSSP_write(0x25);                   // RF Channel
     SPI_dubleMSSP_write(0x1F);                   // 2.4 + 0.031 = 2.431GHz
     ChipSelect = 1;
    

    }

    void flushRX()

    {

     ChipSelect = 0;
     SPI_dubleMSSP_write(FLUSH_RX);                   // Flush RX
     ChipSelect = 1;
    

    }

    void flushTX()

    {

     ChipSelect = 0;
     SPI_dubleMSSP_write(FLUSH_TX);                   // Flush TX
     ChipSelect = 1;
    

    }

    void auto_ack(short int x)

    {

     ChipSelect = 0;
     SPI_dubleMSSP_write(0x21);                   // write EN_AA
     SPI_dubleMSSP_write(x);                      // disable/enable auto-ack
     ChipSelect = 1;
    

    }

    void nRF_write_register(char reg, char pod)

    {

     ChipSelect = 0;
     SPI_dubleMSSP_write(reg);                    // registar which to write
     SPI_dubleMSSP_write(pod);                    // data to write  to registar
     ChipSelect = 1;
    

    }

    char nRF_read_register(char reg)

    {

     char pod;
     ChipSelect = 0;
     SPI_dubleMSSP_write(reg);
     pod = SPI_dubleMSSP_read();
     ChipSelect = 1;
     return pod;
    

    }

    void send_data(short int number_of_bytes)

    {

     int k;
     ChipSelect = 0;                              // announce the transmission
     SPI_dubleMSSP_write(T_TX_PAYLOAD);           // write the command byte
     for(k = 0; k < number_of_bytes; k++) SPI_dubleMSSP_write(byte[k]);
     ChipSelect = 1;
    
     CEpin = 1;
     delay_us(15);              // send the payload
     CEpin = 0;
    

    }

    void read_data(int x)

    {

     int k;
     ChipSelect = 0;
     SPI_dubleMSSP_write(R_RX_PAYLOAD);              // command byte (read data)
     for(k = 0; k < x; k++) byte[k] = SPI_dubleMSSP_read();
     ChipSelect = 1;
    

    }

    void read_address(char x)

    {

     ChipSelect = 0;
     SPI_dubleMSSP_write(x);
     SPI_dubleMSSP_write(NOP);           // 5 dummy bytes
     SPI_dubleMSSP_write(NOP);
     SPI_dubleMSSP_write(NOP);
     SPI_dubleMSSP_write(NOP);
     SPI_dubleMSSP_write(NOP);
     ChipSelect = 1;
    

    }

    void en_RXADDR(char x)

    {

     ChipSelect = 0;
     SPI_dubleMSSP_write(0x22);                   // write EN_RXADDR
     SPI_dubleMSSP_write(x);                      // disable/enable pipes
    
     ChipSelect = 1;
    

    }

    void wait_for_data() {

     CEpin = 1;                        //receive mode
     while(IRQ){}                      //waiting for IRQ to go low
     CEpin = 0;
    

    }

    void nRF_Config() {

     config_receiver();             // set as receiver and power up
     setRADDR();                    // address for pipe 0 (oxF0F0F0F0)
     setTADDR();                    // same for transmitter
     payload_size(8);              // just 8 bytes
     setRF_CH();                    // 2.431GHz
     flushRX();                     // clear any data in RX FIFO
     auto_ack(0x3F);              // turn on auto ack
    

    }

    void main() {

    OSCCON = 0b01110000;    //8MHZ
    ANSELA = 0;
    TRISA = 0;
    PORTA = 0;
    ANSELB = 0;
    TRISB = 0;
    PORTB = 0;
    SPI_dubleMSSP_Init();                       // Initialize SPI
    CEpin = 0;
    nRF_Config();                        //receive mode
    while (1){
        CEpin = 0;
        wait_for_data();
        read_data(8);                               // 8 = number of bytes
        flushRX();                                                              //not mandatory but recommended
        nRF_write_register(0x27,0x40);                     //clear the RX_DR bit from STATUS register
        delay_us(250);
        }
    

    }

  • Hi Mohamed

    I can't really spot any issues with your code.

    Can you double check that the SPI is configured correctly, in terms of bit order, clock polarity and so forth?

    For reference I have attached a screenshot of how it should look like when you set the PRIM_RX and PWR_UP bits by writing 0x0B to the CONFIG register. If you are able to scope the lines you can double check that it looks the same.

Related