SparkFun Forums 

Where electronics enthusiasts find answers.

All things pertaining to wireless and RF links
By ssaguiar
#32345
Hi to all.

I am trying to make an rf link using the 24l01 transceiver.
I am using a code based on the demo code for the sparkfun mirf v2 board.

I am using the CCS compiler.

The transmitter uses a PIC12F629 and the receiver uses a PIC16F877A.
The transmitter transmit, then enter the sleep mode and, after 1152 ms (+-), exit from sleep and repeat the cycle (this to make battery last more).

I can´t get it to work.
Can somebody help me to locate what I am doing wrong?
The code of Transmitter and Receiver are pasted below.

Any help is much apreciated.
Thanks
Sergio

Transmiter:
Code: Select all

#include <12f629.h>
#device adc=8
#FUSES WDT                       //Watch Dog Timer
#FUSES INTRC_IO                  //Internal RC Osc, no CLKOUT
#FUSES PUT                       //Power Up Timer
#FUSES NOMCLR                    //Master Clear pin used for I/O
#FUSES NOBROWNOUT                //No brownout reset
#FUSES NOCPD                     //No EE protection
#FUSES NOPROTECT                 //Code not protected from reading

#use delay(clock=4000000)

/*******************************************************************/

#define CE      PIN_A0  // output Chip enable to nRF24L01 CE PIN_1 
#define CSN     PIN_A5  // output Chip Select to nRF24L01 CSN PIN_2 
#define SCK     PIN_A1  // serial clock output to nRF24L01 SCK PIN_3 
#define MOSI    PIN_A4  // serial data out to nRF24L01 MOSI PIN_4 
#define MISO    PIN_A2  // serial data in from nRF24L01 MISO PIN_5 
#define IRQ     PIN_A3  // input valid TX/RX from nRF24L01 IRQ PIN_6 

/*******************************************************************/

unsigned int cmd, data, j;

/*******************************************************************/

void NRF24l01_Send(int dat);
void TX_Mode    (void);
void TX_Data    (void);

/*******************************************************************/

void main()
{
    setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);setup_wdt(WDT_1152MS);
    setup_timer_1(T1_DISABLED);
    setup_comparator(NC_NC_NC_NC);
    enable_interrupts(GLOBAL);
    
    while(1)
    {
      delay_ms(2); // Wait for everything to settle...
      TX_Mode(); 
      TX_Data(); 
      delay_ms(10);
      restart_wdt ();           // Restart WatchDog
      sleep();
    } 

}

/*******************************************************************/

void TX_Mode()
{

    output_low(CSN);
    output_low(CE);

    cmd=0x20;   // 0010 0000 - Write register 0 - CONFIG
    data=0x38;  // 0011 1000 - PTX, CRC enabled
                // bit 7 - RESERVED
                // bit 6 - MASK_RX_DR
                // bit 5 - MASK_TX_DS
                // bit 4 - MASK_MAX_RT
                // bit 3 - EN_CRC
                // bit 2 - CRCO
                // bit 1 - PWR_UP
                // bit 0 - PRIM_RX

    NRF24l01_Send(cmd);
    NRF24l01_Send(data);
    
    output_high(CSN);
    delay_us(20);
    output_low(CSN);
    
    cmd=0x24;   // 0010 0100 - Write register 4 - SETUP_RETR
    data=0x00;  // 0000 0000 - Wait 250+86 ms - Re-transmit disabled
                // bit 7 - ARD
                // bit 6 - ARD
                // bit 5 - ARD
                // bit 4 - ARD
                // bit 3 - ARC
                // bit 2 - ARC
                // bit 1 - ARC
                // bit 0 - ARC

    NRF24l01_Send(cmd);
    NRF24l01_Send(data);
    output_high(CSN);
    delay_us(20);
    output_low(CSN);

    cmd=0x23;   // 0010 0011 - Write register 3 - SETUP_AW
    data=0x03;  // 0000 0011 - ADDRESS Width = 3
                // bit 7 - RESERVED
                // bit 6 - RESERVED
                // bit 5 - RESERVED
                // bit 4 - RESERVED
                // bit 3 - RESERVED
                // bit 2 - RESERVED
                // bit 1 - AW
                // bit 0 - AW

    NRF24l01_Send(cmd);
    NRF24l01_Send(data);
    output_high(CSN);
    delay_us(20);
    output_low(CSN);    

    cmd=0x26;   // 0010 0110 - Write register 6 - RF_SETUP
    data=0x07;  // 0000 0111 - DATA RATE = 1 Mb
                // bit 7 - RESERVED
                // bit 6 - RESERVED
                // bit 5 - RESERVED
                // bit 4 - PLL_LOCK
                // bit 3 - RF_DR
                // bit 2 - RF_PWR
                // bit 1 - RF_PWR
                // bit 0 - LNA_HCURR

    NRF24l01_Send(cmd);
    NRF24l01_Send(data);
    output_high(CSN);
    delay_us(20);
    output_low(CSN);
        
    cmd=0x25;   // 0010 0101 - Write register 5 - RF_CH
    data=0x02;  // 0000 0010 - Set Channel 2
                // bit 7 - RESERVED
                // bit 6 - RF_CH
                // bit 5 - RF_CH
                // bit 4 - RF_CH
                // bit 3 - RF_CH
                // bit 2 - RF_CH
                // bit 1 - RF_CH
                // bit 0 - RF_CH

    NRF24l01_Send(cmd);
    NRF24l01_Send(data);
    output_high(CSN);
    delay_us(20);
    output_low(CSN);
    
    cmd=0x30;   // 0011 0000 - Write register 10 - TX_ADDR
    data=0xE7;  // 1110 0111 - Set Address E7E7E7E7E7.

    NRF24l01_Send(cmd);
    
    for(j=0;j<5;j++)
    NRF24l01_Send(data);    
    
    output_high(CSN);
    delay_us(20);
    output_low(CSN);
    
    cmd=0x21;   // 0010 0001 - Write register 1 - EN_AA
    data=0x00;  // 0000 0000 - Disable AUTOACK
                // bit 7 - RESERVED
                // bit 6 - RESERVED
                // bit 5 - ENAA_P5
                // bit 4 - ENAA_P4
                // bit 3 - ENAA_P3
                // bit 2 - ENAA_P2
                // bit 1 - ENAA_P1
                // bit 0 - ENAA_P0 

    NRF24l01_Send(cmd);
    NRF24l01_Send(data);
    output_high(CSN);
    delay_us(20);
    output_low(CSN); 
    
} 

