Quantcast
Channel: MEL PICBASIC Forum
Viewing all articles
Browse latest Browse all 4745

NRF24L01+ CODE Example for 1 to 1 data communication using same code on 2 PICs.

$
0
0
'************************************************* ***************
; This code allows for data communication between 2 NRF24L01+
; modules running on a PIC microcontroller using the MSSP module.
; In my version of the code, I use DT-18 interrutps to increment a counter once
; every 500ms. When the counter reaches 10, the PIC sets the module up in TX mode
; and transmits 5 bytes. When it has completed, it will pause for 25us and
; wait for the IRQ pin to go low so that it could be reset by the user.
;
; There are no Automatic Acknowledge Functions enabled and also no Re-Transmit
; Functions enabled. The settings are for bare-bones use only.
;
; No settings for the MSSP module are listed as the register settings vary from
; PIC to PIC. Variables and constants are listed.
; Data transfer is at 1Mpbs at 0dbm. It allows for up to 32 bytes to be transmitted
; and received using the same code on each PIC. You would just need to make the array
; to your desired size and adjust the configuration accordingly.
; This code was inspired from forum member vancalst, http://sites.google.com/site/avcnetsite/mcu.
; His is a very good project I might add!
'************************************************* ***************


;*-*-*-*-*BE SURE TO INCLUDE THE DT_INTS FOR WHATEVER PIC YOU'RE WORKING WITH *-*-*-*-*

Code:

;******************************************************************************
;Constants.
;******************************************************************************
; SPI NRF24L01 commands
    ReadCmd        con    $00          ; Read command to read registers.
    WriteCmd        con    $20          ; Write command to write to registers.
    ReadRxPld      con    $61          ; Read Rx payload register address.
    WriteTxPld      con    $A0          ; Write Tx payload register address.
    FlushTx        con    $E1          ; Flush Tx register command.
    FlushRx        con    $E2          ; Flush Rx register command.
    ReuseTxPld      con    $E3          ; Reuse Tx payload register command.
    NoOperate      con    $FF          ; No operation, for reading STATUS register.
   
;******************************************************************************
; SPI NRF24L01 registers addresses
    ConfigAddr      con    $00          ; Config register, address $00.                 
    EnAAAddr        con    $01          ; Auto Acknowledgement Function register, address $01.
    EnRxAddr        con    $02          ; Enable the Receiver register, address $02.
    SetupAWAddr    con    $03          ; Setup Address Widths of Data Pipes, register address $03.
    SetupReTxAddr  con    $04          ; Setup Automatic Retransmission register, address $04.   
    SetupRfChAddr  con    $05          ; RF Channel selection regsiter, address, $05. Channels 0 to 127.
    RfSetupAddr    con    $06          ; RF setup register address.
    StatusAddr      con    $07          ; Status register address.
    ObsrvTxAddr    con    $08          ; Observe TX register address.
    CardetectAddr  con    $09          ; NRF_Carrier detect register address.
    RxPipe0Addr    con    $0A          ; NRF_RX Pipe 0 register address.
    RxPipe1Addr    con    $0B          ; NRF_RX pipe 1 register address.
    RxPipe2Addr    con    $0C          ; NRF_RX pipe 2 register address.
    RxPipe3Addr    con    $0D          ; NRF_RX pipe 3 register address.
    RxPipe4Addr    con    $0E          ; NRF_RX pipe 4 register address.
    RxPipe5Addr    con    $0F          ; NRF_RX pipe 5 register address.
    TxADDRAddr      con    $10          ; NRF_TX AdDRESS register address.
    RxPwPipe0Addr  con    $11          ; NRF_RX payload width pipe0 register address.
    RxPwPipe1Addr  con    $12          ; NRF_RX payload width pipe1 register address.
    RxPwPipe2Addr  con    $13          ; NRF_RX payload width pipe2 register address.
    RxPwPipe3Addr  con    $14          ; NRF_RX payload width pipe3 register address.
    RxPwPipe4Addr  con    $15          ; NRF_RX payload width pipe4 register address.
    RxPwPipe5Addr  con    $16          ; NRF_RX payload width pipe5 register address.
    FifoStatAddr    con    $17          ; NRF_FIFO status register register address.
    DynPldAddr      con    $1C          ; NRF_DYNPD Enable dynamic payload register address.
    FeatureAddr    con    $1D          ; NRF_Feature register address.
   
