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

Interface nrf24l01+ module with pic18f25k22.

Hello

I got this nordic nrf24l01+ module and trying to interface with pic18f25k22. this is my code. tried lot but unable to communicate (receive any data). I'm able to read the register values through SPI. I verified that all registers have values as configured. Please help me asap thanks in advance

transmitter :-

#include <xc.h>
#include "stdint.h"
#include <p18f25k22.h>
#include <flash.h>
#include <stdio.h>
#include <string.h>
#include<plib/spi.h>

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

// CONFIG1H
#pragma config FOSC = INTIO67   // Oscillator Selection bits (Internal oscillator block)
#pragma config PLLCFG = OFF     // 4X PLL Enable (Oscillator used directly)
#pragma config PRICLKEN = OFF   // Primary clock enable bit (Primary clock can be disabled by software)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

// CONFIG2L
#pragma config PWRTEN = OFF     // Power-up Timer Enable bit (Power up timer disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)
#pragma config BORV = 190       // Brown Out Reset Voltage bits (VBOR set to 1.90 V nominal)

// CONFIG2H
#pragma config WDTEN = OFF      // Watchdog Timer Enable bits (Watch dog timer is always disabled. SWDTEN has no effect.)
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config CCP2MX = PORTC1  // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = OFF     // PORTB A/D Enable bit (PORTB<5:0> pins are configured as digital I/O on Reset)
#pragma config CCP3MX = PORTB5  // P3A/CCP3 Mux bit (P3A/CCP3 input/output is multiplexed with RB5)
#pragma config HFOFST = OFF     // HFINTOSC Fast Start-up (HFINTOSC output and ready status are delayed by the oscillator stable status)
#pragma config T3CMX = PORTC0   // Timer3 Clock input mux bit (T3CKI is on RC0)
#pragma config P2BMX = PORTB5   // ECCP2 B output mux bit (P2B is on RB5)
#pragma config MCLRE = EXTMCLR  // MCLR Pin Enable bit (MCLR pin enabled, RE3 input pin disabled)

// CONFIG4L
#pragma config STVREN = OFF     // Stack Full/Underflow Reset Enable bit (Stack full/underflow will not cause Reset)
#pragma config LVP = OFF        // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
#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 Block 0 (Block 0 (000800-001FFFh) not code-protected)
#pragma config CP1 = OFF        // Code Protection Block 1 (Block 1 (002000-003FFFh) not code-protected)
#pragma config CP2 = OFF        // Code Protection Block 2 (Block 2 (004000-005FFFh) not code-protected)
#pragma config CP3 = OFF        // Code Protection Block 3 (Block 3 (006000-007FFFh) not code-protected)

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

// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection Block 0 (Block 0 (000800-001FFFh) not write-protected)
#pragma config WRT1 = OFF       // Write Protection Block 1 (Block 1 (002000-003FFFh) not write-protected)
#pragma config WRT2 = OFF       // Write Protection Block 2 (Block 2 (004000-005FFFh) not write-protected)
#pragma config WRT3 = OFF       // Write Protection Block 3 (Block 3 (006000-007FFFh) not write-protected)

// CONFIG6H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot Block (000000-0007FFh) 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 Block 0 (Block 0 (000800-001FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection Block 1 (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF      // Table Read Protection Block 2 (Block 2 (004000-005FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF      // Table Read Protection Block 3 (Block 3 (006000-007FFFh) not protected from table reads executed in other blocks)

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

#define FOSC 8000000
#define BAUD 9600
#define _XTAL_FREQ 8000000
/* ConfigRegisters */
#define CONFIG      0x00
#define EN_AA       0x01
#define EN_RXADDR   0x02
#define SETUP_AW    0x03
#define SETUP_RETR  0x04
#define RF_CH       0x05
#define RF_SETUP    0x06
#define STATUS      0x07
#define OBSERVE_TX  0x08
#define CD          0x09
#define RX_ADDR_P0  0x0A
#define RX_ADDR_P1  0x0B
#define RX_ADDR_P2  0x0C
#define RX_ADDR_P3  0x0D
#define RX_ADDR_P4  0x0E
#define RX_ADDR_P5  0x0F
#define TX_ADDR     0x10
#define RX_PW_P0    0x11
#define RX_PW_P1    0x12
#define RX_PW_P2    0x13
#define RX_PW_P3    0x14
#define RX_PW_P4    0x15
#define RX_PW_P5    0x16
#define FIFO_STATUS 0x17
#define DYNPD       0x1C
#define FEATURE     0x1D