/*******************************************************************/

void TX_Data()
{

    output_low(CSN);

    cmd=0x27;   // 0010 0111 - Write register 7 - STATUS
    data=0x7E;  // 0111 1110 - Clear Ints
                // bit 7 - RESERVED
                // bit 6 - RX_DR
                // bit 5 - TX_DS
                // bit 4 - MAX_RT
                // bit 3 - RX_P_NO
                // bit 2 - RX_P_NO
                // bit 1 - RX_P_NO
                // bit 0 - TX_FULL

    NRF24l01_Send(cmd);
    NRF24l01_Send(data);
    output_high(CSN);
    delay_us(20);
    output_low(CSN);

    cmd=0xE1;   // (1110 0001) - Flush TX
    data=0x3A;  // 0011 1010 - Power up module
                // bit 7 - RESERVED
                // bit 6 - MASK_RX_DR
                // bit 5 - MASK_TX_DS
                // bit 4 - MASK_MAX_RT
                // bit 3 - EN_CRC
                // bit 2 - CRCO
                // bit 1 - PWR_UP
                // bit 0 - PRIM_RX

    NRF24l01_Send(cmd);
    NRF24l01_Send(data);
    output_high(CSN);
    delay_us(20);
    output_high(CE);
    
    cmd = 0xA0;         // 1010 0000 - Write tx_payload
    NRF24l01_Send(cmd);
    
    data = 0x34;        // 0011 0100 - First byte of payload 
    NRF24l01_Send(data);
    data = 0x33;        // 0011 0011 - Second byte of payload
    NRF24l01_Send(data); 
    data = 0x32;        // 0011 0010 - Third byte of payload
    NRF24l01_Send(data); 
    data = 0x31;        // 0011 0001 - Fourth byte of payload
    NRF24l01_Send(data);
    
    output_high(CSN); 
    delay_us(20);     
    output_high(CE); 
    delay_us(20); 
    output_low(CE); 
} 

/*******************************************************************/

void NRF24l01_Send(int dat)
{

    int i;
    
    for (i=0;i<8;i++)
    {    
        if (dat && 0x80)
        {
            output_high(MOSI);
        }
        else
        {
            output_low(MOSI);        
        }
        
        output_high(SCK);
        output_low(SCK);
        dat <<=1;        
     }//for (i...
}

/*******************************************************************/
Receiver:
Code: Select all

#case
#include <16F877.h>
#device *=16

/*******************************************************************/

//Change the following to change the clock frequency
#define CRYSTAL_FREQ       8000000
#define YES                1
#define NO                 0
#define ON                 1
#define OFF                0
#define HIGH               1
#define LOW                0
#define LCD_D0             PIN_B4
#define LCD_D1             PIN_B5
#define LCD_D2             PIN_B6
#define LCD_D3             PIN_B7
#define LCD_EN             PIN_B3
#define LCD_RS             PIN_B2
#define RX_IN              PIN_B2
#define BUZZER             PIN_D0
#define LED                PIN_B7
#define LINE_1             0x00
#define LINE_2             0x40
#define LINE_3             0x10
#define LINE_4             0x50
#define CLEAR_DISP         0x01
#define CR                 13
#define SPACE              ' '
#define PERIOD             '.'
#define PLUS               '+'
#define RX_BUFFER_SIZE     40

// Control and SPI Pin defines ////////////////////////////////////////// 
#define CE                  PIN_C1 // output Chip enable to nRF24L01 CE
#define CSN                 PIN_C2 // output Chip Select to nRF24L01 CSN
#define SCK                 PIN_C3 // serial clock output to nRF24L01 SCK 
#define MOSI                PIN_C5 // serial data out to nRF24L01 MOSI
#define MISO                PIN_C4 // serial data in from nRF24L01 MISO
#define IRQ                 PIN_B0 // input valid TX/RX from nRF24L01 IRQ

// LED indicator Pins 
#define LED0                PIN_A0 
#define LED1                PIN_A1
#define LED2                PIN_A2
#define LED_Activity        PIN_A3 

/*******************************************************************/

#separate void InitRxBuffer     ( void );
#separate void LCD_Init         ( void );
#separate void LCD_SetPosition  ( unsigned int cX );
#separate void LCD_PutChar      ( unsigned int cX );
#separate void LCD_PutCmd       ( unsigned int cX );
#separate void LCD_PulseEnable  ( void );
#separate void LCD_SetData      ( unsigned int cX );
#separate void Play             (void);
#separate void Zero_cC          (void);
#separate void RF_Config_RX     (void);
#separate void NRF24l01_Send    (int cmd);
#separate void NRF24l01_Rx_RST  (void);

/*******************************************************************/

#fuses HS, NOPROTECT, PUT, NOWDT, NOBROWNOUT//, NOLVP//, NOCPD

#use standard_io ( A )
#use standard_io ( B )
#use standard_io ( C )
#use delay ( clock = CRYSTAL_FREQ )
#use rs232 ( baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS, stream=TAG )

#priority RDA, RTCC

/*******************************************************************/

static char     cRxBuffer[RX_BUFFER_SIZE]; // RX Buffer
static char     cRxMsgReady, cRxByteCnt;
static char     *cRxBufferWritePtr, *cRxBufferReadPtr;// Pointer for the Rx buffer
unsigned int    dataready;
unsigned int    Timer_1ms, Timer_100ms, Timer_1s;// Timers 1ms, 100ms, 1s
unsigned int    ID_1, ID_2, ID_3, ID_4, state;
//long            CRC xFFFF;

enum
{
   State_IDDLE,
   State_TIMEOUT_Second,
   State_ID_Received
};

/*******************************************************************/

