; 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


Menu
Re: LCDOUT command followed by variable data
no , you can create your alias names for the array address' in the buffer in any way that you prefer or just use array notation and have no alias' at all
richard - 13th March 2026, 23:08