This is a work in progress for an NRF2401P
Dependents: NRF_receiver sender locker4 Weather_Station_Ofiicial ... more
About
This is a simple library to drive the nRF24l01+.
Hardware
This uses the commonly available breakout. The connections are shown below
Software
Use case: For a simple transmitter
tx code snipet
#include "NRF2401P.h" int main() { * * long long addr1=0xAB00CD; // setup address - any 5 byte number - same as RX * int channel =0x12; // [0-126] setup channel, must be same as RX * bool txOK; * char msg[32]; * char ackData[32]; * char len; * * // Setup * NRF2401P nrf1(PTD6,PTD7, PTD5,PTD4, PTC12); //mosi, miso, sclk, csn, ce) * nrf1.quickTxSetup(channel, addr1); // sets nrf24l01+ as transmitter * * // transmit * strcpy (msg, "Hello"); * txOK= nrf1.transmitData(msg,strlen(msg)); * * // read ack data if available * if (nrf1.isAckData()) { * len= nrf1.getRxData(ackData); // len is number of bytes in ackData * } *}
Use case: For a simple receiver
rx code snipet
#include "NRF2401P.h" *int main(){ * * long long addr1=0xAB00CD; // setup address - any 5 byte number - same as TX * int channel =0x12; // [0-126] setup channel, must be same as TX * bool txOK; * char msg[32]; * char ackData[32]; * char len; * * // Setup * NRF2401P nrf1(PTD6,PTD7, PTD5,PTD4, PTC12); //mosi, miso, sclk, csn, ce) * nrf1.quickRxSetup(channel, addr1); // sets nrf24l01+ as receiver, using pipe 1 * * // set ack data * sprintf(ackData,"Ack data"); * nrf1.acknowledgeData(ackData, strlen(ackData),1); // ack for pipe 1 * * // receive * while (! nrf1.isRxData()); // note this blocks until RX data * len= nrf1.getRxData(msg); // gets the message, len is length of msg * *}
NRF2401P.cpp
- Committer:
- epgmdm
- Date:
- 2015-06-11
- Revision:
- 1:ff53b1ac3bad
- Parent:
- 0:8fd0531ae0be
- Child:
- 2:ca0a3c0bba70
File content as of revision 1:ff53b1ac3bad:
#include "mbed.h" #include "NRF2401P.h" /** *@section DESCRIPTION * mbed NRF2401+ Library *@section LICENSE * Copyright (c) 2015, Malcolm McCulloch * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * @file "NRF2401P.cpp" */ NRF2401P::NRF2401P ( PinName mosi, PinName miso, PinName sclk, PinName _csn, PinName _ce ) : csn( DigitalOut( _csn ) ), ce( DigitalOut( _ce ) ) { addressWidth = 5; pc = new Serial( USBTX, USBRX ); // tx, rx sprintf(logMsg, "Initialise " ); log(logMsg); spi = new SPI( mosi, miso, sclk, NC ); //SPI (PinName mosi, PinName miso, PinName sclk, PinName _unused=NC) spi->frequency( 10000000 ); // 1MHZ max 10 MHz spi->format( 8, 0 ); // 0: 0e 08; 1: 0e 00; 2:0e 00 ;3:1c 00 csn = 1; ce = 0; dynamic = false; debug=1|false; }; /** * writes to pc and waits */ void NRF2401P::log (char *msg) { if(debug) { printf("<%s \t %s>\n\r",statusString(), msg); wait(0.01); }; } void NRF2401P::scratch() { int status = 0; int register1 = 0; ce = 0; for ( char i = 0; i < 24; i++ ) { csn = 0; //wait_us(100); status = spi->write( i ); register1 = spi->write( 0x00 ); csn = 1; sprintf(logMsg, " register %02x (%02x) = %02x", i, status, register1 ); log(logMsg); } } /** * Sets up a reciever using shockburst and dynamic payload. Uses pipe 1 * defaults to 5 bytes */ void NRF2401P::quickRxSetup(int channel,long long addr) { setRadio(0,3); setChannel(channel); setRxMode(); setAddressWidth(3); setRxAddress(addr,0); setDynamicPayload(); writeReg(0x02,0x03); // EN_RXADDR for P1 writeReg(0x01,0x03); // EN_AA regi for P1 setPwrUp(); ce=1; wait (0.1f); } /** * Sets up for receive of a message to address 0XA0A0A0 */ char NRF2401P::testReceive() { char message[64]; char width; int channel = 0x12; long long addr=0xA0B0C0; debug = true; quickRxSetup(channel, addr); while (1) { while (!isRxData()) { //wait(0.5); }; width=getRxData(message); message[width]='\0'; sprintf(logMsg,"Received= [%s]",message); log(logMsg); }; } /** * Sets up a transmitter using shockburst and dynamic payload. Uses pipe 1 * defaults to 5 bytes */ void NRF2401P::quickTxSetup(int channel,long long addr) { setRadio(0,3); setChannel(channel); setTxMode(); setPwrUp(); setDynamicPayload(); setAddressWidth(3); setTxAddress(addr); writeReg(0x04,0x2f); // ARD 750 uS ARC 15 writeReg(0x02,0x03); // EN_RXADDR for P1 and P0 setPwrUp(); ce=1; wait (0.0016f); // wait for pll to settle } /** * Sets up for transmit of a message to address 0XA0A0A0 */ char NRF2401P::testTransmit() { long long addr=0xA0B0C0; int channel = 0x12; char data[32] ; int i=0; quickRxSetup(channel, addr); while (1) { sprintf(data," packet %03d", i++ |100); transmitData(data,18); wait (1.0); } } /** *Speed : ‘0x00’ – 1Mbps ‘0x01’ – 2Mbps ‘0x02’ – 250kbps ‘0x03’ – Reserved Power: '0x00' – -18dBm '0x01' – -12dBm '0x02' – -6dBm '0x03' – 0dBm */ char NRF2401P::setRadio(char speed,char power) { char val=0; sprintf(logMsg, "Set radio"); log(logMsg); if (speed & 0x02) { val |= (1<<5); } val |= (speed & 0x01)<<3; val |= ((power &0x03)<<1); writeReg (0x06,val); } /** Set RF_CH = chan; F0= 2400 + chan [MHz] */ char NRF2401P::setChannel(char chan) { sprintf(logMsg, "Set channel"); log(logMsg); writeReg (0x05,(chan&0x7f)); } /** * Transmits width bytes of data. width <32 */ char NRF2401P::transmitData( char *data, char width ) { clearStatus(); ce = 1; csn = 0; char address = 0XA0; int i; // set up for writing status = spi->write( address ); for ( i = 0; i <width; i++ ) { spi->write( data[ i ] ); } csn = 1; sprintf(logMsg, " Transmit data %d bytes to %02x (%02x) = %02x", width, address, status, data ); log(logMsg); return status; } /** * sets acknowledge data width bytes of data. width <32 */ char NRF2401P::acknowledgeData( char *data, char width, char pipe ) { ce = 1; csn = 0; writeReg(0x1d,0x06); // enable payload with ack char address = 0XA8| (pipe&0x07); int i; // set up for writing status = spi->write( address ); for ( i = 0; i <width; i++ ) { spi->write( data[ i ] ); } csn = 1; sprintf(logMsg, " acknowledge data %d bytes to %02x (%02x) = %02x", width, address, status, *data ); log(logMsg); return status; } /** * Writes 1 byte data to a register **/ char NRF2401P::writeReg( char address, char data ) { char status = 0; char reg; csn = 0; address &= 0x1F; reg = address | 0x20; status = spi->write( reg ); spi->write( data ); csn = 1; sprintf(logMsg, " register write %02x (%02x) = %02x", address, status, data ); log(logMsg); return status; } /** * Writes width bytes data to a register, ls byte to ms byte /for adressess **/ char NRF2401P::writeReg( char address, char *data, char width ) { char reg; csn = 0; int i; // set up for writing address &= 0x1F; reg = address| 0x20; status = spi->write( reg ); for ( i = width - 1; i >= 0; i-- ) { spi->write( data[ i ] ); } csn = 1; sprintf(logMsg, " register write %d bytes to %02x (%02x) = %02x %02x %02x", width, address, status, data[0], data[1], data[2] ); log(logMsg); return status; } /** * Reads 1 byte from a register **/ char NRF2401P::readReg( char address, char *data ) { csn = 0; address &= 0x1F; status = spi->write( address ); *data = spi->write( 0x00 ); csn = 1; // sprintf(logMsg, " register read %02x (%02x) = %02x", address, status, *data ); // log(logMsg); return status; } /** * Clears the status flags RX_DR, TX_DS, MAX_RT */ bool NRF2401P::clearStatus() { status = writeReg(0x07,0x70); sprintf(logMsg, "Clear status (%02x)", status ); log(logMsg); } /** * flushes TX FIFO and resets status flags */ bool NRF2401P::flushTx() { csn = 0; status = spi->write( 0xE1 ); csn = 1; clearStatus(); sprintf(logMsg, "Flush TX FIFO (%02x)", status ); log(logMsg); return; } /** * flushes RX FIFO and resets status flags */ bool NRF2401P::flushRx() { csn = 0; status = spi->write( 0xE2 ); status = spi->write( 0xFF ); //Update status csn = 1; sprintf(logMsg, "Flush RX FIFO (%02x)", status ); log(logMsg); } /** * Sets PRIM_RX = 0; */ bool NRF2401P::setTxMode() { char data; char bit; sprintf(logMsg, "Set Tx Mode"); log(logMsg); readReg( 0x00, &data ); data &= ~( 1 << 0 ); writeReg( 0x00, data ); // check readReg( 0x00, &data ); bit = ( data >> 0 ) & 1; ce=1; clearStatus(); flushTx(); wait(0.003); return ( bit == 0 ); } /** * Sets the number of bytes of the address width = 3,4,5 */ bool NRF2401P::setAddressWidth( char width ) { addressWidth = width; if ( ( width > 5 ) || ( width < 3 ) ) return false; width -= 2; return writeReg( 0x03, width ); } /** * Sets the address, uses addess width set (either 3,4 or 5) */ char NRF2401P::setTxAddress( char *address ) { writeReg( 0x0A, address, addressWidth ); //Write to RX_ADDR_P0 return writeReg( 0x10, address, addressWidth ); //Write to TX_ADDR } /** * Sets the address, uses addess width set (either 3,4 or 5) */ char NRF2401P::setTxAddress( long long address ) { char buff[ 5 ]; buff[ 0 ] = address & 0xff; buff[ 1 ] = ( address >> 8 ) & 0xFF; buff[ 2 ] = ( address >> 16 ) & 0xFF; buff[ 3 ] = ( address >> 24 ) & 0xFF; buff[ 4 ] = ( address >> 32 ) & 0xFF; return setTxAddress( buff ); } /** * Sets the address, uses addess width set (either 3,4 or 5) */ char NRF2401P::setRxAddress( char *address, char pipe ) { log ("Set Rx Address"); char reg = 0x0A + pipe; switch ( pipe ) { case ( 0 ) : case ( 1 ) : { status = writeReg( reg, address, addressWidth ); //Write to RX_ADDR_P0 or _P1 break; } case ( 2 ) : case ( 3 ) : case ( 4 ) : case ( 5 ) : { status = writeReg( reg, address, 1 ); //Write to RX_ADDR_P2 ... _P5 break; } } // writeReg( 0x0A, address, addressWidth ); //Write to RX_ADDR_P0 return status; } /** * Sets the address of pipe (<=5), uses addess width set (either 3,4 or 5) */ char NRF2401P::setRxAddress( long long address, char pipe ) { char buff[ 5 ]; buff[ 0 ] = address & 0xff; buff[ 1 ] = ( address >> 8 ) & 0xFF; buff[ 2 ] = ( address >> 16 ) & 0xFF; buff[ 3 ] = ( address >> 24 ) & 0xFF; buff[ 4 ] = ( address >> 32 ) & 0xFF; return setRxAddress( buff, pipe ); } /** *checks the status flag */ char NRF2401P::checkStatus() { readReg(0x07,&status); return status; } /** * checks if Ack data available. */ bool NRF2401P::isAckData() { char fifo; readReg(0x17,&fifo); bool isData = !(fifo&0x01); return isData; } /** * checks if RX data available. */ bool NRF2401P::isRxData() { checkStatus(); bool isData = (status>>6)&0x01; return isData; } /** * returns the width of the dynamic payload */ char NRF2401P::getRxWidth() { char width; if (dynamic) { csn = 0; status = spi->write( 0x60 ); width = spi->write(0x00); csn = 1; if (width>32) { flushRx(); width=0; } } else { status = readReg(0x12,&width); // width of p1 } // width=18; return width; } /** * return message in buffer, mem for buffer must have been allocated. * Return value is number of bytes of buffer */ char NRF2401P::getRxData(char * buffer) { char address = 0x61; char width; width = getRxWidth(); bool isData = (status>>6)&0x01; if (isData) { csn = 0; int i; // set up for reading status = spi->write( address ); for ( i = 0; i <= width; i++ ) { buffer[i]=spi->write(0x00 ); } csn = 1; sprintf(logMsg, "Receive data %d bytes", width ); log(logMsg); clearStatus(); return width; } else { sprintf(logMsg, "Receive NO data %d bytes", width ); log(logMsg); clearStatus(); return 0; } } /** * Sets all the receive pipes to dynamic payload length */ char NRF2401P::setDynamicPayload() { dynamic = true; writeReg (0x1D,0x06); writeReg(0x01,0x3f); // EN_AA regi for P1 and P0 return(writeReg(0x1C, 0x1F)); } /** * Sets PWR_UP = 1; */ bool NRF2401P::setPwrUp() { char data; char bit; ce=1; readReg( 0x00, &data ); data |= ( 0x02 ); writeReg( 0x00, data ); // check readReg( 0x00, &data ); bit = ( data >> 1 ) & 1; sprintf(logMsg, "Set PWR_UP to %x", bit); log(logMsg); wait(0.005); // wait 5ms return ( bit == 1 ); } /** * Sets PRIM_RX = 0; */ bool NRF2401P::setRxMode() { char data; char bit; ce=1; readReg( 0x00, &data ); data |= ( 0x03 ); writeReg( 0x00, data ); // check readReg( 0x00, &data ); bit = ( data >> 0 ) & 1; sprintf(logMsg, " set PRIM_RX to %x", bit); log(logMsg); clearStatus(); flushRx(); return ( bit == 1 ); } /** * Prints status string */ char * NRF2401P::statusString() { char *msg; msg = statusS; if (((status>>1) & 0x07)==0x07) { sprintf(msg,"RX empty"); } else { sprintf(msg,"pipe %02x",(status>>1) & 0x07); } if ((status>>6)&0x01) strcat(msg," RX_DR,"); if ((status>>5)&0x01) strcat(msg," TX_DS,"); if ((status>>4)&0x01) strcat(msg," MAX_RT,"); if ((status>>0)&0x01) strcat(msg," TX_FLL,"); return msg; }