#INT_EXT
EXTINT_isr()
{
    if(!input(PIN_B0))         // keep button action sychronized wth button flag
    {
      ID_1 ++;
    
          if (ID_1 == 0)
          {
             ID_2 ++;
    
             if (ID_2 ==0)
             {
                ID_3 ++;
    
                if (ID_3 == 0)
                {
                    ID_4 ++;
    
                    if (ID_4 == 0)
                    {
                        ID_1 = 1;
                    }// if (ID_4
                }// if (ID_3...
             }// if )ID_2...
          }// if (ID_1...
    
        state = State_ID_Received;
        //delay_ms(10);
    }
    
    return (0);
}

/*******************************************************************/

#INT_TIMER0
TIMER0_isr()
{
   set_timer0(100);                    // Restart 1 ms timming

   if (Timer_1ms++ >= 100)             // If 100 ms
    {
      Timer_1ms =0;                    // Reset counter
      Timer_100ms++;                   // Increment 100 ms counter
      output_toggle(LED_Activity);     // Toggle the state of led
    }

   if (Timer_100ms >= 10)              // 1 second?
   {
      Timer_100ms =0;                  // Reset 100ms counter
      Timer_1s++;                      // Increment 1 second counter
      state = State_TIMEOUT_Second;    // 1 second elapsed.
   }
   
   return(0);
}

/*******************************************************************/

void main ( void )

    {
    
    disable_interrupts ( GLOBAL );      // Just in case...
    set_tris_a(00000000);               // 1 --> Input 0 --> output
    set_tris_b(00000001);               // 1 --> Input 0 --> output
    set_tris_c(00000000);               // 1 --> Input 0 --> output
    set_tris_d(00000000);               // 1 --> Input 0 --> output
    
    setup_adc_ports(NO_ANALOGS);        // Set PortA Digital IO 
    setup_adc(ADC_OFF);                 // Turn off ADC 
    setup_ccp1(CCP_OFF);                // Turn off CCP - will disrupt output writes on PIN_B3 if on 
    //setup_spi(SPI_MASTER|SPI_XMIT_L_TO_H|SPI_CLK_DIV_64);
    setup_timer_1(T1_DISABLED);         // Disable Timer 1
    setup_timer_2(T2_DISABLED,0,1);     // Disable Timer 2
    output_float ( RX_IN );             // Ensure Rx input is HiZ
    LCD_Init();                         // Set up LCD for 4-wire bus, etc.
    delay_ms(200);                      // wait lcd...
    
    ID_1        = 0;
    ID_2        = 0;
    ID_3        = 0;
    ID_4        = 0;
    
    Timer_1ms   = 0;                    // Reset Timer counters
    Timer_100ms = 0;                    //   "     "       "
    Timer_1s    = 0;                    //   "     "       "
    
    dataready   = FALSE;
    /* INIT MESSAGE */
    LCD_SetPosition ( LINE_1 + 0 );
    printf ( LCD_PutChar, "2.4 GHz Terminal" );   // welcome screen
    LCD_SetPosition ( LINE_2 + 0 );
    printf ( LCD_PutChar, "    RFtreck    " );
    output_low(CE);                     // set CE low to disable transmission
    output_low(LED0 | LED1 | LED2 | LED_Activity); // set LEDs Low 
    delay_ms(2); 
    output_high(LED0);

    setup_timer_0(RTCC_INTERNAL|RTCC_DIV_128);//Internal counter and div by 64
    set_timer0(100);                    // Count 156 times (20000000/128/156 = 1ms)
    enable_interrupts ( INT_TIMER0);    // enable timer0 interrupt
    ext_int_edge(H_TO_L);               // Interrupção na descida do pulso.
    enable_interrupts(INT_EXT);
    //aqui, limpar os flags de interrupções, senão gera int na b0...
    
    enable_interrupts ( GLOBAL );       // enable all interrupts
    delay_ms(100);
    output_low(LED0); 

    Play (); // Starting Connection to modem...
    
    RF_Config_RX(); // Init NRF24l01 in reception mode.

/********************************************************************
    MAIN LOOP
********************************************************************/

        while(1)
        {
        
            switch   (state)
            {
            
                case     State_IDDLE:
                
                    break;
            
                case    State_ID_Received:
                {
                    disable_interrupts ( GLOBAL );
                    NRF24l01_Rx_RST();
                    LCD_PutCmd (CLEAR_DISP); // Clear LCD.
                    LCD_SetPosition ( LINE_1 + 0 );
                    printf ( LCD_PutChar, " Recebido dado." );
                    LCD_SetPosition ( LINE_2 + 0 );
                    printf ( LCD_PutChar, "    %X%X%X%X    ", ID_4, ID_3, ID_2, ID_1 );
                    fprintf ( TAG,"%X%X%X%X\n\r", ID_4, ID_3, ID_2, ID_1 );
                    //LCD_PutCmd (CLEAR_DISP); // Clear LCD.
                    state = State_IDDLE;
                    enable_interrupts ( GLOBAL ); // Enable all interrupts
                    
                    break;
                  }
                  
                  case  State_TIMEOUT_Second:
                  {
                    disable_interrupts ( GLOBAL );
                    output_toggle(LED2);     // Toggle the state of led
                    state = State_IDDLE;
                    enable_interrupts ( GLOBAL ); // Enable all interrupts
                  }
                  
                  default:                
                    state = State_IDDLE;        
                    break;      
            }//switch (state)
        }//while(1)

    }

/*******************************************************************/

/* LCD FUNCTIONS ==================================================*/

#separate void LCD_Init ( void )

    {
    LCD_SetData ( 0x00 );
    delay_ms ( 200 );       /* wait enough time after Vdd rise */
    output_low ( LCD_RS );
    LCD_SetData ( 0x03 );   /* init with specific nibbles to start 4-bit mode */
    LCD_PulseEnable();
    LCD_PulseEnable();
    LCD_PulseEnable();
    LCD_SetData ( 0x02 );   /* set 4-bit interface */
    LCD_PulseEnable();      /* send dual nibbles hereafter, MSN first */
    LCD_PutCmd ( 0x2C );    /* function set (all lines, 5x7 characters) */
    LCD_PutCmd ( 0x0C );    /* display ON, cursor off, no blink */
    LCD_PutCmd ( 0x01 );    /* clear display */
    LCD_PutCmd ( 0x06 );    /* entry mode set, increment & scroll left */
    }