/* Bit Mnemonics */
/* configuration register */
#define MASK_RX_DR  6
#define MASK_TX_DS  5
#define MASK_MAX_RT 4
#define EN_CRC      3
#define CRCO        2
#define PWR_UP      1
#define PRIM_RX     0

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

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

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

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

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

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

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

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

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

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

#define nrf24_CONFIG ((1 << MASK_RX_DR)|(1<<EN_CRC)|(1<<CRCO)|(1<<EN_CRC))

/// hardware SPI pin defined
#define CS_Pin       PORTAbits.RA5          //set port as output
#define CE_Pin       PORTBbits.RB1         //set port as output
#define SCK_Pin      PORTCbits.RC3        //set port as output
#define Mosi_Pin     PORTCbits.RC5         //set port as output
#define Miso_Pin     PORTCbits.RC4        //set port as input
#define HIGH         1
#define LOW          0

#define	_delay_us(x) { unsigned char us; \
us = (x)/(12000000/FOSC)|1; \
while(--us != 0) continue; }

void uart_init(){
 OSCTUNE = 0x00; //(INTSRC|PLLEN|TUN<5:0>)
 OSCCON = 0x67; //(IDLEN|IRCF<2:0>|OSTS|HFIOFS|SCS<1:0>)
 TRISB = 0x04;  //(TRISB7|TRISB6|TRISB5|TRISB4|TRISB3|TRISB2|TRISB1|TRISB0)
 TRISC = 0x90;  //(TRISC7|TRISC6|TRISC5|TRISC4|TRISC3|TRISC2|TRISC1|TRISC0)
 TRISAbits.RA5=0;
 ANSELC = 0x00;
 ANSELB = 0x00;
 ANSELA = 0x00;
 /*UART1 Initialization*/
 PORTCbits.RC6 = 1;
 PORTCbits.RC7 = 1;
 TXSTA1 = 0x24; //(CSRC|TX9|TXEN|SYNC|SENDB|BRGH|TRMT|TX9D)
 //SPBRGH1= 0x01;
 SPBRG1= 207;   //0xA0; 
 RCSTA1 = 0x96; //(SPEN|RX9|SREN|CREN|ADDEN|FERR|OERR|RX9D)
 BAUDCON1 =0x08;//(ABDOVF|RCIDL|DTRXP|CKTXP|BRG16|?|WUE|ABDEN)
}

void _delay_ms(unsigned int ms){
 unsigned int i;
 do {
 i = 6; //4;
    do {
    _delay_us(210);
    } while(--i);
 } while(--ms);
}

void SendByteSerially1(unsigned char Byte){  // Writes a character to the serial port
    while(!PIR1bits.TX1IF);  // wait for previous transmission to finish
    TXREG1 = Byte;
    _delay_ms(1);
}

void SPI_Init(){
     SSP1CON1bits.SSPEN = 0; 
     SSP1CON1 = 0x01;             // SPI Master mode, clock = Fosc/64
     SSP1STAT= 0xC0;             // CKE = 1
     SSP1CON1bits.SSPEN = 1; 
}

void nrf24_ce_digitalwrite(uint8_t state){
    if (state)
    {
    CE_Pin = 1;
    }
    else
    {
    CE_Pin = 0;
    }
}

void nrf24_csn_digitalwrite(uint8_t state){
    if (state)
    {
    CS_Pin = 1;
    }
    else
    {
    CS_Pin = 0;
    }
}

/* software SPI routine */
uint8_t spi_transfer(uint8_t tx){
    unsigned char temp;
    SSP1BUF = tx;           // send data to the BUFFER
    while(!SSP1STATbits.BF && !PIR1bits.SSP1IF);      // wait for the tramsit/recieve to finish
                          // has to be SSPSTAT.BF not just BF!! (for some reason)
    temp = SSP1BUF;           // clear the BF flag
    PIR1bits.SSP1IF = 0;
    return temp;
}

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

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

