; 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: SERIN2 Receiving Wrong Data
The sending device has the typical 18F4550 USB setup and it is set to "Define OSC 48". The receiving device is set to "DEFINE OSC 16".
rsocor01 Yesterday, 19:56