/*******************************************************************/

#separate void LCD_SetPosition ( unsigned int cX )

    {
    /* this subroutine works specifically for 4-bit Port A */
    LCD_SetData ( swap ( cX ) | 0x08 );
    LCD_PulseEnable();
    LCD_SetData ( swap ( cX ) );
    LCD_PulseEnable();
    }

/*******************************************************************/

#separate void LCD_PutChar ( unsigned int cX )

    {
    /* this subroutine works specifically for 4-bit Port A */
        output_high ( LCD_RS );
        LCD_SetData ( swap ( cX ) );     /* send high nibble */
        LCD_PulseEnable();
        LCD_SetData ( swap ( cX ) );     /* send low nibble */
        LCD_PulseEnable();
        output_low ( LCD_RS );
    }

/*******************************************************************/

#separate void LCD_PutCmd ( unsigned int cX )

    {
    /* this subroutine works specifically for 4-bit Port A */
    LCD_SetData ( swap ( cX ) );     /* send high nibble */
    LCD_PulseEnable();
    LCD_SetData ( swap ( cX ) );     /* send low nibble */
    LCD_PulseEnable();
    }

/*******************************************************************/

#separate void LCD_PulseEnable ( void )

    {
    output_high ( LCD_EN );
    delay_us ( 3 );         // was 10
    output_low ( LCD_EN );
    delay_ms ( 3 );         // was 5
    }

/*******************************************************************/

#separate void LCD_SetData ( unsigned int cX )

    {
    output_bit ( LCD_D0, cX & 0x01 );
    output_bit ( LCD_D1, cX & 0x02 );
    output_bit ( LCD_D2, cX & 0x04 );
    output_bit ( LCD_D3, cX & 0x08 );
    }

/*******************************************************************/

/* RS232 FUNCTIONS ================================================*/

#separate void InitRxBuffer ( void )

    {
    disable_interrupts ( INT_RDA );
    memset  (cRxBuffer, 0, sizeof(cRxBuffer)); // Zero Buffer.
    Zero_cC(); // Zero Buffer cC
    cRxBufferWritePtr = cRxBuffer;      // Point to beginning of buffer.
    cRxBufferReadPtr  = cRxBuffer;      // "            "           "
    cRxByteCnt = 0;                     // Number of chars received.
    cRxMsgReady = NO;                   // Message is not ready to process.
    enable_interrupts ( INT_RDA );      // Enable serial interrupt.
    enable_interrupts ( GLOBAL );       // Enable all interrupts.
    }

/*******************************************************************/

#separate void Play (void)

{
    // Play a tone in Buzzer (for debug only).

    output_high (BUZZER);
    delay_ms (250);
    output_low (BUZZER);
}

/*******************************************************************/

void RF_Config_RX (void)
{

    int j, data, cmd;
    
    output_low(CSN);
    output_low(CE);

    cmd=0x20;   // 0010 0000 - Write register 0 - CONFIG
    data=0x39;  // 0011 1001 - PRX, CRC enabled
                // bit 7 - RESERVED
                // bit 6 - MASK_RX_DR
                // bit 5 - MASK_TX_DS
                // bit 4 - MASK_MAX_RT
                // bit 3 - EN_CRC
                // bit 2 - CRCO
                // bit 1 - PWR_UP
                // bit 0 - PRIM_RX
                
    NRF24l01_Send(cmd);
    NRF24l01_Send(data);
    output_high(CSN);
    output_low(CSN);

    cmd=0x21;   // 0010 0001 - Write register 1 - EN_AA
    data=0x00;  // 0000 0000 - Disable AUTOACK
                // bit 7 - RESERVED
                // bit 6 - RESERVED
                // bit 5 - ENAA_P5
                // bit 4 - ENAA_P4
                // bit 3 - ENAA_P3
                // bit 2 - ENAA_P2
                // bit 1 - ENAA_P1
                // bit 0 - ENAA_P0 

    NRF24l01_Send(cmd);
    NRF24l01_Send(data);
    output_high(CSN);
    output_low(CSN);

    cmd=0x23;   // 0010 0011 - Write register 3 - SETUP_AW
    data=0x03;  // 0000 0011 - ADDRESS Width = 3
                // bit 7 - RESERVED
                // bit 6 - RESERVED
                // bit 5 - RESERVED
                // bit 4 - RESERVED
                // bit 3 - RESERVED
                // bit 2 - RESERVED
                // bit 1 - AW
                // bit 0 - AW

    NRF24l01_Send(cmd);
    NRF24l01_Send(data);
    output_high(CSN);
    output_low(CSN);

    cmd=0x26;   // 0010 0110 - Write register 6 - RF_SETUP
    data=0x07;  // 0000 0111 - DATA RATE = 1 Mb
                // bit 7 - RESERVED
                // bit 6 - RESERVED
                // bit 5 - RESERVED
                // bit 4 - PLL_LOCK
                // bit 3 - RF_DR
                // bit 2 - RF_PWR
                // bit 1 - RF_PWR
                // bit 0 - LNA_HCURR

    NRF24l01_Send(cmd);
    NRF24l01_Send(data);
    output_high(CSN);
    output_low(CSN);

    cmd=0x31;   // 0011 0001 - Write register 11 - RX_PW_P0
    data=0x04;  // 0000 0100 - Data payload = 4 bytes
                // bit 7 - RESERVED
                // bit 6 - RESERVED
                // bit 5 - RX_PW_P0
                // bit 4 - RX_PW_P0
                // bit 3 - RX_PW_P0
                // bit 2 - RX_PW_P0
                // bit 1 - RX_PW_P0
                // bit 0 - RX_PW_P0

    NRF24l01_Send(cmd);
    NRF24l01_Send(data);
    output_high(CSN);
    output_low(CSN);

    cmd=0x25;   // 0010 0101 - Write register 5 - RF_CH
    data=0x02;  // 0000 0010 - Set Channel 2
                // bit 7 - RESERVED
                // bit 6 - RF_CH
                // bit 5 - RF_CH
                // bit 4 - RF_CH
                // bit 3 - RF_CH
                // bit 2 - RF_CH
                // bit 1 - RF_CH
                // bit 0 - RF_CH

    NRF24l01_Send(cmd);
    NRF24l01_Send(data);
    output_high(CSN);
    output_low(CSN);

    cmd=0x30;   // 0011 0000 - Write register 10 - TX_ADDR
    data=0xE7;  // 1110 0111 - Set Address E7E7E7E7E7.

    NRF24l01_Send(cmd);
    
    for(j=0;j<5;j++)
    NRF24l01_Send(data);    
    
    output_high(CSN);
    output_low(CSN);

    cmd=0x20;   // 0010 0000 - Write register 0 - CONFIG
    data=0x3B;  // 0011 1011 - Power up module
                // bit 7 - RESERVED
                // bit 6 - MASK_RX_DR
                // bit 5 - MASK_TX_DS
                // bit 4 - MASK_MAX_RT
                // bit 3 - EN_CRC
                // bit 2 - CRCO
                // bit 1 - PWR_UP
                // bit 0 - PRIM_RX

    NRF24l01_Send(cmd);
    NRF24l01_Send(data);
    output_high(CSN);
    output_high(CE);
    
}