//send multiple bytes over SPI // checked with mirf
void nrf24_transmitSync(uint8_t *dataout,uint8_t len){
    uint8_t i;

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

void nrf24_readRegister(uint8_t reg,uint8_t *value,uint8_t len) //checked with mirf
{
    nrf24_csn_digitalwrite(LOW);
    spi_transfer(R_REGISTER | (REGISTER_MASK & reg));
    nrf24_transferSync(value,value,len);
    nrf24_csn_digitalwrite(HIGH);
}

void nrf24_configRegister(uint8_t reg, uint8_t *value, int num){
    int i;
    nrf24_csn_digitalwrite(LOW);
    spi_transfer(W_REGISTER | (REGISTER_MASK & reg));
    
    for(i=0;i<num; i++)
    {
    //SendByteSerially1(value[i]);

    spi_transfer(value[i]);
    }
    nrf24_csn_digitalwrite(HIGH);
   // SendByteSerially1(0x51);  
}

// checked with mirf
void nrf24_powerUpTx(){
    unsigned char flags;  
    flags = nrf24_CONFIG|((1<<PWR_UP)|(0<<PRIM_RX));
   // PTX = 1;
   nrf24_configRegister(CONFIG,(unsigned char*)&flags,1);

}

void setRFPWR(){
    unsigned char temp;
    temp=0x06;
    nrf24_configRegister(RF_SETUP,&temp,1);
//    nrf24_readRegister(RF_SETUP,&temp,1);
//    SendByteSerially1(temp);
//    SendByteSerially1(0x52);
}

void nrf24_init(uint8_t inittype){
    nrf24_ce_digitalwrite(LOW);
    nrf24_csn_digitalwrite(HIGH);
    nrf24_ce_digitalwrite(HIGH);
    _delay_us(15);
    nrf24_ce_digitalwrite(LOW);
    nrf24_powerUpTx();
    uint8_t val[5];

        uint8_t i;
        val[0]=108;

        nrf24_configRegister(RF_CH,val,1);

        val[0]=0x01;

        nrf24_configRegister(EN_AA,val,1);


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

            val[i]=0xC2;

        }

        nrf24_configRegister(RX_ADDR_P0,val,5);

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

            val[i]=0xE7;

        }

        nrf24_configRegister(TX_ADDR,val,5);

        val[0]=0x01;

        nrf24_configRegister(RX_PW_P0,val,1);
        val[0]=0x00;

        nrf24_configRegister(DYNPD,val,1);
        val[0]=0x7E;

        nrf24_configRegister(STATUS,val,1);
        val[0]=0x00;

        nrf24_configRegister(FEATURE,val,1);

        if(inittype==1)     //TX
        {

            val[0]=0x0E;

        }

        if(inittype==0)         //RX
        {

            val[0]=0x0F;

        }

        //nrf24_configRegister(CONFIG,val,1);
}

