├── Example ├── nrf24l01_library_receiver.ino ├── nrf24l01_library_transmitter.ino └── nrf24l01_low_level.c ├── README.md ├── nrf24l01.c ├── nrf24l01.h └── nrf24l01_low_level.c /Example/nrf24l01_library_receiver.ino: -------------------------------------------------------------------------------- 1 | /*receiver code example, prints the received payload to the Serial monitor in HEX format*/ 2 | /*static payload length of 1 byte, 1Mbps datarate, -6 dbm rf transmit power, channel 32 of 125 chanels*/ 3 | extern "C"{ 4 | #include "nrf24l01.h" 5 | } 6 | 7 | void setup() 8 | { 9 | Serial.begin(115200); 10 | nrf24_device(RECEIVER, RESET); //initializing nrf24l01+ as a receiver device with one simple function call 11 | } 12 | 13 | void loop() 14 | { 15 | uint8_t received_payload; 16 | while(nrf24_receive(&received_payload, 1) == RECEIVE_FIFO_EMPTY) //poll and receive in one simple function call 17 | ; 18 | Serial.println(received_payload, HEX); 19 | } 20 | -------------------------------------------------------------------------------- /Example/nrf24l01_library_transmitter.ino: -------------------------------------------------------------------------------- 1 | /*transmitter code example, transmits an ascending number every TIME_GAP milliseconds in NO_ACK mode*/ 2 | /*static payload length of 1 byte, 1Mbps datarate, -6 dbm rf transmit power, channel 32 of 125 chanels*/ 3 | extern "C"{ 4 | #include "nrf24l01.h" 5 | } 6 | 7 | #define TIME_GAP 500 8 | 9 | uint8_t ascending_number = 0X00; 10 | 11 | void setup() 12 | { 13 | Serial.begin(115200); 14 | nrf24_device(TRANSMITTER, RESET); //initializing nrf24l01+ as a transmitter using one simple function 15 | } 16 | 17 | void loop() 18 | { 19 | delay(TIME_GAP); 20 | while(nrf24_transmit(&ascending_number, 1, NO_ACK_MODE) == TRANSMIT_FAIL) //wait until payload is loaded into TX buffer 21 | { 22 | Serial.println("Transmit fail!"); 23 | } 24 | while(nrf24_transmit_status() == TRANSMIT_IN_PROGRESS) //poll the transmit status, make sure the payload is sent 25 | ; 26 | Serial.println("Sent!"); //payload is sent without acknowledge successfully 27 | ascending_number++; 28 | } 29 | -------------------------------------------------------------------------------- /Example/nrf24l01_low_level.c: -------------------------------------------------------------------------------- 1 | /*low level api example for avr/arduino*/ 2 | #include "nrf24l01.h" 3 | #include 4 | 5 | /*macros for SPI, CE and CSN pin configuration, change pins # according to mcu*/ 6 | #define MOSI_PIN 11 7 | #define MISO_PIN 12 8 | #define SCK_PIN 13 9 | #define SS_PIN 10 10 | #define NRF24_CSN 9 /*to enable SPI on nrf24, active LOW*/ 11 | #define NRF24_CE 8 /*active HIGH, activate chip in RX or TX mode*/ 12 | 13 | /*start of low level functions, specific to the mcu and compiler*/ 14 | 15 | /*delay in miliseconds*/ 16 | void delay_function(uint32_t duration_ms) 17 | { 18 | delay(duration_ms); 19 | } 20 | 21 | /*contains all SPI configuations, such as pins and control registers*/ 22 | /*SPI control: master, interrupts disabled, clock polarity low when idle, clock phase falling edge, clock up tp 1 MHz*/ 23 | void SPI_Initializer() 24 | { 25 | pinMode(MOSI_PIN, OUTPUT); 26 | pinMode(MISO_PIN, INPUT); 27 | pinMode(SCK_PIN, OUTPUT); 28 | pinMode(SS_PIN, OUTPUT); 29 | 30 | SPCR = 0X51; /*master, interrupt disabled, spi enabled, clock polarity low when idle, clock phase falling edge, 1 MHz clock*/ 31 | } 32 | 33 | /*contains all CSN and CE pins gpio configurations, including setting them as gpio outputs and turning SPI off and CE '1'*/ 34 | void pinout_Initializer() 35 | { 36 | pinMode(NRF24_CSN, OUTPUT); 37 | pinMode(NRF24_CE, OUTPUT); 38 | 39 | digitalWrite(NRF24_CSN, SPI_OFF); /*nrf24l01 is not accepting commands*/ 40 | nrf24_CE(HIGH); /*no need to change this line*/ 41 | } 42 | 43 | /*CSN pin manipulation to high or low (SPI on or off)*/ 44 | void nrf24_SPI(uint8_t input) 45 | { 46 | if (input == SPI_ON) 47 | digitalWrite(NRF24_CSN, LOW); 48 | else 49 | digitalWrite(NRF24_CSN, HIGH); 50 | } 51 | 52 | /*1 byte SPI shift register send and receive routine*/ 53 | uint8_t SPI_send_command(uint8_t command) 54 | { 55 | SPDR = command; 56 | while ((SPSR & (1 << SPIF)) == 0) {} 57 | return SPDR; 58 | } 59 | 60 | /*CE pin maniplation to high or low*/ 61 | void nrf24_CE(uint8_t input) 62 | { 63 | if (input == CE_ON) 64 | digitalWrite(NRF24_CE, HIGH); 65 | else 66 | digitalWrite(NRF24_CE, LOW); 67 | } 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # nRF24L01+ C LIBRARY 2 | * version 1.0 3 | * Reza Ebrahimi 4 | 5 | This library is written in **portable C**, and is **MCU independent**. It consumes a small amount of RAM (under 50 bytes) and program memory (under 2 KB). In order to implement it to your MCU of choice, you need to manipulate functions inside nrf24l01_low_level.c file (SPI, pin configurations) and leave other files as they are. 6 | 7 | nRF24L01+ C library abstracts away the internals of the hardware, using LEVEL 4 functions (description below). 8 | 9 | This library is written based on the nRF24L01+ Preliminary Product Specification released by Nordic Semiconductor and is not influenced by other (probably numorous) libraries out there. Any resemblance to pre-existing code is unintentional. 10 | 11 | You can use this library in any way, shape or form. I'd be very happy if you mention my name though. 12 | 13 | ## HOW TO USE 14 | 15 | As mentioned earlier, first you need to implement low level settings like SPI, delay function and pin configurations inside nrf24l01_low_level.c file (LEVEL 1). 16 | 17 | Start by calling nrf24_device(uint8_t device_mode, uint8_t reset_state) function. You can set the device mode to either TRANSMITTER, RECEIVER, POWER_SAVING or TURN_OFF and reset_state to RESET or NO_RESET. if this is the first time nrf24_device is called, nrf24l01+ is reset regardless of reset_state. nrf24_device initializes the low level API like SPI etc, and sets nrf24l01+ with default values and settings. These settings and values can be changed with manipulating macros inside nrf24l01.h, or by calling LEVEL 3 functions. the next steps depend on the chosen device_mode. 18 | 19 | For TRANSMITTER: 20 | Use nrf24_transmit(uint8_t *payload, uint8_t payload_width, uint8_t acknowledgement_state) to send an array of 1 byte blocks, with the specified payload_width and acknowledgement_state (could be ACK_MODE or NO_ACK_MODE). If nrf24l01+ is set to static payload width, payload_width is ignored. nrf24_transmit has 2 different outputs: TRANSMIT_BEGIN and TRANSMIT_FAIL (in case of wrong mode of operation or full TX FIFO buffer). Next, you can use nrf24_transmit_status() which has no input, but gives back status: TRANSMIT_IN_PROGRESS if the payload is still not sent or if TX buffer is empty, TRANSMIT_DONE if the payload is sent successfully, TRANSMIT_FAILED if the payload has reached he maximum number of retransmits (only in ACK_MODE). 21 | 22 | For RECEIVER: 23 | nrf24_receive(uint8_t *payload, uint8_t payload_width) can be used to both poll the RX buffer, and receive the payload if its already inside the buffer. payload_width is ignored if nrf24l01+ was set to static payload width mode. nrf24_receive outputs the polling results as: OPERATION_ERROR if not in RECEIVER mode, RECEIVE_FIFO_EMPTY in case of empty buffer (payload array is not updated) and OPERATION_DONE if the received data is saved inside payload array. 24 | 25 | For POWER_SAVING or TURN_OFF: 26 | You cannot send or receive any data in these modes of operation, these are used only to reduce power consumption. device_mode can be changed mid code. 27 | 28 | General considerations: 29 | the default value for transmit radio power is set to -6 dbm. 30 | the default value for radio channel is set to channel 32. 31 | the default payload width is 1 byte and its static. 32 | the default value for datarate is 1Mbps. 33 | 34 | ## HOW IT WORKS 35 | 36 | Functions can be categorized into different levels: from low level APIs up to higher ones. 37 | Lower level APIs are used by higher level APIs. Use LEVEL 4 functions (or sometimes LEVEL 3, 38 | if you want to change settings) in your firmware. 39 | 40 | LEVEL 1: 41 | * void delay_function(uint32_t duration_ms) 42 | * void SPI_Initializer() 43 | * void pinout_Initializer() 44 | * void nrf24_SPI(uint8_t input) 45 | * uint8_t SPI_send_command(uint8_t command) 46 | * void nrf24_CE(uint8_t input) 47 | 48 | LEVEL 2: 49 | * void nrf24_write(uint8_t address, uint8_t *value, uint8_t data_length, uint8_t spi_state) 50 | * void nrf24_read(uint8_t address, uint8_t *value, uint8_t data_length, uint8_t spi_state) 51 | * void nrf24_send_payload(uint8_t *payload, uint8_t payload_width) 52 | 53 | LEVEL 3: 54 | * void nrf24_mode(uint8_t mode) 55 | * void nrf24_crc_configuration(uint8_t crc_enable, uint8_t crc_encoding_scheme) 56 | * void nrf24_interrupt_mask(uint8_t rx_mask, uint8_t tx_mask, uint8_t max_rt_mask) 57 | * void nrf24_rf_channel(uint8_t rf_channel) 58 | * void nrf24_rf_power(uint8_t rf_power) 59 | * void nrf24_rf_datarate(uint8_t rf_datarate) 60 | * void nrf24_address_width(uint8_t address_width) 61 | * void nrf24_datapipe_enable(uint8_t number_of_datapipes) 62 | * void nrf24_prx_static_payload_width(uint8_t static_payload_width, uint8_t number_of_datapipes) 63 | * void nrf24_datapipe_address_configuration() 64 | * void nrf24_datapipe_ptx(uint8_t datapipe_number) 65 | * void nrf24_dynamic_payload(uint8_t state, uint8_t datapipe) 66 | * void nrf24_auto_acknowledgment_setup(uint8_t datapipe) 67 | * void nrf24_automatic_retransmit_setup(uint16_t delay_time, uint8_t retransmit_count) 68 | * void nrf24_dynamic_ack(uint8_t state) 69 | 70 | LEVEL 4: 71 | * void nrf24_device(uint8_t device_mode, uint8_t reset_state) 72 | * void nrf24_reset() 73 | * uint8_t nrf24_flush(uint8_t fifo_select) 74 | * uint8_t nrf24_receive(uint8_t *payload, uint8_t payload_width) 75 | * uint8_t nrf24_transmit_status() 76 | * uint8_t nrf24_transmit(uint8_t *payload, uint8_t payload_width, uint8_t acknowledgement_state) 77 | 78 | ## EXAMPLE 79 | 80 | As an example, a simple byte transmitter for arduino/atmega boards is provided. 81 | -------------------------------------------------------------------------------- /nrf24l01.c: -------------------------------------------------------------------------------- 1 | #include "nrf24l01.h" 2 | 3 | /*global variables related to this file*/ 4 | static uint8_t SPI_command; /*1 byte spi command*/ 5 | static uint8_t register_current_value; /*in order to change some bits of internal registers or to check their content*/ 6 | static uint8_t register_new_value; /*used to write new value to nrf24l01+ registers*/ 7 | static uint8_t write_pointer; /*used as an input for read and write functions (as a pointer)*/ 8 | static uint8_t current_address_width; /*current address width for receiver pipe addresses (up to 6 pipes), from 3 to 5 bytes*/ 9 | static uint8_t reset_flag = 0; /*reset flag lets the software know if the nrf24l01+ has ever been reset or not*/ 10 | static uint8_t current_mode = DEVICE_NOT_INITIALIZED; /*current mode of operation: DEVICE_NOT_INITIALIZED, PRX, PTX, STANDBYI, STANDBYII, POWER_DOWN*/ 11 | static uint8_t current_payload_width; /*payload width could be from 1 to 32 bytes, in either dynamic or static forms*/ 12 | static uint8_t current_acknowledgement_state = NO_ACK_MODE; 13 | static uint8_t dynamic_payload = DISABLE; 14 | 15 | /*2 dimensional array of pipe addresses (5 byte address width) by default. you can change addresses using a new array later. 16 | Pipe 1 address could be anything. pipe 3 to 6 addresses share the first 4 bytes with pipe 2 and only differ in byte 5*/ 17 | uint8_t datapipe_address[MAXIMUM_NUMBER_OF_DATAPIPES][ADDRESS_WIDTH_DEFAULT] = { 18 | {0X20, 0XC3, 0XC2, 0XC1, 0XA0}, 19 | {0X20, 0XC3, 0XC2, 0XC1, 0XA1}, 20 | {0X20, 0XC3, 0XC2, 0XC1, 0XA2}, 21 | {0X20, 0XC3, 0XC2, 0XC1, 0XA3}, 22 | {0X20, 0XC3, 0XC2, 0XC1, 0XA4}, 23 | {0X20, 0XC3, 0XC2, 0XC1, 0XA5} 24 | }; 25 | 26 | /*function to enable or disable dynamic acknowledge. if enabled, you can disable acknowledge 27 | on a specific payload with W_TX_PAYLOAD_NOACK or enable acknowledge using W_TX_PAYLOAD commands. 28 | if disabled, you cannot disable acknowledging a payload. manipulates EN_DYN_ACK inside FEATURE*/ 29 | void nrf24_dynamic_ack(uint8_t state) 30 | { 31 | if (state == ENABLE) 32 | { 33 | nrf24_read(FEATURE_ADDRESS, ®ister_current_value, 1, CLOSE); 34 | register_new_value = register_current_value | (1 << EN_DYN_ACK); 35 | nrf24_write(FEATURE_ADDRESS, ®ister_new_value, 1, CLOSE); 36 | } 37 | else 38 | { 39 | nrf24_read(FEATURE_ADDRESS, ®ister_current_value, 1, CLOSE); 40 | register_new_value = register_current_value & (~(1 << EN_DYN_ACK)); 41 | nrf24_write(FEATURE_ADDRESS, ®ister_new_value, 1, CLOSE); 42 | } 43 | } 44 | 45 | /*function for PTX device to transmit 1 to 32 bytes of data, used for both dynamic payload length 46 | and static payload length methods. acknowledgemet state could be NO_ACK_MODE or ACK_MODE*/ 47 | uint8_t nrf24_transmit(uint8_t *payload, uint8_t payload_width, uint8_t acknowledgement_state) 48 | { 49 | nrf24_read(STATUS_ADDRESS, ®ister_current_value, 1, CLOSE); /*in order to check TX_FIFO status*/ 50 | if ((!(register_current_value & (1 << TX_FULL))) && (current_mode == PTX)) 51 | { 52 | current_acknowledgement_state = acknowledgement_state; /*setting the acknowledgement state to either NO_ACK or ACK, based on input*/ 53 | if (dynamic_payload == ENABLE) 54 | payload_width = current_payload_width; 55 | nrf24_send_payload(payload, payload_width); /*the actual function to send data*/ 56 | return (TRANSMIT_BEGIN); /*TX FIFO is not full and nrf24l01+ mode is standby ii or ptx*/ 57 | } 58 | else 59 | { 60 | return (TRANSMIT_FAIL); /*TX FIFO full or wrong mode*/ 61 | } 62 | } 63 | 64 | /*used by nrf24_transmit function to send the actual data*/ 65 | void nrf24_send_payload(uint8_t *payload, uint8_t payload_width) 66 | { 67 | nrf24_SPI(SPI_ON); 68 | if (current_acknowledgement_state == NO_ACK_MODE) 69 | SPI_command = W_TX_PAYLOAD_NOACK; 70 | else 71 | SPI_command = W_TX_PAYLOAD; 72 | SPI_send_command(SPI_command); 73 | for (; payload_width; payload_width--) 74 | { 75 | SPI_command = *payload; 76 | SPI_send_command(SPI_command); 77 | payload++; 78 | } 79 | nrf24_SPI(SPI_OFF); 80 | } 81 | 82 | /*reports back transmit status: TRANSMIT_DONE, TRANSMIT_FAILED (in case of reaching maximum number of retransmits in auto acknowledgement mode) 83 | and TRANSMIT_IN_PROGRESS, if neither flags are set. automatically resets the '1' flags.*/ 84 | uint8_t nrf24_transmit_status() 85 | { 86 | nrf24_read(STATUS_ADDRESS, ®ister_current_value, 1, CLOSE); /*status register is read to check TX_DS flag*/ 87 | if (register_current_value & (1 << TX_DS)) /*if the TX_DS == 1, */ 88 | { 89 | nrf24_write(STATUS_ADDRESS, ®ister_current_value, 1, CLOSE); /*reseting the TX_DS flag. as mentioned by datasheet, writing '1' to a flag resets that flag*/ 90 | return TRANSMIT_DONE; 91 | } 92 | else if (register_current_value & (1 << MAX_RT)) 93 | { 94 | nrf24_write(STATUS_ADDRESS, ®ister_current_value, 1, CLOSE); /*reseting the MAX_RT flag. as mentioned by datasheet, writing '1' to a flag resets that flag*/ 95 | return TRANSMIT_FAILED; 96 | } 97 | else 98 | return TRANSMIT_IN_PROGRESS; 99 | } 100 | 101 | /*the receive function output is used as a polling method to check the received data inside RX FIFOs. 102 | If there is any data available, it will be loaded inside payload array*/ 103 | uint8_t nrf24_receive(uint8_t *payload, uint8_t payload_width) 104 | { 105 | if (current_mode == PRX) 106 | { 107 | nrf24_read(STATUS_ADDRESS, ®ister_current_value, 1, CLOSE); 108 | if (register_current_value & (1 << RX_DR)) /*if received data is ready inside RX FIFO*/ 109 | { 110 | if(dynamic_payload == DISABLE) /*if dynamic payload width is disabled, use the static payload width and ignore the input*/ 111 | payload_width = current_payload_width; 112 | 113 | nrf24_SPI(SPI_ON); /*sending the read payload command to nrf24l01+*/ 114 | SPI_command = R_RX_PAYLOAD; 115 | SPI_send_command(SPI_command); 116 | 117 | for (; payload_width; payload_width--) 118 | { 119 | SPI_command = NOP_CMD; 120 | *payload = SPI_send_command(SPI_command); 121 | payload++; 122 | } 123 | nrf24_SPI(SPI_OFF); 124 | nrf24_read(FIFO_STATUS_ADDRESS, ®ister_current_value, 1, CLOSE); /*in order to check the RX_EMPTY flag*/ 125 | if(register_current_value & (1 << RX_EMPTY)) /*if the RX FIFO is empty, reset the RX_DR flag inside STATUS register*/ 126 | { 127 | nrf24_read(STATUS_ADDRESS, ®ister_current_value, 1, CLOSE); 128 | register_new_value = register_current_value | (1 << RX_DR); 129 | nrf24_write(STATUS_ADDRESS, ®ister_new_value, 1, CLOSE); 130 | } 131 | return OPERATION_DONE; 132 | } 133 | else 134 | { 135 | return RECEIVE_FIFO_EMPTY; 136 | } 137 | } 138 | else 139 | return OPERATION_ERROR; 140 | } 141 | 142 | /*function which uses TX_FLUSH or RX_FLUSH command to flush the fifo buffers. if successful, output is OPERATION_DONE. 143 | if not successful (wrong input or wrong mode of operation) output will be OPERATION_ERROR*/ 144 | uint8_t nrf24_flush(uint8_t fifo_select) 145 | { 146 | switch (fifo_select) 147 | { 148 | case TX_BUFFER: 149 | if (current_mode == PTX) 150 | { 151 | nrf24_SPI(SPI_ON); 152 | SPI_command = FLUSH_TX; 153 | SPI_send_command(SPI_command); 154 | nrf24_SPI(SPI_OFF); 155 | return OPERATION_DONE; 156 | } 157 | else 158 | return OPERATION_ERROR; 159 | case RX_BUFFER: 160 | if (current_mode == PRX) 161 | { 162 | nrf24_SPI(SPI_ON); 163 | SPI_command = FLUSH_RX; 164 | SPI_send_command(SPI_command); 165 | nrf24_SPI(SPI_OFF); 166 | return OPERATION_DONE; 167 | } 168 | else 169 | return OPERATION_ERROR; 170 | default: 171 | return OPERATION_ERROR; 172 | } 173 | } 174 | 175 | /*must be called atleast once, which happens with calling nrf24_device function*/ 176 | void nrf24_reset() 177 | { 178 | reset_flag = 1; 179 | nrf24_CE(CE_OFF); 180 | register_new_value = CONFIG_REGISTER_DEFAULT; 181 | nrf24_write(CONFIG_ADDRESS, ®ister_new_value, 1, CLOSE); 182 | register_new_value = EN_AA_REGISTER_DEFAULT; 183 | nrf24_write(EN_AA_ADDRESS, ®ister_new_value, 1, CLOSE); 184 | register_new_value = EN_RXADDR_REGISTER_DEFAULT; 185 | nrf24_write(EN_RXADDR_ADDRESS, ®ister_new_value, 1, CLOSE); 186 | register_new_value = SETUP_AW_REGISTER_DEFAULT; 187 | nrf24_write(SETUP_AW_ADDRESS, ®ister_new_value, 1, CLOSE); 188 | register_new_value = RF_CH_REGISTER_DEFAULT; 189 | nrf24_write(RF_CH_ADDRESS, ®ister_new_value, 1, CLOSE); 190 | register_new_value = RF_SETUP_REGISTER_DEFAULT; 191 | nrf24_write(RF_SETUP_ADDRESS, ®ister_new_value, 1, CLOSE); 192 | register_new_value = STATUS_REGISTER_DEFAULT; 193 | nrf24_write(STATUS_ADDRESS, ®ister_new_value, 1, CLOSE); 194 | 195 | nrf24_mode(PTX); 196 | nrf24_flush(TX_BUFFER); 197 | nrf24_mode(PRX); 198 | nrf24_flush(RX_BUFFER); 199 | 200 | nrf24_read(STATUS_ADDRESS, ®ister_current_value, 1, CLOSE); 201 | register_new_value = register_current_value | (1 << RX_DR) | (1 << TX_DS) | (1 << MAX_RT); 202 | nrf24_write(STATUS_ADDRESS, ®ister_new_value, 1, CLOSE); 203 | 204 | nrf24_interrupt_mask(ENABLE, ENABLE, ENABLE); 205 | nrf24_crc_configuration(ENABLE, 1); 206 | nrf24_address_width(ADDRESS_WIDTH_DEFAULT); 207 | nrf24_rf_datarate(RF_DATARATE_DEFAULT); 208 | nrf24_rf_power(RF_PWR_DEFAULT); 209 | nrf24_rf_channel(RF_CHANNEL_DEFAULT); 210 | nrf24_datapipe_enable(NUMBER_OF_DP_DEFAULT); 211 | /*nrf24_datapipe_address_configuration();*/ 212 | /*nrf24_datapipe_ptx(1);*/ 213 | nrf24_prx_static_payload_width(STATIC_PAYLOAD_WIDTH_DEFAULT, NUMBER_OF_DP_DEFAULT); 214 | nrf24_automatic_retransmit_setup(RETRANSMIT_DELAY_DEFAULT, RETRANSMIT_COUNT_DEFAULT); 215 | nrf24_auto_acknowledgment_setup(NUMBER_OF_DP_DEFAULT); 216 | nrf24_dynamic_payload(DISABLE, NUMBER_OF_DP_DEFAULT); 217 | nrf24_dynamic_ack(ENABLE); 218 | } 219 | 220 | /*used by firmware to set the nrf24 mode in TRANSMITTER, RECEIVER, POWER_SAVING or TURN_OFF states, and reseting the device 221 | if it has not been done yet. This is the initializer, and everything starts by calling nrf24_device first.It has a higher 222 | level of abstraction than nrf24_mode and must be used by user*/ 223 | void nrf24_device(uint8_t device_mode, uint8_t reset_state) 224 | { 225 | SPI_Initializer(); 226 | pinout_Initializer(); 227 | delay_function(STARTUP_DELAY); 228 | 229 | if ((reset_state == RESET) || (reset_flag == 0)) 230 | { 231 | nrf24_reset(); 232 | } 233 | 234 | switch (device_mode) 235 | { 236 | case TRANSMITTER: 237 | nrf24_mode(POWER_DOWN); 238 | nrf24_interrupt_mask(ENABLE, DISABLE, DISABLE); /*disabling tx interrupt mask*/ 239 | nrf24_mode(PTX); 240 | break; 241 | case RECEIVER: 242 | nrf24_mode(POWER_DOWN); 243 | nrf24_interrupt_mask(DISABLE, ENABLE, ENABLE); /*disabling rx interrupt mask*/ 244 | nrf24_mode(PRX); 245 | delay_function(PRX_MODE_DELAY); /*100ms for PRX mode*/ 246 | break; 247 | case POWER_SAVING: 248 | nrf24_mode(POWER_DOWN); 249 | nrf24_interrupt_mask(ENABLE, ENABLE, ENABLE); 250 | nrf24_mode(STANDBYI); 251 | break; 252 | case TURN_OFF: 253 | nrf24_mode(POWER_DOWN); 254 | nrf24_interrupt_mask(ENABLE, ENABLE, ENABLE); 255 | break; 256 | default: 257 | nrf24_mode(POWER_DOWN); 258 | nrf24_interrupt_mask(ENABLE, ENABLE, ENABLE); 259 | break; 260 | } 261 | } 262 | 263 | /*setting automatic retransmit delay time and maximum number of retransmits*/ 264 | void nrf24_automatic_retransmit_setup(uint16_t delay_time, uint8_t retransmit_count) 265 | { 266 | register_new_value = 0x00; 267 | for (; (delay_time > 250) && (register_new_value < 0X0F); delay_time -= 250) 268 | register_new_value++; 269 | register_new_value <<= ARD_0; 270 | if ((retransmit_count > 0) && (retransmit_count < 16)) 271 | register_new_value |= retransmit_count; 272 | else 273 | register_new_value |= 0; 274 | nrf24_write(SETUP_RETR_ADDRESS, ®ister_new_value, 1, CLOSE); 275 | } 276 | 277 | /*setting auto acknoledgement on datapipes*/ 278 | void nrf24_auto_acknowledgment_setup(uint8_t datapipe) 279 | { 280 | if (datapipe < 7) 281 | register_new_value = (1 << datapipe) - 1; 282 | nrf24_write(EN_AA_ADDRESS, ®ister_new_value, 1, CLOSE); 283 | } 284 | 285 | /*turns on or off the dynamic payload width capability*/ 286 | void nrf24_dynamic_payload(uint8_t state, uint8_t datapipe) 287 | { 288 | nrf24_auto_acknowledgment_setup(datapipe); /*setting auto acknowledgment before setting dynamic payload*/ 289 | nrf24_read(FEATURE_ADDRESS, ®ister_current_value, 1, CLOSE); 290 | if (state == ENABLE) 291 | { 292 | register_new_value = register_current_value | (1 << EN_DPL); /*EN_DPL bit turns dynamic payload width on or off on all datapipes*/ 293 | nrf24_write(FEATURE_ADDRESS, ®ister_new_value, 1, CLOSE); 294 | if (datapipe < 7) 295 | register_new_value = (1 << datapipe) - 1; /*turning on dynamic payload width on chosen datapipes, using DYNPD register*/ 296 | nrf24_write(DYNPD_ADDRESS, ®ister_new_value, 1, CLOSE); 297 | dynamic_payload = ENABLE; 298 | } 299 | else 300 | { 301 | register_new_value = register_current_value & (~(1 << EN_DPL)); 302 | nrf24_write(FEATURE_ADDRESS, ®ister_new_value, 1, CLOSE); 303 | dynamic_payload = DISABLE; 304 | } 305 | } 306 | 307 | /*on nrf24l01+ there is only one address for PTX device which must be the same as PRX data pipe address 0*/ 308 | void nrf24_datapipe_ptx(uint8_t datapipe_number) 309 | { 310 | nrf24_write(TX_ADDR_ADDRESS, &datapipe_address[datapipe_number - 1][0], current_address_width, CLOSE); 311 | } 312 | 313 | /*setting the 6 datapipe addresses using the datapipe_address[][]*/ 314 | void nrf24_datapipe_address_configuration() 315 | { 316 | uint8_t address = RX_ADDR_P0_ADDRESS; 317 | for (uint8_t counter = 0; counter < 6; counter++) 318 | { 319 | nrf24_write(address, &datapipe_address[counter][0], current_address_width, CLOSE); 320 | address++; 321 | } 322 | } 323 | 324 | /*function to change static payload width, from 1 to 32 bytes in each payload*/ 325 | void nrf24_prx_static_payload_width(uint8_t static_payload_width, uint8_t number_of_datapipes) 326 | { 327 | for (uint8_t address = RX_PW_P0_ADDRESS; number_of_datapipes; number_of_datapipes--) 328 | { 329 | nrf24_write(address, &static_payload_width, 1, CLOSE); 330 | address++; 331 | } 332 | current_payload_width = static_payload_width; 333 | } 334 | 335 | /*datapipes are turned on and off using EN_RXADDR register, PRX datapipe addresses are located in RX_ADDR_Pn, TX address is located inside TX_ADDR*/ 336 | void nrf24_datapipe_enable(uint8_t number_of_datapipes) 337 | { 338 | register_new_value = (1 << number_of_datapipes) - 1; 339 | nrf24_write(EN_RXADDR_ADDRESS, ®ister_new_value, 1, CLOSE); 340 | } 341 | 342 | /*function to set the nrf24l01+ address width, from 3 to 5 bytes*/ 343 | void nrf24_address_width(uint8_t address_width) 344 | { 345 | if ((address_width <= 5) && (address_width >= 3)) 346 | { 347 | write_pointer = address_width - 2; 348 | } 349 | else 350 | { 351 | write_pointer = 3; 352 | } 353 | nrf24_write(SETUP_AW_ADDRESS, &write_pointer, 1, CLOSE); /*5 bytes is the maximum address width available*/ 354 | current_address_width = address_width; 355 | } 356 | 357 | /*datarate settings, you can choose between 2mbps, 1mbps, 250kbps*/ 358 | void nrf24_rf_datarate(uint8_t rf_datarate) 359 | { 360 | nrf24_read(RF_SETUP_ADDRESS, ®ister_current_value, 1, CLOSE); 361 | register_current_value &= ~((1 << RF_DR_LOW) | (1 << RF_DR_HIGH)); 362 | switch (rf_datarate) 363 | { 364 | case 2000: 365 | register_new_value = register_current_value | (1 << RF_DR_HIGH); 366 | break; 367 | case 1000: 368 | register_new_value = register_current_value; 369 | break; 370 | case 250: 371 | register_new_value = register_current_value | (1 << RF_DR_LOW); 372 | break; 373 | default: 374 | register_new_value = register_current_value; 375 | break; 376 | } 377 | nrf24_write(RF_SETUP_ADDRESS, ®ister_new_value, 1, CLOSE); 378 | } 379 | 380 | /*nrf24l01+ RF power settings. 0dbm, -6dbm, -12dbm, -18dbm*/ 381 | void nrf24_rf_power(uint8_t rf_power) 382 | { 383 | nrf24_read(RF_SETUP_ADDRESS, ®ister_current_value, 1, CLOSE); 384 | register_current_value &= ~((1 << RF_PWR_1) | (1 << RF_PWR_0)); 385 | switch (rf_power) 386 | { 387 | case 0: 388 | register_new_value = register_current_value | ((1 << RF_PWR_1) | (1 << RF_PWR_0)); 389 | break; 390 | case 6: 391 | register_new_value = register_current_value | (1 << RF_PWR_1); 392 | break; 393 | case 12: 394 | register_new_value = register_current_value | (1 << RF_PWR_0); 395 | break; 396 | case 18: 397 | register_new_value = register_current_value; 398 | break; 399 | default: 400 | register_new_value = register_current_value | (1 << RF_PWR_1); 401 | break; 402 | } 403 | nrf24_write(RF_SETUP_ADDRESS, ®ister_new_value, 1, CLOSE); 404 | } 405 | 406 | /*nrf24l01+ RF channel selection, from 1 to 125*/ 407 | void nrf24_rf_channel(uint8_t rf_channel) 408 | { 409 | if ((rf_channel <= 125) && (rf_channel >= 1)) 410 | { 411 | uint8_t write_pointer = rf_channel; 412 | nrf24_write(RF_CH_ADDRESS, &write_pointer, 1, CLOSE); 413 | } 414 | else 415 | { 416 | uint8_t write_pointer = 1; 417 | nrf24_write(RF_CH_ADDRESS, &write_pointer, 1, CLOSE); 418 | } 419 | } 420 | 421 | /*interrupt mask settings. 3 seperate masks for RX, TX, and RT (maximum numbers of retransmission reached*/ 422 | void nrf24_interrupt_mask(uint8_t rx_mask, uint8_t tx_mask, uint8_t max_rt_mask) 423 | { 424 | nrf24_read(CONFIG_ADDRESS, ®ister_current_value, 1, CLOSE); 425 | if (rx_mask) 426 | register_new_value = (register_current_value) | (1 << MASK_RX_DR); 427 | else 428 | register_new_value &= (~(1 << MASK_RX_DR)); 429 | if (tx_mask) 430 | register_new_value |= (1 << MASK_TX_DS); 431 | else 432 | register_new_value &= (~(1 << MASK_TX_DS)); 433 | if (max_rt_mask) 434 | register_new_value |= (1 << MASK_MAX_RT); 435 | else 436 | register_new_value &= (~(1 << MASK_MAX_RT)); 437 | 438 | nrf24_write(CONFIG_ADDRESS, ®ister_new_value, 1, CLOSE); 439 | } 440 | 441 | /*enabling or disabling crc in payload; setting crc encoding scheme between 1 or 2 bytes*/ 442 | void nrf24_crc_configuration(uint8_t crc_enable, uint8_t crc_encoding_scheme) 443 | { 444 | nrf24_read(CONFIG_ADDRESS, ®ister_current_value, 1, CLOSE); 445 | if (crc_enable) 446 | register_new_value = (register_current_value) | (1 << EN_CRC); 447 | else 448 | register_new_value &= (~(1 << EN_CRC)); 449 | if (crc_encoding_scheme == 2) 450 | register_new_value |= (1 << CRCO); 451 | else 452 | register_new_value &= (~(1 << CRCO)); 453 | 454 | nrf24_write(CONFIG_ADDRESS, ®ister_new_value, 1, CLOSE); 455 | } 456 | 457 | /*mode selector: power down, standby i, standby ii, ptx, prx. used by nrf24_device function*/ 458 | void nrf24_mode(uint8_t mode) 459 | { 460 | nrf24_read(CONFIG_ADDRESS, ®ister_current_value, 1, CLOSE); 461 | switch (mode) 462 | { 463 | case POWER_DOWN: 464 | nrf24_CE(CE_OFF); 465 | register_new_value = (register_current_value) & (~(1 << PWR_UP)); 466 | delay_function(POWER_DOWN_DELAY); 467 | break; 468 | case STANDBYI: /*standby I is defined by 'PWR_UP = 1' and 'CE pin LOW'*/ 469 | nrf24_CE(CE_OFF); 470 | register_new_value = (register_current_value) | (1 << PWR_UP); 471 | delay_function(STANDBYI_DELAY); 472 | break; 473 | case STANDBYII: /*standby ii is related to a ptx device*/ 474 | nrf24_CE(CE_ON); 475 | register_new_value = ((register_current_value) | (1 << PWR_UP)) & (~(1 << PRIM_RX)); 476 | delay_function(STANDBYI_DELAY); 477 | break; 478 | case PTX: 479 | nrf24_CE(CE_ON); 480 | register_new_value = ((register_current_value) | (1 << PWR_UP)) & (~(1 << PRIM_RX)); 481 | delay_function(STANDBYI_DELAY); 482 | break; 483 | case PRX: 484 | nrf24_CE(CE_ON); 485 | register_new_value = (register_current_value) | (1 << PWR_UP) | (1 << PRIM_RX); 486 | delay_function(STANDBYI_DELAY); 487 | break; 488 | default: 489 | nrf24_CE(CE_OFF); 490 | register_new_value = (register_current_value) & (~(1 << PWR_UP)); 491 | delay_function(POWER_DOWN_DELAY); 492 | break; 493 | } 494 | nrf24_write(CONFIG_ADDRESS, ®ister_new_value, 1, CLOSE); 495 | current_mode = mode; 496 | } 497 | 498 | /*reads the number of bytes (data_length) from the register in nrf24l01+ (address) and stores them inside an array (value), 499 | then closes the spi connection (spi_state = CLOSE) or leaves it open (spi_state = OPEN)*/ 500 | void nrf24_read(uint8_t address, uint8_t *value, uint8_t data_length, uint8_t spi_state) 501 | { 502 | nrf24_SPI(SPI_ON); 503 | SPI_command = R_REGISTER | address; /*in order to read CONFIG, then change one bit*/ 504 | SPI_send_command(SPI_command); 505 | SPI_command = NOP_CMD; 506 | for (; data_length ; data_length--) 507 | { 508 | *value = SPI_send_command(SPI_command); 509 | value++; 510 | } 511 | if (spi_state == CLOSE) 512 | nrf24_SPI(SPI_OFF); 513 | } 514 | 515 | /*writes the number of bytes (data_length) from an array (value) inside registers in nrf24l01+ (address), 516 | then closes the spi connection (spi_state = CLOSE) or leaves it open (spi_state = OPEN)*/ 517 | void nrf24_write(uint8_t address, uint8_t *value, uint8_t data_length, uint8_t spi_state) 518 | { 519 | nrf24_SPI(SPI_ON); 520 | SPI_command = W_REGISTER | address; /*in order to read CONFIG, then change one bit*/ 521 | SPI_send_command(SPI_command); 522 | for (; data_length ; data_length--) 523 | { 524 | SPI_command = *value; 525 | value++; 526 | SPI_send_command(SPI_command); 527 | } 528 | if (spi_state == CLOSE) 529 | nrf24_SPI(SPI_OFF); 530 | } 531 | -------------------------------------------------------------------------------- /nrf24l01.h: -------------------------------------------------------------------------------- 1 | #ifndef NRF24L01_H 2 | #define NRF24L01_H 3 | /*nrf24l01: MSbit to LSbit, LSbyte to MSbyte*/ 4 | #include 5 | #include 6 | 7 | #define STARTUP_DELAY 150 /*in milliseconds*/ 8 | #define POWER_DOWN_DELAY 2 9 | #define STANDBYI_DELAY 2 10 | #define PRX_MODE_DELAY 100 11 | #define ADDRESS_WIDTH_DEFAULT 5 /*address width in bytes, for default value*/ 12 | #define RF_CHANNEL_DEFAULT 32 13 | #define RF_DATARATE_DEFAULT 1000 /*250, 1000, 2000*/ 14 | #define RF_PWR_DEFAULT 6 /*0, -6, -12, -18*/ 15 | #define STATIC_PAYLOAD_WIDTH_DEFAULT 1 /*for static payload mode, configurable between 1 and 32 bytes for PRX device ONLY (RX_PW_Pn, n for data pipe n)(no register for payload length in PTX device)*/ 16 | #define NUMBER_OF_DP_DEFAULT 1 /*number of datapipes, 1 to 6*/ 17 | #define RETRANSMIT_DELAY_DEFAULT 500 18 | #define RETRANSMIT_COUNT_DEFAULT 2 19 | 20 | #define OPEN 1 21 | #define CLOSE 0 22 | #define ENABLE 1 23 | #define DISABLE 0 24 | #define SPI_OFF 1 25 | #define SPI_ON 0 26 | #define CE_OFF 0 27 | #define CE_ON 1 28 | 29 | #define CONFIG_REGISTER_DEFAULT 0X08 30 | #define EN_AA_REGISTER_DEFAULT 0X3F 31 | #define EN_RXADDR_REGISTER_DEFAULT 0X00 32 | #define SETUP_AW_REGISTER_DEFAULT 0X03 33 | #define SETUP_RETR_REGISTER_DEFAULT 0X03 34 | #define RF_CH_REGISTER_DEFAULT 0X02 35 | #define RF_SETUP_REGISTER_DEFAULT 0X0E 36 | #define STATUS_REGISTER_DEFAULT 0X0E 37 | #define MAXIMUM_NUMBER_OF_DATAPIPES 6 38 | 39 | #define POWER_DOWN 0X00 40 | #define STANDBYI 0X01 41 | #define STANDBYII 0X02 42 | #define PTX 0X03 43 | #define PRX 0X04 44 | #define DEVICE_NOT_INITIALIZED 0X05 45 | 46 | #define TRANSMITTER 0X00 47 | #define RECEIVER 0X01 48 | #define POWER_SAVING 0X02 49 | #define TURN_OFF 0X03 50 | 51 | #define RESET 1 52 | #define NO_RESET 0 53 | #define NO_ACK_MODE 1 54 | #define ACK_MODE 0 55 | #define TRANSMIT_BEGIN 1 56 | #define TRANSMIT_FAIL 0 57 | #define TRANSMIT_IN_PROGRESS 0 58 | #define TRANSMIT_DONE 1 59 | #define TRANSMIT_FAILED 0XFF 60 | #define OPERATION_DONE 1 61 | #define OPERATION_ERROR 0 62 | #define RECEIVE_FIFO_EMPTY 2 63 | #define TX_BUFFER 1 64 | #define RX_BUFFER 0 65 | 66 | /*bits definition section*/ 67 | #define MASK_RX_DR 6 /*mask interrupt caused by RX_DR: 1 interrupt not reflected on IRQ pin (IRQ is active low), inside CONFIG register*/ 68 | #define MASK_TX_DS 5 /*mask interrupt caused by TX_DS: 1 interrupt not reflected on IRQ pin (IRQ is active low), inside CONFIG register*/ 69 | #define MASK_MAX_RT 4 /*mask interrupt caused by MAX_RT means maximum number of retransmissions reached: 1 interrupt not reflected on IRQ pin (IRQ is active low), inside CONFIG register*/ 70 | #define EN_CRC 3 /*enale CRC, forced high if one of the bits in EN_AA is high, inside CONFIG register*/ 71 | #define CRCO 2 /*CRC encoding scheme, 0 is 1 byte, 1 is 2 bytes, inside CONFIG register*/ 72 | #define PWR_UP 1 /*1 is power up, inside CONFIG register*/ 73 | #define PRIM_RX 0 /*RX/TX control, 1: PRX, inside CONFIG register*/ 74 | #define ENAA_P5 5 /*enable auto acknowledgement data pipe 5*/ 75 | #define ENAA_P4 4 76 | #define ENAA_P3 3 77 | #define ENAA_P2 2 78 | #define ENAA_P1 1 79 | #define ENAA_P0 0 80 | #define ERX_P5 5 /*part of EN_RXADDR, enable data pipe 5*/ 81 | #define ERX_P4 4 82 | #define ERX_P3 3 83 | #define ERX_P2 2 84 | #define ERX_P1 1 85 | #define ERX_P0 0 86 | #define AW_1 1 /*RX/TX address field width, 00 illegal, 01 3 bytes, 10 4 bytes, 11 5 bytes*/ 87 | #define AW_0 0 88 | #define ARD_3 7 /*auto retransmit delay, 0000 250us, 0001 500us ...> 1111 4000us*/ 89 | #define ARD_2 6 90 | #define ARD_1 5 91 | #define ARD_0 4 92 | #define ARC_3 3 /*auto retransmit count, 0000 retransmit deisabled, 1111 up to 15 retransmit on failure of AA. (inside SETUP_RETR register)*/ 93 | #define ARC_2 2 94 | #define ARC_1 1 95 | #define ARC_0 0 96 | #define RF_CH_6 6 /*sets the frequencvy channel nRF24L01+ operates on*/ 97 | #define RF_CH_5 5 98 | #define RF_CH_4 4 99 | #define RF_CH_3 3 100 | #define RF_CH_2 2 101 | #define RF_CH_1 1 102 | #define RF_CH_0 0 103 | #define CONT_WAVE 7 /*enables continuous carrier transmit when high*/ 104 | #define RF_DR_LOW 5 /*sets the RF data rate to 250kbps*/ 105 | #define PLL_LOCK 4 /*force PLL lock signal. used for testing ONLY*/ 106 | #define RF_DR_HIGH 3 /*select between high speed data rates and works ONLY when RF_DR_LOW is 0. 0 for 1Mbps, 1 for 2Mbps*/ 107 | #define RF_PWR_1 2 108 | #define RF_PWR_0 1 109 | #define RX_DR 6 /*IRQ for new packet in RX FIFO (newly received)*/ 110 | #define TX_DS 5 /*IRQ for ACK received in TX mode*/ 111 | #define MAX_RT 4 112 | #define RX_P_NO_2 3 113 | #define RX_P_NO_1 2 114 | #define RX_P_NO_0 1 115 | #define TX_FULL 0 116 | #define PLOS_CNT_3 7 /*inside OBSERVE_TX register, counts the total number of retransmissions since last channel change. reset by writing to RF_CH*/ 117 | #define PLOS_CNT_2 6 118 | #define PLOS_CNT_1 5 119 | #define PLOS_CNT_0 4 120 | #define ARC_CNT_3 3 /*inside OBSERVE_TX register, counts the number of retransmissions for current transaction. reset by initiating new transaction*/ 121 | #define ARC_CNT_2 2 122 | #define ARC_CNT_1 1 123 | #define ARC_CNT_0 0 124 | #define RPD 0 /*received power detector, if received power is less than -64dbm, RPD = 0*/ 125 | #define TX_REUSE 6 126 | #define TX_FULL 5 127 | #define TX_EMPTY 4 128 | #define RX_FULL 1 129 | #define RX_EMPTY 0 130 | #define DPL_P5 5 131 | #define DPL_P4 4 132 | #define DPL_P3 3 133 | #define DPL_P2 2 134 | #define DPL_P1 1 135 | #define DPL_P0 0 /*must be set on PTX in dynamic payload length mode*/ 136 | #define EN_DPL 2 /*set to enable dynamic payload length*/ 137 | #define EN_ACK_PAY 1 /*used to enable auto acknowledgement with payload in PRX (inside FEATURE register)*/ 138 | #define EN_DYN_ACK 0 /**/ 139 | 140 | /*registers definition section*/ 141 | #define CONFIG_ADDRESS 0X00 142 | #define EN_AA_ADDRESS 0X01 /*enable auto acknowledgement feature*/ 143 | #define EN_RXADDR_ADDRESS 0X02 /*register containing bits to enable 6 data pipes individually*/ 144 | #define SETUP_AW_ADDRESS 0X03 /*address field length is configured in here to be 3, 4 or 5 bytes long*/ 145 | #define SETUP_RETR_ADDRESS 0X04 /*setup ARC bits to configure auto retransmission count*/ 146 | #define RF_CH_ADDRESS 0X05 147 | #define RF_SETUP_ADDRESS 0X06 148 | #define STATUS_ADDRESS 0X07 /*contains RX_DR, TX_DS, MAX_RT, RX_P_NO, TX_FULL, send R_REGISTER then NOP to read*/ 149 | #define OBSERVE_TX_ADDRESS 0X08 /*contains ARC_CNT and PLOS_CNT, two counters for retransmission. these counters could be used to assess the network quality*/ 150 | #define RPD_REG_ADDRESS 0X09 151 | #define RX_ADDR_P0_ADDRESS 0X0A /*the address for PRX device. if a packet contains this address, enhanced shockburst starts validating the packet*/ 152 | #define RX_ADDR_P1_ADDRESS 0X0B /*a total of 6 unique addresses could be assigned to a PRX device (Multiceiver feature)*/ 153 | #define RX_ADDR_P2_ADDRESS 0X0C /*these addresses must NOT be the same*/ 154 | #define RX_ADDR_P3_ADDRESS 0X0D 155 | #define RX_ADDR_P4_ADDRESS 0X0E 156 | #define RX_ADDR_P5_ADDRESS 0X0F 157 | #define TX_ADDR_ADDRESS 0X10 /*40 bits long register, transmit address, used for a PTX device only. configure address legth in SETUP_AW register. set RX_ADDR_P0 equal to this address to handle automatic acknowledge*/ 158 | #define RX_PW_P0_ADDRESS 0X11 /*these registers are for setting the static payload length in static payload length mode (receiver side)*/ 159 | #define RX_PW_P1_ADDRESS 0X12 160 | #define RX_PW_P2_ADDRESS 0X13 161 | #define RX_PW_P3_ADDRESS 0X14 162 | #define RX_PW_P4_ADDRESS 0X15 163 | #define RX_PW_P5_ADDRESS 0X16 164 | #define FIFO_STATUS_ADDRESS 0X17 165 | #define DYNPD_ADDRESS 0X1C /*on receiver side (RX mode), this register must be set to enable dynamic payload length. a PTX in dynamic mode, must have the DYNPD_P0 set*/ 166 | #define FEATURE_ADDRESS 0X1D /*contains the EN_DPL bit to enable dynamic payload length*/ 167 | 168 | /*commands definition section*/ 169 | #define R_REGISTER 0X00 /*read commmand and STATUS registers, 5 bit register map address*/ 170 | #define W_REGISTER 0X20 /*write commmand and STATUS registers, 5 bit register map address, executable in POWER DOWN or STANDBY modes only*/ 171 | #define R_RX_PAYLOAD 0X61 /*read RX payload, 1-32 bytes. read operation starts at byte 0. payload is deleted from FIFO after its read*/ 172 | #define W_TX_PAYLOAD 0XA0 /*write TX payload, starts at byte 0, 1-32 bytes*/ 173 | #define FLUSH_TX 0XE1 /*flush TX FIFO, used in TX mode*/ 174 | #define FLUSH_RX 0XE2 /*flush RX FIFO, used in RX mode*/ 175 | #define REUSE_TX_PL 0XE3 /*used for a PTX device, reuse last transmitted payload for an exact number. alternative to auto retransmission*/ 176 | #define R_RX_PL_WID 0X60 /*command for receiver side, in order to read the payload length in dynamic payload length mode*/ 177 | #define W_ACK_PAYLOAD 0XA0 /*used in RX mode, to write payload in TX FIFO and later transmit the payloads along with ACK packet to PTX, if DPL is enabled*/ 178 | #define W_TX_PAYLOAD_NOACK 0XB0 /*used in TX mode, disables AUTOACK on this specific packet. must be first enabled in FEATURE register by setting the EN_DYN_ACK bit. if used, PTX will not wait for ACK and goes directly to standby I*/ 179 | #define NOP_CMD 0XFF /*might be used to read the status register*/ 180 | 181 | void nrf24_reset(); 182 | void nrf24_device(uint8_t device_mode, uint8_t reset_state); 183 | uint8_t SPI_send_command(uint8_t command); 184 | void pinout_Initializer(); 185 | void SPI_Initializer(); 186 | void nrf24_mode(uint8_t mode); 187 | void nrf24_SPI(uint8_t input); 188 | void nrf24_CE(uint8_t input); 189 | void nrf24_address_width(uint8_t address_width); 190 | void nrf24_rf_channel(uint8_t rf_channel); 191 | void nrf24_rf_power(uint8_t rf_power); 192 | void nrf24_rf_datarate(uint8_t rf_datarate); 193 | void nrf24_read(uint8_t address, uint8_t *value, uint8_t data_length, uint8_t spi_state); 194 | void nrf24_write(uint8_t address, uint8_t *value, uint8_t data_length, uint8_t spi_state); 195 | void delay_function(uint32_t duration_ms); 196 | void nrf24_crc_configuration(uint8_t crc_enable, uint8_t crc_encoding_scheme); 197 | void nrf24_interrupt_mask(uint8_t rx_mask, uint8_t tx_mask, uint8_t max_rt_mask); 198 | void nrf24_datapipe_enable(uint8_t number_of_datapipes); 199 | void nrf24_prx_static_payload_width(uint8_t static_payload_width, uint8_t number_of_datapipes); 200 | void nrf24_datapipe_address_configuration(); 201 | void nrf24_datapipe_ptx(uint8_t datapipe_number); 202 | void nrf24_automatic_retransmit_setup(uint16_t delay_time, uint8_t retransmit_count); 203 | void nrf24_auto_acknowledgment_setup(uint8_t datapipe); 204 | void nrf24_dynamic_payload(uint8_t state, uint8_t datapipe); 205 | void nrf24_device(uint8_t device_mode, uint8_t reset_state); 206 | void nrf24_send_payload(uint8_t *payload, uint8_t payload_width); 207 | uint8_t nrf24_receive(uint8_t *payload, uint8_t payload_width); 208 | uint8_t nrf24_transmit(uint8_t *payload, uint8_t payload_width, uint8_t acknowledgement_state); 209 | uint8_t nrf24_transmit_status(); 210 | void nrf24_dynamic_ack(uint8_t state); 211 | uint8_t nrf24_flush(uint8_t fifo_select); 212 | 213 | #endif 214 | -------------------------------------------------------------------------------- /nrf24l01_low_level.c: -------------------------------------------------------------------------------- 1 | #include "nrf24l01.h" 2 | 3 | /*start of low level functions, specific to the mcu and compiler*/ 4 | 5 | /*delay in miliseconds*/ 6 | void delay_function(uint32_t duration_ms) 7 | { 8 | } 9 | 10 | /*contains all SPI configuations, such as pins and control registers*/ 11 | /*SPI control: master, interrupts disabled, clock polarity low when idle, clock phase falling edge, clock up tp 1 MHz*/ 12 | void SPI_Initializer() 13 | { 14 | } 15 | 16 | /*contains all CSN and CE pins gpio configurations, including setting them as gpio outputs and turning SPI off and CE '1'*/ 17 | void pinout_Initializer() 18 | { 19 | } 20 | 21 | /*CSN pin manipulation to high or low (SPI on or off)*/ 22 | void nrf24_SPI(uint8_t input) 23 | { 24 | } 25 | 26 | /*1 byte SPI shift register send and receive routine*/ 27 | uint8_t SPI_send_command(uint8_t command) 28 | { 29 | } 30 | 31 | /*CE pin maniplation to high or low*/ 32 | void nrf24_CE(uint8_t input) 33 | { 34 | } 35 | --------------------------------------------------------------------------------