/*******************************************************************/

void NRF24l01_Send(int dat)
{

    int i;
    
    for (i=0;i<8;i++)
    {    
        if (dat && 0x80)
        {
            output_high(MOSI);
        }
        else
        {
            output_low(MOSI);        
        }
        
        output_high(SCK);
        output_low(SCK);
        dat <<=1;        
     }//for (i...
}

/*******************************************************************/

void NRF24l01_Rx_RST  (void)
{

    int i, j, data, cmd;
    
    cmd = 0x61; // 0110 0001 - Read RX Payload
    
    output_low (CSN);
    NRF24l01_Send(cmd);
    
    for (j=0; j<4; j++)
    {
        data=0;
        for (i=0;i<8;i++)
        {
            output_high(SCK);
            shift_left(&data, 1, input(MISO));
            output_low(SCK);        
        }// for (i=0...
        
        printf("%X", data);    
    }// for (j=0...
    
    printf("\n\r");
    
    cmd=0xE2;// 1110 0010 - Flush RX FIFO
    
    output_low (CSN);
    NRF24l01_Send(cmd);
    output_high(CSN);
    output_low(CSN);
    
    cmd=0x27;   // 0010 0111 - Write Register 7 - STATUS
    data=0x40;  // 0100 0000 - Reset INTs
                // bit 7 - RESERVED
                // bit 6 - RX_DR
                // bit 5 - TX_DS
                // bit 4 - MAX_RT
                // bit 3 - RX_P_NO
                // bit 2 - RX_P_NO
                // bit 1 - RX_P_NO
                // bit 0 - TX_FULL
                
    NRF24l01_Send(cmd);
    NRF24l01_Send(data);
    output_high(CSN);
}

/*******************************************************************/
By brennen
#32348
You might want to have a look at my code to see if it helps you (tutorials are at my website listed in my tag line). You should first test that you are communicating from your micro to its connected 24L01 over SPI. If you are, I would suggest then simply trying to ping a receiver from a transmitter (like I do in Tutorial 1 on my site). This would require you stripping out all of the timer code and stuff like that, though. If your devices don't talk over SPI, then check your hardware and fix as necessary until they do.
By bmckenney
#32373
Without looking any deeper:
Code: Select all
        if (dat && 0x80) 
This doesn't do what you want. Try:
Code: Select all
        if (dat &  0x80) 
By ssaguiar
#32377
Thank you for the replies.

I corrected the bug in the NRF24l01_Send routine (changed the && by & :oops: ).

The transmit code also was changed and now is :
Code: Select all

void TX_Mode()
{

    CE=0;
    //--------------------------------------------------------------        
    CSN=0;
    cmd=0x20;   // 0010 0000 - Write register 0 - CONFIG
    data=0x38;  // 0011 1000 - PTX, CRC enabled
                // bit 7 - RESERVED
                // bit 6 - MASK_RX_DR
                // bit 5 - MASK_TX_DS
                // bit 4 - MASK_MAX_RT
                // bit 3 - EN_CRC
                // bit 2 - CRCO
                // bit 1 - PWR_UP
                // bit 0 - PRIM_RX

    NRF24l01_Send(cmd);
    NRF24l01_Send(data);    
    CSN=1;
    delay_us(20);
    //--------------------------------------------------------------        
    CSN=0;    
    cmd=0x24;   // 0010 0100 - Write register 4 - SETUP_RETR
    data=0x00;  // 0000 0000 - Wait 250+86 ms - Re-transmit disabled
                // bit 7 - ARD
                // bit 6 - ARD
                // bit 5 - ARD
                // bit 4 - ARD
                // bit 3 - ARC
                // bit 2 - ARC
                // bit 1 - ARC
                // bit 0 - ARC

    NRF24l01_Send(cmd);
    NRF24l01_Send(data);
    CSN=1;
    delay_us(20);
    //--------------------------------------------------------------        
    CSN=0;
    cmd=0x23;   // 0010 0011 - Write register 3 - SETUP_AW
    data=0x03;  // 0000 0011 - ADDRESS Width = 3
                // bit 7 - RESERVED
                // bit 6 - RESERVED
                // bit 5 - RESERVED
                // bit 4 - RESERVED
                // bit 3 - RESERVED
                // bit 2 - RESERVED
                // bit 1 - AW
                // bit 0 - AW

    NRF24l01_Send(cmd);
    NRF24l01_Send(data);
    CSN=1;
    delay_us(20);
    //--------------------------------------------------------------        
    CSN=0;    
    cmd=0x26;   // 0010 0110 - Write register 6 - RF_SETUP
    data=0x07;  // 0000 0111 - DATA RATE = 1 Mb
                // bit 7 - RESERVED
                // bit 6 - RESERVED
                // bit 5 - RESERVED
                // bit 4 - PLL_LOCK
                // bit 3 - RF_DR
                // bit 2 - RF_PWR
                // bit 1 - RF_PWR
                // bit 0 - LNA_HCURR

    NRF24l01_Send(cmd);
    NRF24l01_Send(data);
    CSN=1;
    delay_us(20);
    //--------------------------------------------------------------        
    CSN=0;        
    cmd=0x25;   // 0010 0101 - Write register 5 - RF_CH
    data=0x02;  // 0000 0010 - Set Channel 2
                // bit 7 - RESERVED
                // bit 6 - RF_CH
                // bit 5 - RF_CH
                // bit 4 - RF_CH
                // bit 3 - RF_CH
                // bit 2 - RF_CH
                // bit 1 - RF_CH
                // bit 0 - RF_CH

    NRF24l01_Send(cmd);
    NRF24l01_Send(data);
    CSN=1;
    delay_us(20);
    //--------------------------------------------------------------        
    CSN=0;    
    cmd=0x30;   // 0011 0000 - Write register 10 - TX_ADDR
    data=0xE7;  // 1110 0111 - Set Address E7E7E7E7E7.

    NRF24l01_Send(cmd);
    
    for(j=0;j<5;j++) NRF24l01_Send(data);        
    CSN=1;
    delay_us(20);
    //--------------------------------------------------------------        
    CSN=0;    
    cmd=0x21;   // 0010 0001 - Write register 1 - EN_AA
    data=0x00;  // 0000 0000 - Disable AUTOACK
                // bit 7 - RESERVED
                // bit 6 - RESERVED
                // bit 5 - ENAA_P5
                // bit 4 - ENAA_P4
                // bit 3 - ENAA_P3
                // bit 2 - ENAA_P2
                // bit 1 - ENAA_P1
                // bit 0 - ENAA_P0 

    NRF24l01_Send(cmd);
    NRF24l01_Send(data);
    CSN=1;
    delay_us(20);
} 