// check with mirf
void nrf24_send(uint8_t* value){
    /* Go to Standby-I first */
    nrf24_ce_digitalwrite(LOW);

    /* Set to transmitter mode , Power up if needed */
    //nrf24_powerUpTx();
    nrf24_csn_digitalwrite(LOW);
    spi_transfer(FLUSH_TX);
    nrf24_csn_digitalwrite(HIGH);

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

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

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

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

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

uint8_t data_array[3];

void main()
{
 unsigned char i;
 uart_init();
 SPI_Init();
 nrf24_init(1);
 //nrf24_powerUpTx();
 setRFPWR();
 nrf24_csn_digitalwrite(LOW);
 spi_transfer(FLUSH_TX);
 nrf24_csn_digitalwrite(HIGH);

while(1)
{
 data_array[0] = 0x6F;
 data_array[1] = 0x12;
 data_array[2] = 0x12;

 nrf24_send(data_array);
 _delay_ms(5000); // wait some time
 
 SendByteSerially1(data_array[0]);
 SendByteSerially1(data_array[1]);
 //SendByteSerially1(data_array[2]);

}
}

Receiver :-

#include <xc.h>
#include "stdint.h"
#include <p18f25k22.h>
#include <flash.h>
#include <stdio.h>
#include <string.h>
#include<plib/spi.h>

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

// CONFIG1H
#pragma config FOSC = INTIO67   // Oscillator Selection bits (Internal oscillator block)
#pragma config PLLCFG = OFF     // 4X PLL Enable (Oscillator used directly)
#pragma config PRICLKEN = OFF   // Primary clock enable bit (Primary clock can be disabled by software)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF       // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)

// CONFIG2L
#pragma config PWRTEN = OFF     // Power-up Timer Enable bit (Power up timer disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)
#pragma config BORV = 190       // Brown Out Reset Voltage bits (VBOR set to 1.90 V nominal)

// CONFIG2H
#pragma config WDTEN = OFF      // Watchdog Timer Enable bits (Watch dog timer is always disabled. SWDTEN has no effect.)
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config CCP2MX = PORTC1  // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = OFF     // PORTB A/D Enable bit (PORTB<5:0> pins are configured as digital I/O on Reset)
#pragma config CCP3MX = PORTB5  // P3A/CCP3 Mux bit (P3A/CCP3 input/output is multiplexed with RB5)
#pragma config HFOFST = OFF     // HFINTOSC Fast Start-up (HFINTOSC output and ready status are delayed by the oscillator stable status)
#pragma config T3CMX = PORTC0   // Timer3 Clock input mux bit (T3CKI is on RC0)
#pragma config P2BMX = PORTB5   // ECCP2 B output mux bit (P2B is on RB5)
#pragma config MCLRE = EXTMCLR  // MCLR Pin Enable bit (MCLR pin enabled, RE3 input pin disabled)

// CONFIG4L
#pragma config STVREN = OFF     // Stack Full/Underflow Reset Enable bit (Stack full/underflow will not cause Reset)
#pragma config LVP = OFF        // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
#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 Block 0 (Block 0 (000800-001FFFh) not code-protected)
#pragma config CP1 = OFF        // Code Protection Block 1 (Block 1 (002000-003FFFh) not code-protected)
#pragma config CP2 = OFF        // Code Protection Block 2 (Block 2 (004000-005FFFh) not code-protected)
#pragma config CP3 = OFF        // Code Protection Block 3 (Block 3 (006000-007FFFh) not code-protected)

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

// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection Block 0 (Block 0 (000800-001FFFh) not write-protected)
#pragma config WRT1 = OFF       // Write Protection Block 1 (Block 1 (002000-003FFFh) not write-protected)
#pragma config WRT2 = OFF       // Write Protection Block 2 (Block 2 (004000-005FFFh) not write-protected)
#pragma config WRT3 = OFF       // Write Protection Block 3 (Block 3 (006000-007FFFh) not write-protected)

// CONFIG6H
#pragma config WRTC = OFF       // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF       // Boot Block Write Protection bit (Boot Block (000000-0007FFh) 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 Block 0 (Block 0 (000800-001FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection Block 1 (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF      // Table Read Protection Block 2 (Block 2 (004000-005FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF      // Table Read Protection Block 3 (Block 3 (006000-007FFFh) not protected from table reads executed in other blocks)

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

#define FOSC 8000000
#define BAUD 9600
#define _XTAL_FREQ 8000000

/* Memory Map */
#define CONFIG      0x00
#define EN_AA       0x01
#define EN_RXADDR   0x02
#define SETUP_AW    0x03
#define SETUP_RETR  0x04
#define RF_CH       0x05
#define RF_SETUP    0x06
#define STATUS      0x07
#define OBSERVE_TX  0x08
#define CD          0x09
#define RX_ADDR_P0  0x0A
#define RX_ADDR_P1  0x0B
#define RX_ADDR_P2  0x0C
#define RX_ADDR_P3  0x0D
#define RX_ADDR_P4  0x0E
#define RX_ADDR_P5  0x0F
#define TX_ADDR     0x10
#define RX_PW_P0    0x11
#define RX_PW_P1    0x12
#define RX_PW_P2    0x13
#define RX_PW_P3    0x14
#define RX_PW_P4    0x15
#define RX_PW_P5    0x16
#define FIFO_STATUS 0x17
#define DYNPD       0x1C
#define FEATURE     0x1D

/* Bit Mnemonics */
/* configuration register */
#define MASK_RX_DR  6
#define MASK_TX_DS  5
#define MASK_MAX_RT 4
#define EN_CRC      3
#define CRCO        2
#define PWR_UP      1
#define PRIM_RX     0

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

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

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

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

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

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

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

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

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

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

#define nrf24_CONFIG ((1 << MASK_RX_DR)|(1<<EN_CRC)|(1<<CRCO)|(1<<EN_CRC))

/// hardware spi pin defined
#define CS_Pin       PORTAbits.RA5          //set port as output
#define CE_Pin       PORTBbits.RB1         //set port as output
#define SCK_Pin      PORTCbits.RC3        //set port as output
#define Mosi_Pin     PORTCbits.RC5         //set port as output
#define Miso_Pin     PORTCbits.RC4        //set port as input
#define HIGH         1
#define LOW          0

#define	_delay_us(x) { unsigned char us; \
us = (x)/(12000000/FOSC)|1; \
while(--us != 0) continue; }