;******************************************************************************
; Port Pin names.
;*******************************************************************************
    HeartBeat  var    PORTX.Y
    NrfChipEn  var    PORTX.Y
    NrfChipSel  var    PORTX.Y
    NrfMosi    var    PORTX.Y
    NrfMiso    var    PORTX.Y
    NrfClock    var    PORTX.Y
    NrfIRQ      var    PORTX.Y


;*******************************************************************************
; Variables listing.
;*******************************************************************************
    SPICounter          var byte    ; General Puspose Counter.
    RxTxCounter        var byte    ; General Puspose Counter.

    NrfRxPckt          var byte[8]   
    NrfTxPckt          var byte[8]

    WriteBytes          var byte
    Readbytes          var byte
    ReadSPIBuffer      var byte

;*******************************************************************************
;ASM INTERRUPTS COURTESY OF DARREL TAYLOR.   
ASM
INT_LIST  macro  ;  IntSource,      Label,            Type,  ResetFlag?
    INT_Handler    TMR1_INT,      _Heart_Beat,        PBP,    YES       
    endm     
    INT_CREATE              ; Creates the interrupt processor   
ENDASM


;*******************************************************************************
    goto Start

;*******************************************************************************
Heart_Beat:
    toggle HeartBeat
    RxTxCounter = RxTxCounter + 1
@ INT_RETURN


;*******************************************************************************
;*******************************************************************************
;*******************************************************************************
Start:
    clear
    SSPEN = 1                                ; Enable SPI pins
    NrfChipEn = 1                            ; Enable the NRF Module.
    NrfChipSel = 1                          ; Disable the NRF Module.
    pause 500                                ; Wait 500ms for the rest of the system to power up.


InitNRF:  ; All Common registers are written to sequentially, $01 - $1D. The WRITE command includes
          ; the regsiter address being written to. A data byte must followed the Write
          ; command. It will contain the information needing to be changed.


    ; Writing to Address $01
    NrfTxPckt[0] = WriteCmd + EnAAAddr      ; Read/Write to the EN_AA REGISTER Address $01.
    NrfTxPckt[1] = 000000                ; Data for EnAAAddr REGISTER Address $01. Disable all Auto Acknowledge Functions.
    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
    gosub NrfSPIWrite                        ; Send data to the Nrf Module.
   
    ; Writing to Address $02
    NrfTxPckt[0] = WriteCmd + EnRxAddr      ; Read/Write to the EN_RXADDR REGISTER Address $02.
    NrfTxPckt[1] = 000001                ; Data for EnAAAddr REGISTER Address $02. Enable Data Pipe o
    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
    gosub NrfSPIWrite                        ; Send data to the Nrf Module.
   
    ; Writing to Address $03
    NrfTxPckt[0] = WriteCmd + SetupAWAddr    ; Read/Write to the SETUP_AW REGISTER Address $03.
    NrfTxPckt[1] = 000001                ; Data for EnAAAddr REGISTER Address $03. Address width is 3 bytes long.
    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
    gosub NrfSPIWrite                        ; Send data to the Nrf Module.
   
    ; Writing to Address $04
    NrfTxPckt[0] = WriteCmd + SetupReTxAddr  ; Read/Write to the SETUP_RETR REGISTER Address $04.
    NrfTxPckt[1] = 010000                ; Data for EnAAAddr REGISTER Address $04. AutoRetransmit set min and disabled.
    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
    gosub NrfSPIWrite                        ; Send data to the Nrf Module.
   
    ; Writing to Address $05
    NrfTxPckt[0] = WriteCmd + SetupRfChAddr  ; Read/Write to the RF_CH REGISTER Address $05.
    NrfTxPckt[1] = 000010                ; Data for EnAAAddr REGISTER Address $05. Rf Channel is set to default.
    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
    gosub NrfSPIWrite                        ; Send data to the Nrf Module.
   
    ; Writing to Address $06
    NrfTxPckt[0] = WriteCmd + RfSetupAddr    ; Read/Write to the RF_SETUP REGISTER Address $06.
    NrfTxPckt[1] = 000110                ; Data for EnAAAddr REGISTER Address $06. Data rate at 1Mbps, at 0dbm.
    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
    gosub NrfSPIWrite                        ; Send data to the Nrf Module.

    ; Writing to Address $0A
    NrfTxPckt[0] = WriteCmd + RxPipe0Addr    ; Read/Write to the RX_ADDR_P0 REGISTER Address $0A.
    NrfTxPckt[1] = 000001                ; Data for EnAAAddr REGISTER Address $0A. Receive Address length is the same as address width.
                                            ; Set to one, Current AW value will only use 1 byte instead of 3.
    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
    gosub NrfSPIWrite                        ; Send data to the Nrf Module.
   
