#include #include #include #include #include #include "spi.h" #include "nrf24l01.h" #include "nrf24l01_definitions.h" extern volatile bool nrfInterruptRaised; void Print_Register_Contents(uint8_t address); void Send_TX_Flush_Command(void); void Send_RX_Flush_Command(void); static uint8_t Write_One_Byte(uint8_t byte1); static uint8_t Write_Two_Bytes(uint8_t byte1, uint8_t byte2); static void Write_Byte_And_Buffer(uint8_t byte, uint8_t * buffer, uint8_t length); /* Startup and initial configuration of the NRF24L01 */ void Initialize_NRF24L01(void) { CONFIG_REGISTER configRegisterContents = {.byte = 0x0}; /* Configure the AVR pins for the nrf24l01 */ Set_NRF24L01_Pins(); /* Wait more than 10.3 ms to make sure the nrf24l01 is running */ _delay_ms(11); /* Write the PWR_UP bit of the CONFIG register (EN_CRC is also set) */ configRegisterContents.bits.EN_CRC = 0x1; configRegisterContents.bits.PWR_UP = 0x1; Write_NRF_Register(CONFIG_ADDRESS, configRegisterContents.byte); /* Wait more than 1.5 ms for the change to take effect */ _delay_ms(2); /* The NRF24L01 is now in the mode Standby-I */ } void Set_NRF24L01_Pins(void) { /* Set up the NRF24L01 */ NRF_CE_DDR |= (1 << NRF_CE_PIN); NRF_CSN_DDR |= (1 << NRF_CSN_PIN); /* Set the chip select pin to not selected */ NRF_CSN_PORT |= (1 << NRF_CSN_PIN); /* Ensure that the CE pin is set to 0*/ NRF_CE_PORT &= ~(1 << NRF_CE_PIN); /* Set the interrupt pin */ NRF_IRQ_DDR &= ~(1 << NRF_IRQ_PIN); // Set the pin as input NRF_IRQ_PORT |= (1 << NRF_IRQ_PORT); // Enable the pullup for the pin } void Configure_Transmission(uint8_t moduleId) { SETUP_RETR_REGISTER setupRetrRegisterContents = {.byte = 0x0}; EN_RXADDR_REGISTER enableRxAddressesRegisterContents = {.byte = 0x0}; RX_PW_Pn_REGISTER rxPwPnRegisterContents = {.byte = 0x0}; EN_AA_REGISTER enAaRegister = {.byte = 0x0}; FEATURE_REGISTER featureRegisterContents = {.byte = 0x0}; DYNPD_REGISTER dyndpRegisterContents = {.byte = 0x0}; uint8_t txAddress[5] = {0xB3, 0xB3, 0xB3, 0xB3, 0x00}; uint8_t rx1Address[5] = {0xB3, 0xB3, 0xB3, 0xB3, 0x00}; /* Set the frequency to 1450 MHz */ Write_NRF_Register(RF_CH_ADDRESS, 0x32); /* Enable dynamic payload length */ Send_Activate_Command(); featureRegisterContents.bits.EN_DPL = 1; // enable dynamic payload length Write_NRF_Register(FEATURE_ADDRESS, featureRegisterContents.byte); /* set dynamic payload length for all data pipes * When the dynamic payload length is not set the module cannot receive packets from some * stations. This is probably due to counterfeit NRF24L01+ chips. */ dyndpRegisterContents.bits.DPL_P0 = 1; dyndpRegisterContents.bits.DPL_P1 = 1; dyndpRegisterContents.bits.DPL_P2 = 1; dyndpRegisterContents.bits.DPL_P3 = 1; dyndpRegisterContents.bits.DPL_P4 = 1; dyndpRegisterContents.bits.DPL_P5 = 1; Write_NRF_Register(DYNPD_ADDRESS, dyndpRegisterContents.byte); /* Set up the auto retries */ setupRetrRegisterContents.bits.ARC = 0x3; setupRetrRegisterContents.bits.ARD = 0xF; Write_NRF_Register(SETUP_RETR_ADDRESS, setupRetrRegisterContents.byte); /* Set the TX address */ Set_TX_Address(txAddress, MAX_ADDRESS_LENGTH); /* Set the address of the RX pipe 0 to the one of the base station to receive acks */ Set_RX_P0_Address(txAddress, MAX_ADDRESS_LENGTH); /* Set the address of the RX pipe 1 to the own address to receive messages */ rx1Address[4] = moduleId; // The last byte of the address corresponds to the Id set by the pin programming Set_RX_P1_Address(rx1Address, MAX_ADDRESS_LENGTH); /* Enable the rx addresses for pipe 0 and pipe 1*/ enableRxAddressesRegisterContents.bits.ERX_P0 = 1; enableRxAddressesRegisterContents.bits.ERX_P1 = 1; Write_NRF_Register(EN_RXADDR_ADDRESS, enableRxAddressesRegisterContents.byte); /* Set the payload witth for pipe 1 */ rxPwPnRegisterContents.bits.RX_PW_Pn = 32; Write_NRF_Register(RX_PW_P1_ADDRESS, rxPwPnRegisterContents.byte); rxPwPnRegisterContents.bits.RX_PW_Pn = 0; Write_NRF_Register(RX_PW_P0_ADDRESS, rxPwPnRegisterContents.byte); // auto-ack pipe Write_NRF_Register(RX_PW_P2_ADDRESS, rxPwPnRegisterContents.byte); // not used Write_NRF_Register(RX_PW_P3_ADDRESS, rxPwPnRegisterContents.byte); // not used Write_NRF_Register(RX_PW_P4_ADDRESS, rxPwPnRegisterContents.byte); // not used Write_NRF_Register(RX_PW_P5_ADDRESS, rxPwPnRegisterContents.byte); // not used /* Enable auto acknowledge for pipe 1 */ enAaRegister.bits.ENAA_P0 = 1; enAaRegister.bits.ENAA_P1 = 1; enAaRegister.bits.ENAA_P2 = 1; enAaRegister.bits.ENAA_P3 = 1; enAaRegister.bits.ENAA_P4 = 1; enAaRegister.bits.ENAA_P5 = 1; Write_NRF_Register(EN_AA_ADDRESS, enAaRegister.byte); /* Flush FIFOs */ Send_TX_Flush_Command(); Send_RX_Flush_Command(); PCMSK2 |= (1< 32) || (length == 0)) { return success; } PCICR |= (1< 0)) { _delay_ms(1); duration --; }; if (nrfInterruptRaised == true) // check if a message was received { /* A message was received */ statusRegisterContents.byte = Read_NRF_Status_Register(); fifoStatusRegisterContents.byte = Read_NRF_Register(FIFO_STATUS_ADDRESS); if (fifoStatusRegisterContents.bits.RX_EMPTY != 1) { messageReceived = true; } nrfInterruptRaised = false; } // Set the NRF to standby NRF_CE_PORT &= ~(1 << NRF_CE_PIN); configRegisterContents.byte = Read_NRF_Register(CONFIG_ADDRESS); configRegisterContents.bits.PRIM_RX = 0x0; Write_NRF_Register(CONFIG_ADDRESS, configRegisterContents.byte); PCICR &= ~(1<