void uart_init(){
 OSCTUNE = 0x00; //(INTSRC|PLLEN|TUN<5:0>)
 OSCCON = 0x67; //(IDLEN|IRCF<2:0>|OSTS|HFIOFS|SCS<1:0>)
 TRISB = 0x04;  //(TRISB7|TRISB6|TRISB5|TRISB4|TRISB3|TRISB2|TRISB1|TRISB0)
 TRISC = 0x90;  //(TRISC7|TRISC6|TRISC5|TRISC4|TRISC3|TRISC2|TRISC1|TRISC0)
 TRISAbits.RA5=0;
 ANSELC = 0x00;
 ANSELB = 0x00;
 ANSELA = 0x00;
 /*UART1 Initialization*/
 PORTCbits.RC6 = 1;
 PORTCbits.RC7 = 1;
 TXSTA1 = 0x24; //(CSRC|TX9|TXEN|SYNC|SENDB|BRGH|TRMT|TX9D)
 //SPBRGH1= 0x01;
 SPBRG1= 207;   //0xA0; 
 RCSTA1 = 0x96; //(SPEN|RX9|SREN|CREN|ADDEN|FERR|OERR|RX9D)
 BAUDCON1 =0x08;//(ABDOVF|RCIDL|DTRXP|CKTXP|BRG16|?|WUE|ABDEN)
}

void _delay_ms(unsigned int ms){
 unsigned int i;
 do {
 i = 6; //4;
    do {
    _delay_us(210);
    } while(--i);
 } while(--ms);
}

void SendByteSerially1(unsigned char Byte){  // Writes a character to the serial port
    while(!PIR1bits.TX1IF);  // wait for previous transmission to finish
    TXREG1 = Byte;
    _delay_ms(1);
}

void SPI_Init(){
     SSP1CON1bits.SSPEN = 0; 
     SSP1CON1 = 0x01;             // SPI Master mode, clock = Fosc/64
     SSP1STAT= 0xC0;             // CKE = 1
     SSP1CON1bits.SSPEN = 1; 
}

void nrf24_ce_digitalwrite(uint8_t state)
{
    if (state)
    {
    CE_Pin = 1;
    }
    else
    {
    CE_Pin = 0;
    }
}

void nrf24_csn_digitalwrite(uint8_t state)
{
    if (state)
    {
    CS_Pin = 1;
    }
    else
    {
    CS_Pin = 0;
    }
}

/* software spi routine */
uint8_t spi_transfer(uint8_t tx)
{
    unsigned char temp;
      SSP1BUF = tx;           // send data to the BUFFER
      while(!SSP1STATbits.BF && !PIR1bits.SSP1IF);      // wait for the tramsit/recieve to finish
                              // has to be SSPSTAT.BF not just BF!! (for some reason)
     temp = SSP1BUF;    
      PIR1bits.SSP1IF = 0;
      return temp;
}

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

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