'    ; Writing to Address $0B
'    NrfTxPckt[0] = WriteCmd + RxPipe1Addr    ; Read/Write to the RX_ADDR_P1 Address $0B.
'    NrfTxPckt[1] = 000000                ; Data for EnAAAddr REGISTER Address $0B. Receive Address length is the same as address width.
'                                            ; Set to one, Current AW value will only use 1 byte instead of 3.
'    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
'    gosub NrfSPIWrite                        ; Send data to the Nrf Module.
   
'    ; Writing to Address $0C
'    NrfTxPckt[0] = WriteCmd + RxPipe2Addr    ; Read/Write to the RX_ADDR_P2 Address $0C.
'    NrfTxPckt[1] = 000000                ; Data for EnAAAddr REGISTER Address $0C. Receive Address length is the same as address width.
'                                            ; Set to one, Current AW value will only use 1 byte instead of 3.
'    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
'    gosub NrfSPIWrite                        ; Send data to the Nrf Module.
   
'    ; Writing to Address $0D
'    NrfTxPckt[0] = WriteCmd + RxPipe3Addr    ; Read/Write to the RX_ADDR_P3 Address $0D.
'    NrfTxPckt[1] = 000000                ; Data for EnAAAddr REGISTER Address $0D. Receive Address length is the same as address width.
'                                            ; Set to one, Current AW value will only use 1 byte instead of 3.
'    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
'    gosub NrfSPIWrite                        ; Send data to the Nrf Module.
   
'    ; Writing to Address $0E
'    NrfTxPckt[0] = WriteCmd + RxPipe4Addr    ; Read/Write to the RX_ADDR_P4 Address $0E.
'    NrfTxPckt[1] = 000000                ; Data for EnAAAddr REGISTER Address $0E. Receive Address length is the same as address width.
'                                            ; Set to one, Current AW value will only use 1 byte instead of 3.
'    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
'    gosub NrfSPIWrite                        ; Send data to the Nrf Module.
   
'    ; Writing to Address $0F
'    NrfTxPckt[0] = WriteCmd + RxPipe5Addr    ; Read/Write to the RX_ADDR_P5 Address $0F.
'    NrfTxPckt[1] = 000000                ; Data for EnAAAddr REGISTER Address $0F. Receive Address length is the same as address width.
'                                            ; Set to one, Current AW value will only use 1 byte instead of 3.
'    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
'    gosub NrfSPIWrite                        ; Send data to the Nrf Module.
   
    ; Writing to Address $10
    NrfTxPckt[0] = WriteCmd + TxADDRAddr    ; Read/Write to the TX_ADDR REGISTER Address $10.
    NrfTxPckt[1] = 000001                ; Data for EnAAAddr REGISTER Address $10. Set to same as Receive Address.
    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
    gosub NrfSPIWrite                        ; Send data to the Nrf Module.
   
    ; Writing to Address $11
    NrfTxPckt[0] = WriteCmd + RxPwPipe0Addr  ; Read/Write to the RX_PW_P0 REGISTER Address $11.
    NrfTxPckt[1] = 000101                ; Data for EnAAAddr REGISTER Address $11. Set the number of bytes expected to be received.
    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
    gosub NrfSPIWrite                        ; Send data to the Nrf Module.
   
'    ; Writing to Address $12
'    NrfTxPckt[0] = WriteCmd + RxPwPipe1Addr  ; Read/Write to the RX_PW_P1 REGISTER Address $12.
'    NrfTxPckt[1] = 000000                ; Data for EnAAAddr REGISTER Address $12. Set the number of bytes expected to be received.
'    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
'    gosub NrfSPIWrite                        ; Send data to the Nrf Module.
   
'    ; Writing to Address $13
'    NrfTxPckt[0] = WriteCmd + RxPwPipe2Addr  ; Read/Write to the RX_PW_P2 REGISTER Address $13.
'    NrfTxPckt[1] = 000000                ; Data for EnAAAddr REGISTER Address $13. Set the number of bytes expected to be received.
'    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
'    gosub NrfSPIWrite                        ; Send data to the Nrf Module.
   
