; 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
Re: LCD_AnyPin.pbp
Wow, I haven't used this routine yet, but I have to admit I would have fallen victim to that pesky detail as well. :wink:
Demon Yesterday, 23:44I added a NOTE to post #1 in case it helps someone.