/*******************************************************************/

void TX_Data()
{

    CSN=0;
    cmd=0x27;   // 0010 0111 - Write register 7 - STATUS
    data=0x7E;  // 0111 1110 - Clear Ints
                // bit 7 - RESERVED
                // bit 6 - RX_DR
                // bit 5 - TX_DS
                // bit 4 - MAX_RT
                // bit 3 - RX_P_NO
                // bit 2 - RX_P_NO
                // bit 1 - RX_P_NO
                // bit 0 - TX_FULL

    NRF24l01_Send(cmd);
    NRF24l01_Send(data);
    CSN=1;
    delay_us(20);
    //--------------------------------------------------------------        
    CSN=0;
    cmd=0x20;   // 0010 0000 - Write register 0 - CONFIG
    data=0x3A;  // 0011 1010 - Power up module - PTX
                // bit 7 - RESERVED
                // bit 6 - MASK_RX_DR
                // bit 5 - MASK_TX_DS
                // bit 4 - MASK_MAX_RT
                // bit 3 - EN_CRC
                // bit 2 - CRCO
                // bit 1 - PWR_UP
                // bit 0 - PRIM_RX

    NRF24l01_Send(cmd);
    NRF24l01_Send(data);
    CSN=1;
    delay_us(20);
    //--------------------------------------------------------------        
    CSN=0;
    cmd=0xE1;   // 1110 0001 - FLUSH_TX
    NRF24l01_Send(cmd);
    CSN=1;
    delay_us(20);    
    //--------------------------------------------------------------        
    CSN=0;    
    cmd = 0xA0;         // 1010 0000 - Write tx_payload    
    data = 0x34;        // 0011 0100 - Size of Payload - Four bytes     
    NRF24l01_Send(cmd);
    NRF24l01_Send(data);    
    data = 0x34;        // 0011 0100 - First byte of payload
    NRF24l01_Send(data); 
    data = 0x33;        // 0011 0011 - Second byte of payload
    NRF24l01_Send(data); 
    data = 0x32;        // 0011 0010 - Third byte of payload
    NRF24l01_Send(data); 
    data = 0x31;        // 0011 0001 - Fourth byte of payload
    NRF24l01_Send(data);     
    delay_us(20);
    CSN=1;
    //--------------------------------------------------------------    
    CE=1; 
    delay_ms(1);        // Pulse CE to transmit datagram.
    CE=0; 
} 
It still don´t work.
By DarioG
#32563
What is not working, the whole tx/rx , or just the "go-to-sleep" ?
By ssaguiar
#32577
DarioG wrote:What is not working, the whole tx/rx , or just the "go-to-sleep" ?
The whole tx/rx (in reality, I can't test the transmitter because I don't have an osciloscope ant it's powered by a 3025 coin battery, so my logic probe (5Volts) don't work).
For the receiver, I am using a development board from mikroelektronics (EasyPIC3), that have everything I need (leds, buttons, rs-232, display, etc...), so I can see all signals (but not the timming).
For testing purpose, in the receiver part, I modified the NRF24l01_Send() routine so, for every bit I put on the MOSI pin, I read the state of the MISO pin.
I discovered that the MISO pin do not change - it's allways 0 (zero).
The module is being powered fine (I am using a 3.3 volts regulator, from the 5 V supply). The pins are all connected directly to the processor, that is powered by 5 Volts supply (the NRF24l01 pins are all 5 Volts tolerant - just the supply must be 3 volts).

I am reading again the NRF24l01 manual to see what is the timming of it.
Maybe I am wrong in this, but, the code I am using is based on the example from sparkfun, I just did it in CCS compiler.

I have 4 modules (from Nordic), but I seriously am thinking that they are all dead...

Anyway, I will try to make a simple program to write and read from the 24l01 registers.

I will keep trying.
By busonerd
#32578
Coin battery is dubious - I have not been impressed with those things ability to source current. Try it with a real PS to see if that fixes it up.

One note -we test the TX + RX of all the modules we sell before we ship them. Its conceivable that one might have died in shipping, but I doubt 4 would have.

Cheers,

--David Carne
By ssaguiar
#32579
Dear David:

Thank you for your answer.
I believe that the modules you sell are ok. The ones we own, we purchased from a representative seller of Nordic, here in Brazil.
I just told that, about all 4 being dead, because I am desesperate, but I really don't believe in this.
As I said, I am reading the MISO after altering the MOSI in the NRF24l01_Send routine and it keeps returning 0 (zero).

I really don't know what is happening - probably it's just some simple matter, but I can't get it.

Cheers.