'    ; Writing to Address $14
'    NrfTxPckt[0] = WriteCmd + RxPwPipe3Addr  ; Read/Write to the RX_PW_P3 REGISTER Address $14.
'    NrfTxPckt[1] = 000000                ; Data for EnAAAddr REGISTER Address $14. Set the number of bytes expected to be received.
'    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
'    gosub NrfSPIWrite                        ; Send data to the Nrf Module.
   
'    ; Writing to Address $15
'    NrfTxPckt[0] = WriteCmd + RxPwPipe4Addr  ; Read/Write to the RX_PW_P4 REGISTER Address $15.
'    NrfTxPckt[1] = 000000                ; Data for EnAAAddr REGISTER Address $15. Set the number of bytes expected to be received.
'    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
'    gosub NrfSPIWrite                        ; Send data to the Nrf Module.
   
'    ; Writing to Address $16
'    NrfTxPckt[0] = WriteCmd + RxPwPipe5Addr  ; Read/Write to the RX_PW_P5 REGISTER Address $16.
'    NrfTxPckt[1] = 000000                ; Data for EnAAAddr REGISTER Address $16. Set the number of bytes expected to be received.
'    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
'    gosub NrfSPIWrite                        ; Send data to the Nrf Module.


'    ; Writing to Address $1C
'    NrfTxPckt[0] = WriteCmd + DynPldAddr    ; Read/Write to the DYNPD REGISTER Address $1C.
'    NrfTxPckt[1] = 000000                ; Data for EnAAAddr REGISTER Address $1C. Indicate that packets will be of different lengths for each data pipe.
'    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
'    gosub NrfSPIWrite                        ; Send data to the Nrf Module.
   
'    ; Writing to Address $1D
'    NrfTxPckt[0] = WriteCmd + FeatureAddr    ; Read/Write to the FEATURE REGISTER Address $1D.
'    NrfTxPckt[1] = 000000                ; Data for EnAAAddr REGISTER Address $1D. Enable/Disable extra features.
'    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
'    gosub NrfSPIWrite                        ; Send data to the Nrf Module.
 
    gosub NrfRxMode
    NrfChipSel = 1                          ; Deselect the NRF Module.
   
    NrfChipEn = 1                            ; Enable the NRF Module.


@  INT_ENABLE  TMR1_INT                    ; Enable Timer 1 interrupts.

;*******************************************************************************
Main:
rx:
    if RxTxCounter = 10 then : RxTxCounter = 0 : gosub tx
    if NrfIRQ = 0 then
        NrfChipEn = 0                        ; Disable the NRF Module.
        gosub  NrfWriteStatus
        gosub NrfSPIReadPayload
        gosub FlushRxRegs
        NrfChipEn = 1                        ; Enable the NRF Module.
        hserout2  [str NrfRxPckt\6,13,10]    ; Send straight to USB           
    endif
    goto main


;*******************************************************************************
tx:
    NrfChipEn = 0                            ; Disable the NRF Module.
    gosub NrfTxMode 


LoadTXPckt:
    NrfTxPckt[0] = WriteTxPld                ; Write Tx payload register address. Address $A0.                         
    NrfTxPckt[1] = "T"                      ; Data for WriteTxPld REGISTER.
    NrfTxPckt[2] = "E"                      ; Data for WriteTxPld REGISTER.
    NrfTxPckt[3] = "S"                      ; Data for WriteTxPld REGISTER.
    NrfTxPckt[4] = "T"                      ; Data for WriteTxPld REGISTER.
    NrfTxPckt[5] = "1"                      ; Data for WriteTxPld REGISTER.
    WriteBytes = 5                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?       


    gosub NrfSPIWrite                        ; Send data to the Nrf Module. 


    NrfChipEn = 1                            ; Enable the NRF Module.
    pauseus 25                              ; Wait for for the module to complete transmission.
    NrfChipEn = 0                            ; Disable the NRF Module.
    pauseus 200                              ; Wait for IRQ to go low
    gosub  NrfWriteStatus                    ; Clear all flags in the module Status Register.


    gosub NrfRxMode
    NrfChipSel = 1                          ; Diselect the NRF Module.
    NrfChipEn = 1                            ; Enable the NRF Module.
    return     