//send multiple bytes over SPI // checked with mirf
void nrf24_transmitSync(uint8_t *dataout,uint8_t len)
{
    uint8_t i;

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

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

void nrf24_configRegister(uint8_t reg, uint8_t *value, int num)
{   int i;
    nrf24_csn_digitalwrite(LOW);
    spi_transfer(W_REGISTER | (REGISTER_MASK & reg));
    for(i=0;i<num; i++)
    {
    spi_transfer(value[i]);
    }
    nrf24_csn_digitalwrite(HIGH);
   // SendByteSerially1(0x51);
}

void nrf24_powerUpTx() // checked with mirf
{
    unsigned char val;
    val=nrf24_CONFIG|((1<<PWR_UP)|(0<<PRIM_RX));
   // PTX = 1;
    nrf24_configRegister(CONFIG, (unsigned char*)&val,1);

}

void nrf24_powerUpRx() // checked with mirf
{
    unsigned char val;
   // PTX = 0;
    val=nrf24_CONFIG|((1<<PWR_UP)|(1<<PRIM_RX));
    nrf24_configRegister(CONFIG, (unsigned char*)&val,1);
}

void setRFPWR(){
    unsigned char temp;
    temp=0x06;
    nrf24_configRegister(RF_SETUP,&temp,1);
//    nrf24_readRegister(RF_SETUP,&temp,1);
//    SendByteSerially1(temp);
//    SendByteSerially1(0x52);
}

void nrf24_init(uint8_t inittype)
{
    nrf24_ce_digitalwrite(LOW);
    nrf24_csn_digitalwrite(HIGH);
    _delay_us(10);
    nrf24_ce_digitalwrite(HIGH);
    nrf24_powerUpRx();
    uint8_t val[5];

        uint8_t i;
        val[0]=108;

        nrf24_configRegister(RF_CH,val,1);

        val[0]=0x01;

        nrf24_configRegister(EN_AA,val,1);

        val[0]=0x01;

        nrf24_configRegister(EN_RXADDR,val,1);

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

            val[i]=0xE7;

        }

        nrf24_configRegister(RX_ADDR_P0,val,5);

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

            val[i]=0xC2;

        }

        nrf24_configRegister(TX_ADDR,val,5);

        val[0]=0x01;

        nrf24_configRegister(RX_PW_P0,val,1);
        
        val[0]=0x00;

        nrf24_configRegister(DYNPD,val,1);
         val[0]=0x7E;

        nrf24_configRegister(STATUS,val,1);
        val[0]=0x00;

        nrf24_configRegister(FEATURE,val,1);
        if(inittype==1)     //TX

        {

                val[0]=0x0E;

        }

        if(inittype==0)     //RX

        {

                val[0]=0x0F;

        }

       // nrf24_configRegister(CONFIG,val,1);
}

void nrf24_send(uint8_t* value)   // check with mirf
{
    /* Go to Standby-I first */
    nrf24_ce_digitalwrite(LOW);

    /* Set to transmitter mode , Power up if needed */
   // nrf24_powerUpTx();
    nrf24_csn_digitalwrite(LOW);
    spi_transfer(FLUSH_TX);
    nrf24_csn_digitalwrite(HIGH);


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

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

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

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

    /* Start the transmission */
    nrf24_ce_digitalwrite(HIGH);

}

uint8_t nrf24_getStatus()    // checked with mirf
{
    uint8_t rv;
    nrf24_readRegister(STATUS,&rv,1);
    return rv;
}

uint8_t nrf24_dataReady() // check with mirf
// checks if data is available for reading
{
    // See note in getData() function - just checking RX_DR isn't good enough
    uint8_t status = nrf24_getStatus();

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

/* Reads payload bytes uint8_to data array */
void nrf24_getData(uint8_t *data1)  // check with mirf
{
    unsigned char val;
    /* Pull down chip select */
    nrf24_csn_digitalwrite(LOW);

    /* Send cmd to read rx payload */
    spi_transfer(R_RX_PAYLOAD);

    /* Read payload */
    nrf24_transferSync(data1,data1,2);
    
    /* Pull up chip select */
    nrf24_csn_digitalwrite(HIGH);
    
    nrf24_csn_digitalwrite(LOW);
    spi_transfer(FLUSH_RX);
    nrf24_csn_digitalwrite(HIGH);
    
    val=1<<RX_DR;
    /* Reset status register */
    nrf24_configRegister(STATUS,(unsigned char*)&val,1);
}

void main()
{
 unsigned char x;
 uint8_t data_array[3];
uart_init();
SPI_Init();
nrf24_init(0);
//nrf24_powerUpRx();
setRFPWR();
nrf24_csn_digitalwrite(LOW);
spi_transfer(FLUSH_RX);
nrf24_csn_digitalwrite(HIGH);

while(1)
{
 x=nrf24_dataReady();
 SendByteSerially1(x);
while(x);
nrf24_getData(data_array); 
if(data_array[0]>0)
SendByteSerially1(data_array[0]);
if(data_array[1]>0)
SendByteSerially1(data_array[1]);
//SendByteSerially1(data_array[2]);

if(data_array[0] == 0x6F)
    SendByteSerially1('Y');
//else
  //  SendByteSerially1('N');
data_array[0]=0x00;
data_array[1]=0x00;
x=0;
nrf24_ce_digitalwrite(LOW);
}
}
Related