Sergio
By grasspuddle
#32640
Step 1 in making the mirf work is to verify you can write to the registers. Read in the register, write data to it, then read again to verify you have changed it. Once you can make that work, you're almost done.
By ssaguiar
#32653
Thank you grasspuddle.

I translated some of the code of the Nordic application to CCS and I am not getting any register to read.
The code is below:
Code: Select all
/*******************************************************************/
//
//
/*******************************************************************/
#case
#include <16F877.h>
#device *=16

/*******************************************************************/
//Change the following to change the clock frequency
#define CRYSTAL_FREQ       4000000

/*******************************************************************/
#fuses HS, NOPROTECT, PUT, NOWDT, NOBROWNOUT//, NOLVP//, NOCPD

#use standard_io ( A )
#use standard_io ( B )
#use standard_io ( C )
#use delay ( clock = CRYSTAL_FREQ )
#use rs232 ( baud=9600, xmit=PIN_C6, rcv=PIN_C7, stream=TAG )

/*******************************************************************/
// Control and SPI Pin defines ////////////////////////////////////// 
#byte   PORTA             = 0x05
#byte   PORTB             = 0x06
#byte   PORTC             = 0x07
#bit    CE                = PORTC.1 // output Chip enable to nRF24L01 CE
#bit    CSN               = PORTC.2 // output Chip Select to nRF24L01 CSN
#bit    SCK               = PORTC.3 // serial clock output to nRF24L01 SCK 
#bit    MOSI              = PORTC.5 // serial data out to nRF24L01 MOSI
#bit    MISO              = PORTC.4 // serial data in from nRF24L01 MISO
#bit    IRQ               = PORTB.0 // input valid TX/RX from nRF24L01 IRQ

/*******************************************************************/
// Define nRF24L01 interrupt flag's
#define IDLE            0x00  // Idle, no interrupt pending
#define MAX_RT          0x10  // Max #of TX retrans interrupt
#define TX_DS           0x20  // TX data sent interrupt
#define RX_DR           0x40  // RX data received

/*******************************************************************/
// SPI(nRF24L01) commands
#define READ_REG        0x00  // Define read command to register
#define WRITE_REG       0x20  // Define write command to register
#define RD_RX_PLOAD     0x61  // Define RX payload register address
#define WR_TX_PLOAD     0xA0  // Define TX payload register address
#define FLUSH_TX        0xE1  // Define flush TX register command
#define FLUSH_RX        0xE2  // Define flush RX register command
#define REUSE_TX_PL     0xE3  // Define reuse TX payload register command
#define NOP             0xFF  // Define No Operation, might be used to read status register

/*******************************************************************/
// SPI(nRF24L01) registers(addresses)
#define CONFIG          0x00  // 'Config' register address
#define EN_AA           0x01  // 'Enable Auto Acknowledgment' register address
#define EN_RXADDR       0x02  // 'Enabled RX addresses' register address
#define SETUP_AW        0x03  // 'Setup address width' register address
#define SETUP_RETR      0x04  // 'Setup Auto. Retrans' register address
#define RF_CH           0x05  // 'RF channel' register address
#define RF_SETUP        0x06  // 'RF setup' register address
#define STATUS          0x07  // 'Status' register address
#define OBSERVE_TX      0x08  // 'Observe TX' register address
#define CD              0x09  // 'Carrier Detect' register address
#define RX_ADDR_P0      0x0A  // 'RX address pipe0' register address
#define RX_ADDR_P1      0x0B  // 'RX address pipe1' register address
#define RX_ADDR_P2      0x0C  // 'RX address pipe2' register address
#define RX_ADDR_P3      0x0D  // 'RX address pipe3' register address
#define RX_ADDR_P4      0x0E  // 'RX address pipe4' register address
#define RX_ADDR_P5      0x0F  // 'RX address pipe5' register address
#define TX_ADDR         0x10  // 'TX address' register address
#define RX_PW_P0        0x11  // 'RX payload width, pipe0' register address
#define RX_PW_P1        0x12  // 'RX payload width, pipe1' register address
#define RX_PW_P2        0x13  // 'RX payload width, pipe2' register address
#define RX_PW_P3        0x14  // 'RX payload width, pipe3' register address
#define RX_PW_P4        0x15  // 'RX payload width, pipe4' register address
#define RX_PW_P5        0x16  // 'RX payload width, pipe5' register address
#define FIFO_STATUS     0x17  // 'FIFO Status Register' register address

#define TX_ADR_LENGTH   5     // 5 bytes TX(RX) address width
#define TX_PLOAD_WIDTH  16    // 16 bytes TX payload
#define TX_AW     5
#define RX_AW     5
#define TX_PL_W   32

/*******************************************************************/
int SPI_RW (char byte);
int SPI_Read(char reg);
int SPI_RW_Reg (char reg, char value);
int SPI_Write_Buf(char reg, char *pbuf, char bytes);

/*******************************************************************/
int result;
char buffer[32];
// Predefine a static TX address
char TX_ADDRESS[TX_ADR_LENGTH]  = {0x34,0x43,0x10,0x10,0x01}; 
// Predefine TX payload packet..
char TX_PAYLOAD[TX_PLOAD_WIDTH] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
                                   0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
char RX_ADDRESS_[RX_AW]   = {0x40,0x50,0x60,0x70,0x80};// Predefined RX_Address

/*******************************************************************/
void main ( void )