;*******************************************************************************
NrfWriteStatus:
    ; Writing to Address $07
    NrfTxPckt[0] = WriteCmd + StatusAddr    ; Read/Write to the STATUS REGISTER Address $07.
    NrfTxPckt[1] = 110000                ; Data for EnAAAddr REGISTER Address $07.
    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
    gosub NrfSPIWrite
    return
;*******************************************************************************
NrfTxMode:
    ; Writing to Address $00 
    NrfTxPckt[0] = WriteCmd + ConfigAddr    ; Read/Write to the CONFIG REGISTER Address $00.
    NrfTxPckt[1] = 000010                ; Data for CONFIG REGISTER Address $00.
    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
    gosub NrfSPIWrite                        ; Send data to the Nrf Module.
    ; Writing to Address $07
    NrfTxPckt[0] = WriteCmd + StatusAddr    ; Read/Write to the STATUS REGISTER Address $07.
    NrfTxPckt[1] = 010000                ; Data for EnAAAddr REGISTER Address $07. Mask RXDataReceived and MAXRetransmit.
    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
    gosub NrfSPIWrite                        ; Send data to the Nrf Module.     
    ; Writing to Address $1D
    NrfTxPckt[0] = FlushTx                  ; Write command to flush the TX Payload register.
    WriteBytes = 0                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ? 
    gosub NrfSPIWrite                        ; Send data to the Nrf Module.
    return
   
;*******************************************************************************
NrfRxMode:
    ; Writing to Address $00 
    NrfTxPckt[0] = WriteCmd + ConfigAddr    ; Read/Write to the CONFIG REGISTER Address $00.
    NrfTxPckt[1] = 110011                ; Data for CONFIG REGISTER Address $00.
    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
    gosub NrfSPIWrite                        ; Send data to the Nrf Module. 
    ; Writing to Address $07
    NrfTxPckt[0] = WriteCmd + StatusAddr    ; Read/Write to the STATUS REGISTER Address $07.
    NrfTxPckt[1] = 110000                ; Data for EnAAAddr REGISTER Address $07. Mask TXDataSent and MAXRetransmit.
    WriteBytes = 1                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
    gosub NrfSPIWrite                        ; Send data to the Nrf Module.
    return
   
;*******************************************************************************
FlushRxRegs:
    ; Writing to Address $1D
    NrfTxPckt[0] = Flushrx                  ; Write command to flush the TX Payload register.                       
    WriteBytes = 0                          ; Number of byte to write to SPI module. 0 = 1 byte, counts from 0 to ?
    gosub NrfSPIWrite                        ; Send data to the Nrf Module.
    return 


;*******************************************************************************
SSP2IF_Check:
    while SSP2IF = 0                        ; Wait for the MSSP module to finish transmitting.
    wend
    SSP2IF = 0
    return
   
;*******************************************************************************
NrfStatus:
    while NrfMiso = 1                        ; Wait until module is ready to accept new data.
    wend                                   
    return


;******************************************************************************* 
NrfSPIWrite:
    NrfChipSel = 0                          ; Select the NRF Module.
    for SPICounter = 0 to WriteBytes
        SSP2BUF = NrfTxPckt[SPICounter]      ; Write to the SPI buffer.
        gosub SSP2IF_Check                  ; Wait for the MSSP module to finish transmitting.
    Next SPICounter
    NrfChipSel = 1                          ; Deselect the NRF Module.
    return
   
;******************************************************************************* 
NrfSPIReadPayload:
    NrfChipSel = 0                          ; Select the NRF Module.   
    SSP2BUF = ReadRxPld                      ; Write to the SPI buffer.
    gosub SSP2IF_Check                      ; Wait for the MSSP module to finish transmitting.
    for SPICounter = 0 to 4                  ; Initialize counter to number of bytes being received.
        SSP2BUF = $FF                        ; Write No_Op byte to the SPI buffer.
        gosub SSP2IF_Check                  ; Wait for the MSSP module to finish transmitting.
        NrfRxPckt[SPICounter] = SSP2BUF      ; Copy the received byte from the SPI buffer.
    Next SPICounter
    NrfChipSel = 1                          ; Deselect the NRF Module.
    return
   
;******************************************************************************* 
    end


Viewing all articles
Browse latest Browse all 4745

Trending Articles