PDA

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



csantex
- 9th September 2018, 01:43
'************************************************* ***************
; 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 *-*-*-*-*



;************************************************* *****************************
;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