{  
   int regcounter;
   
   disable_interrupts ( GLOBAL );      // Just in case...
   set_tris_c(00010000);               // 1 --> Input 0 --> output
   setup_adc(ADC_OFF);                 // Turn off ADC 
   setup_timer_1(T1_DISABLED);         // Disable Timer 1
   setup_timer_2(T2_DISABLED,0,1);     // Disable Timer 2
  
   CE = 0;
   result = SPI_RW_Reg(WRITE_REG + SETUP_AW, (TX_AW-2)); // Setup RX/TX address width
   printf ("Result = %X\n\r", result);
   result = SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS_,RX_AW);// Writes RX_Addr
   printf ("Result = %X\n\r", result);
   result = SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PL_W);  // Pipe0 payload width
   printf ("Result = %X\n\r", result);
   result = SPI_RW_Reg(WRITE_REG + STATUS, 0x70);       // read status & clear IRQ flag's
   printf ("Result = %X\n\r", result);
   result = SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);        // Enable auto ack pipe0
   printf ("Result = %X\n\r", result);
   result = SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);    // Enable pipe0
   printf ("Result = %X\n\r", result);
   result = SPI_RW_Reg(WRITE_REG + SETUP_RETR,0x0a);    // 250µs+86µs, 10 retrans...
   printf ("Result = %X\n\r", result);
   result = SPI_RW_Reg(WRITE_REG + RF_CH, 40);          // Channel 40
   printf ("Result = %X\n\r", result);
   result = SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f);       // PWR_UP, CRC(2bytes) & Prim:RX.
   printf ("Result = %X\n\r", result);
   printf ("\n\rRegisters:\n\r");
   for (regcounter=0; regcounter<17; regcounter++)
   {
      result = SPI_Read(regcounter);
      printf ("Register %X Value: %X\n\r", regcounter, result);   
   }
   CE = 1;
   
   while(1)
   {
   
   }
}
/*******************************************************************/
// Function: SPI_RW

int SPI_RW (char byte)
{
    int bit_ctr, byte2;
    byte2 = 0;
    
    printf("Byte= %X MOSI = ", byte);
    
    for (bit_ctr=0; bit_ctr<8; bit_ctr++)
    {
        MOSI = (bit_test(byte,7));
        if (MOSI) printf("1"); else printf("0");
        byte = (byte<<1);
        SCK = 1;
        if (MISO) bit_set(byte2,0);
        byte2 <<= 1;
        delay_ms(1);
        SCK = 0;
    }
    printf(" ");
    MOSI = 0;
    return (byte2);
}

/*******************************************************************/
// Function: SPI_Read

int SPI_Read(char reg)
{
    int reg_val;
    
    CSN = 0;
    SPI_RW(reg);
    reg_val = SPI_RW(0);
    CSN = 1;
    
    return (reg_val);
}
/*******************************************************************/
//Function: SPI_RW_Reg

int SPI_RW_Reg (char reg, char value)
{
    int status;
    
    CSN = 0;
    status = SPI_RW(reg);
    SPI_RW(value);
    CSN =1;
    
    return (status);
}
/*******************************************************************/
// Function: SPI_Write_Buf
int SPI_Write_Buf(char reg, char *pbuf, char bytes)
{
    int status, byte_ctr;
    
    CSN = 0;
    status = SPI_RW(reg);
    
    for (byte_ctr=0; byte_ctr<bytes; byte_ctr++)
    {
        SPI_RW(*pbuf++);       
    }

    CSN = 1;
    return (status);
}
This is not working with any of the 4 modules I have.

The circuit is connected as below:

pic CE to 24l01 CE
pic CSN to 24l01 CSN
pic SCK to 24l01 SCK
pic MOSI to 24l01 MOSI
pic MISO to 24l01 MISO
IRQ is not being used at this time.
The 24l01 supply is 3.3 Volts, from regulator.
The pic is powered by 5 Volts (the 24l01 pins are 5 Volts tolerant)

Can you tell me if the code above is correct?

I asked, at the firm where I work, to purchase some 24l01 modules from Spark Fun.

Thank you very much.

Sergio
By bmckenney
#32665
Code: Select all
        if (MISO) bit_set(byte2,0);
        byte2 <<= 1;
This shifts by one-too-many. Try reversing the order of these two
statements.

This would explain incorrect results, though not all-00 results.
By lucicop
#32674
bmckenney is right, you are shifting one bit too much to the left. You should shift it before testing the current bit. Are you able to see at the debug string the exact data you are sending and still you receive nothing on MISO ? Check that CSn pin is set to output and that it is low when it should be. Are you able to use a debugger to check some pin states and variables ? Or at least you should use a led as an indication that a certain step has completed successfully. For example, check a condition, and if it is true, light the led, and after that put a while (1); to lock the program at that point. If the condition verifies successfully, go to the next step to check for validity.

Also, you might check the pins you are using for SPI, maybe one of them is not suitable to use as a full I/O pin (e.g. PORTA4 for most PICS needs a pull-up in order to use it as a normal I/O pin).

PS: I have checked PIC12F629's datasheet, and from what I see, on the MISO pin you need a pull-up, because it's a ST input, and not a TTL one (you could enable an internal weak pull-up maybe ?).
By ssaguiar
#32680
Thank you lucicop and bmckenney.

I changed the routine to shift the byte2 before the MISO test and added 2 leds to see what´s happening with the MOSI and MISO pins.
Now, the routine is as below, but still not working (allways, the return in MISO pin is 0, with all 4 modules).
Code: Select all
/*******************************************************************/
// Function: SPI_RW

int SPI_RW (char byte)
{
    int bit_ctr, byte2;
    byte2 = 0;
    
    printf("Byte= %X MOSI = ", byte);
    
    for (bit_ctr=0; bit_ctr<8; bit_ctr++)
    {
        MOSI = (bit_test(byte,7));
        if (MOSI)
        {
            printf("1");
            LED2 = 1;
        }
        else
        {
            printf("0");
            LED2 = 0;
        }
        byte = (byte<<1);
        SCK = 1;
        
        byte2 <<= 1;
        if (MISO)
        {
            LED1 = 1;
            bit_set(byte2,0);
        }
        else
        {
            LED1 = 0;
        }
        
        delay_ms(1);
        SCK = 0;
    }
    printf(" ");
    MOSI = 0;
    return (byte2);
}
I am pretty sure that the modules are defective.

Sergio
By lucicop
#32726
I also am pretty sure that you should try also a pull-up on MISO line :) Or try moving it to another pin.
By ssaguiar
#32753
Thank you lucicop.

The code that is not working (the one I am working now), is the code
for the receiver and this code is being used in a pic16f877A, as you
can on the header (#include <16f877.h>.
The pic12f629 MISO pin I am using for the transmitter, really needs
a pull-up resistor and i am using it (a 10K resistor to vcc).
But, at this time, I am restarting trying to comunicate with the module
using the 16f877A, to discover where I made some mistake.
I am almost there. I am abble now, to receive something on the MISO
pin, with the 16f877A circuit, on the receiver.

As soon as it´s working, I will post the code.

Sergio