糊涂塔克学习笔记01 Arduino+nRF24L01

各位大大好,我是个新手,大概2个月前刚开始学习Arduino(为了参加一个比赛),在极客工坊潜水很久,学习了很多东西,现在也想把这段时间学习的东西和大家分享。



我看到论坛里关于无线发射模块的资料比较少,所以我来发一个无线方面的学习笔记,关于nRF24L01



关于无线模块大家比较熟悉的可能是APC220和Xbee这两种无线模块,网上的资料也很多,我也就不班门弄斧了,但这两种无线模块价格比较贵(因为这个比赛有一个要求是对成本的控制),所以我后来开始研究nRF24L01来进行2个Arduino板子之间的通讯(2块nRF24L01只有36块钱)



关于nRF24L01,工作于2.4 GHz~2.5 GHz ISM频段, 最高工作速率2Mbps,125 频道,满足多点通信和跳频通信需要,低功耗1.9 - 3.6V 工作,待机模式下状态为22uA;掉电模式下为900nA,可以用SPI控制


NRF24L01-RF-Board-B-1.JPG

2012-6-16 14:25 上传
(40.88 KB)

RF24L01_3.jpg

2012-6-16 14:24 上传
(46.45 KB)





首先你需要有2块Arduino开发板和2块nRF24L01通信芯片,一个作为发射,一个作为接收。如果你使用的是标准的Arduino开发板,请注意使用开发板上的3.3V pin 作为电源,因为nRF24L01的工作电压是1.9~3.6V,如果使用5V的供电口会把nRF24L01芯片烧坏。



测试程序原文地址:http://www.elecfreaks.com/203.html



这个测试程序的接口如下:

GND – GND, VCC – 3.3V, CS – D8, CSN – D9, SCK – D10, MOSI – D11, MISO – D12, IRQ – D13

(IRQ这个口在这个例程中并没有用到,所以可以不接)



接好后的示意图如下:


2028_thumb1-190x160.jpg

2012-6-16 14:32 上传
(5.39 KB)





这个测试程序是发射端不断发送0x00到0XFF的数据给接收端(程序中用到的头文件打包在附件里)

先是发射端的代码:ARDUINO 代码复制打印

/***********************************************************************Device:nRF24L01+                ****File: EF_nRF24L01_TX.c              ****                      ****                      ****Copyright (C) 2011 ElecFraks.           ****This example code is in the public domain.        ****                      ****Description:                  ****This file is a sample code for your reference.      ****It's the v1.1 nRF24L01+ by arduino          ****Created by ElecFreaks. Robi.W,24 July 2011        ****                      ****http://www.elecfreaks.com             ****                      **** SPI-compatible                 **** CS - to digital pin 8              **** CSN - to digital pin 9(SS pin)           **** SCK - to digital pin 10 (SCK pin)          **** MOSI - to digital pin 11 (MOSI pin)          **** MISO - to digital pin 12 (MISO pin)          **** IRQ - to digital pin 13 (MISO pin)         ***********************************************************************/#include "NRF24L01.h"//***************************************************#define TX_ADR_WIDTH  5 // 5 unsigned chars TX(RX) address width#define TX_PLOAD_WIDTH32// 32 unsigned chars TX payloadunsigned char TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; // Define a static TX addressunsigned char rx_buf[TX_PLOAD_WIDTH] = {

  • Function: SPI_RW();

  • Description:
  • Writes one unsigned char to nRF24L01, and return the unsigned char read
  • from nRF24L01 during write, according to SPI protocol

    **************************************************/

    unsigned char SPI_RW(unsigned char Byte)

    {

    unsigned char i;

    for(i=0;i<8;i++) // output 8-bit

    {

    if(Byte&0x80)

    {

    digitalWrite(MOSI, 1);

    }

    else

    {

    digitalWrite(MOSI, 0);

    }

    digitalWrite(SCK, 1);

    Byte <<= 1; // shift next bit into MSB..

    if(digitalRead(MISO) == 1)

    {

    Byte |= 1; // capture current MISO bit

    }

    digitalWrite(SCK, 0);

    }

    return(Byte); // return read unsigned char

    }

    /**************************************************/



    /**************************************************<br />
  • Function: SPI_RW_Reg();

  • Description:
  • Writes value 'value' to register 'reg'

    /**************************************************/

    unsigned char SPI_RW_Reg(unsigned char reg, unsigned char value)

    {

    unsigned char status;



    digitalWrite(CSN, 0); // CSN low, init SPI transaction

    status = SPI_RW(reg); // select register

    SPI_RW(value); // ..and write value to it..

    digitalWrite(CSN, 1); // CSN high again



    return(status); // return nRF24L01 status unsigned char

    }

    /**************************************************/



    /**************************************************<br />
  • Function: SPI_Read();

  • Description:
  • Read one unsigned char from nRF24L01 register, 'reg'

    /**************************************************/

    unsigned char SPI_Read(unsigned char reg)

    {

    unsigned char reg_val;



    digitalWrite(CSN, 0); // CSN low, initialize SPI communication...

    SPI_RW(reg); // Select register to read from..

    reg_val = SPI_RW(
  • Function: SPI_Read_Buf();

  • Description:
  • Reads 'unsigned chars' #of unsigned chars from register 'reg'
  • Typically used to read RX payload, Rx/Tx address

    /**************************************************/

    unsigned char SPI_Read_Buf(unsigned char reg, unsigned char *pBuf, unsigned char bytes)

    {

    unsigned char status,i;



    digitalWrite(CSN, 0); // Set CSN low, init SPI tranaction

    status = SPI_RW(reg); // Select register to write to and read status unsigned char



    for(i=0;i<bytes;i++)

    {

    pBuf[i] = SPI_RW(); // Perform SPI_RW to read unsigned char from nRF24L01

    }



    digitalWrite(CSN, 1); // Set CSN high again



    return(status); // return nRF24L01 status unsigned char

    }

    /**************************************************/



    /**************************************************<br />
  • Function: SPI_Write_Buf();

  • Description:
  • Writes contents of buffer '*pBuf' to nRF24L01
  • Typically used to write TX payload, Rx/Tx address

    /**************************************************/

    unsigned char SPI_Write_Buf(unsigned char reg, unsigned char pBuf, unsigned char bytes)

    {

    unsigned char status,i;



    digitalWrite(CSN, 0); // Set CSN low, init SPI tranaction

    status = SPI_RW(reg); // Select register to write to and read status unsigned char

    for(i=0;i<bytes; i++) // then write all unsigned char in buffer(
    pBuf)

    {

    SPI_RW(*pBuf++);

    }

    digitalWrite(CSN, 1); // Set CSN high again

    return(status); // return nRF24L01 status unsigned char

    }

    /**************************************************/



    /**************************************************<br />
  • Function: TX_Mode();

  • Description:
  • This function initializes one nRF24L01 device to
  • TX mode, set TX address, set RX address for auto.ack,
  • fill TX payload, select RF channel, datarate & TX pwr.
  • PWR_UP is set, CRC(2 unsigned chars) is enabled, & PRIM:TX.

  • ToDo: One high pulse(>10us) on CE will now send this
  • packet and expext an acknowledgment from the RX device.

    **************************************************/

    void TX_Mode(void)

    {

    digitalWrite(CE, 0);



    SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // Writes TX_Address to nRF24L01

    SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // RX_Addr0 same as TX_Adr for Auto.Ack



    SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // Enable Auto.Ack:Pipe0

    SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);// Enable Pipe0

    SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a); // 500us + 86us, 10 retrans...

    SPI_RW_Reg(WRITE_REG + RF_CH, 40); // Select RF channel 40

    SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // TX_PWR:0dBm, Datarate:2Mbps, LNA:HCURR

    SPI_RW_Reg(WRITE_REG + CONFIG, 0x0e); // Set PWR_UP bit, enable CRC(2 unsigned chars) & Prim:TX. MAX_RT & TX_DS enabled..

    SPI_Write_Buf(WR_TX_PLOAD,tx_buf,TX_PLOAD_WIDTH);



    digitalWrite(CE, 1);

    }


再是接收端的代码:

ARDUINO 代码复制打印
/***********************************************************************Device:nRF24L01+                ****File: EF_nRF24L01_TX.c              ****                      ****                      ****Copyright (C) 2011 ElecFraks.           ****This example code is in the public domain.        ****                      ****Description:                  ****This file is a sample code for your reference.      ****It's the v1.1 nRF24L01+ by arduino          ****Created by ElecFreaks. Robi.W,24 July 2011        ****                      ****http://www.elecfreaks.com             ****                      **** SPI-compatible                 **** CS - to digital pin 8              **** CSN - to digital pin 9(SS pin)           **** SCK - to digital pin 10 (SCK pin)          **** MOSI - to digital pin 11 (MOSI pin)          **** MISO - to digital pin 12 (MISO pin)          **** IRQ - to digital pin 13 (MISO pin)         ***********************************************************************/#include "NRF24L01.h"//***************************************************#define TX_ADR_WIDTH  5 // 5 unsigned chars TX(RX) address width#define TX_PLOAD_WIDTH32// 32 unsigned chars TX payloadunsigned char TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; // Define a static TX addressunsigned char rx_buf[TX_PLOAD_WIDTH];unsigned char tx_buf[TX_PLOAD_WIDTH];//***************************************************void setup() {pinMode(CE,OUTPUT);pinMode(SCK, OUTPUT);pinMode(CSN, OUTPUT);pinMode(MOSI,OUTPUT);pinMode(MISO, INPUT);pinMode(IRQ, INPUT);//attachInterrupt(1, _ISR, LOW); // interrupt enableSerial.begin(9600);init_io();        // Initialize IO portunsigned char status=SPI_Read(STATUS);Serial.print("status = ");Serial.println(status,HEX);  // There is read the mode鈥檚 status register, the default value should be 鈥楨鈥? Serial.println("*****************RX_Mode start******************************R");RX_Mode();        // set RX mode}void loop() {for(;;){  unsigned char status = SPI_Read(STATUS);         // read register STATUS's value  if(status&RX_DR)                 // if receive data ready (TX_DS) interrupt  {  SPI_Read_Buf(RD_RX_PLOAD, rx_buf, TX_PLOAD_WIDTH);     // read playload to rx_buf  SPI_RW_Reg(FLUSH_RX,0);              // clear RX_FIFO  for(int i=0; i<32; i++)  {    Serial.print(" ");    Serial.print(rx_buf[i],HEX);          // print rx_buf  }  Serial.println(" ");  }  SPI_RW_Reg(WRITE_REG+STATUS,status);         // clear RX_DR or TX_DS or MAX_RT interrupt flag  delay(1000);}}//**************************************************// Function: init_io();// Description:// flash led one time,chip enable(ready to TX or RX Mode),// Spi disable,Spi clock line init high//**************************************************void init_io(void){digitalWrite(IRQ, 0);digitalWrite(CE, 0);            // chip enabledigitalWrite(CSN, 1);     // Spi disable    }/*************************************************** Function: SPI_RW();* * Description:* Writes one unsigned char to nRF24L01, and return the unsigned char read* from nRF24L01 during write, according to SPI protocol**************************************************/unsigned char SPI_RW(unsigned char Byte){unsigned char i;for(i=0;i<8;i++)        // output 8-bit{  if(Byte&0x80)  {  digitalWrite(MOSI, 1);  // output 'unsigned char', MSB to MOSI  }  else  {  digitalWrite(MOSI, 0);  }  digitalWrite(SCK, 1);        // Set SCK high..  Byte <<= 1;         // shift next bit into MSB..  if(digitalRead(MISO) == 1)  {  Byte |= 1;           // capture current MISO bit  }  digitalWrite(SCK, 0);       // ..then set SCK low again}return(Byte);         // return read unsigned char}/**************************************************//*************************************************** Function: SPI_RW_Reg();* * Description:* Writes value 'value' to register 'reg'/**************************************************/unsigned char SPI_RW_Reg(unsigned char reg, unsigned char value){unsigned char status;digitalWrite(CSN, 0);       // CSN low, init SPI transactionstatus = SPI_RW(reg);       // select registerSPI_RW(value);        // ..and write value to it..digitalWrite(CSN, 1);       // CSN high againreturn(status);       // return nRF24L01 status unsigned char}/**************************************************//*************************************************** Function: SPI_Read();* * Description:* Read one unsigned char from nRF24L01 register, 'reg'/**************************************************/unsigned char SPI_Read(unsigned char reg){unsigned char reg_val;digitalWrite(CSN, 0);   // CSN low, initialize SPI communication...SPI_RW(reg);       // Select register to read from..reg_val = SPI_RW(0);   // ..then read register valuedigitalWrite(CSN, 1);    // CSN high, terminate SPI communicationreturn(reg_val);     // return register value}/**************************************************//*************************************************** Function: SPI_Read_Buf();* * Description:* Reads 'unsigned chars' #of unsigned chars from register 'reg'* Typically used to read RX payload, Rx/Tx address/**************************************************/unsigned char SPI_Read_Buf(unsigned char reg, unsigned char *pBuf, unsigned char bytes){unsigned char status,i;digitalWrite(CSN, 0);      // Set CSN low, init SPI tranactionstatus = SPI_RW(reg);       // Select register to write to and read status unsigned charfor(i=0;i<bytes;i++){  pBuf[i] = SPI_RW(0);  // Perform SPI_RW to read unsigned char from nRF24L01}digitalWrite(CSN, 1);       // Set CSN high againreturn(status);      // return nRF24L01 status unsigned char}/**************************************************//*************************************************** Function: SPI_Write_Buf();* * Description:* Writes contents of buffer '*pBuf' to nRF24L01* Typically used to write TX payload, Rx/Tx address/**************************************************/unsigned char SPI_Write_Buf(unsigned char reg, unsigned char *pBuf, unsigned char bytes){unsigned char status,i;digitalWrite(CSN, 0);       // Set CSN low, init SPI tranactionstatus = SPI_RW(reg);     // Select register to write to and read status unsigned charfor(i=0;i<bytes; i++)     // then write all unsigned char in buffer(*pBuf){  SPI_RW(*pBuf++);}digitalWrite(CSN, 1);      // Set CSN high againreturn(status);      // return nRF24L01 status unsigned char}/**************************************************//*************************************************** Function: RX_Mode();* * Description:* This function initializes one nRF24L01 device to* RX Mode, set RX address, writes RX payload width,* select RF channel, datarate & LNA HCURR.* After init, CE is toggled high, which means that* this device is now ready to receive a datapacket./**************************************************/void RX_Mode(void){digitalWrite(CE, 0);SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // Use the same address on the RX device as the TX deviceSPI_RW_Reg(WRITE_REG + EN_AA, 0x01);  // Enable Auto.Ack:Pipe0SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);// Enable Pipe0SPI_RW_Reg(WRITE_REG + RF_CH, 40);  // Select RF channel 40SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); // Select same RX payload width as TX Payload widthSPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // TX_PWR:0dBm, Datarate:2Mbps, LNA:HCURRSPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // Set PWR_UP bit, enable CRC(2 unsigned chars) & Prim:RX. RX_DR enabled..digitalWrite(CE, 1);         // Set CE pin high to enable RX device//This device is now ready to receive one packet of 16 unsigned chars payload from a TX device sending to address//'3443101001', with auto acknowledgment, retransmit count of 10, RF channel 40 and datarate = 2Mbps.}/**************************************************/
/*********************************************************************
**Device:nRF24L01+ **
**File: EF_nRF24L01_TX.c **
** **
** **
**Copyright (C) 2011 ElecFraks. **
**This example code is in the public domain. **
** **
**Description: **
**This file is a sample code for your reference. **
**It's the v1.1 nRF24L01+ by arduino **
**Created by ElecFreaks. Robi.W,24 July 2011 **
** **
**http://www.elecfreaks.com **
** **
** SPI-compatible **
** CS - to digital pin 8 **
** CSN - to digital pin 9(SS pin) **
** SCK - to digital pin 10 (SCK pin) **
** MOSI - to digital pin 11 (MOSI pin) **
** MISO - to digital pin 12 (MISO pin) **
** IRQ - to digital pin 13 (MISO pin) **
*********************************************************************/

#include "NRF24L01.h"

//***************************************************
#define TX_ADR_WIDTH 5 // 5 unsigned chars TX(RX) address width
#define TX_PLOAD_WIDTH32// 32 unsigned chars TX payload

unsigned char TX_ADDRESS[TX_ADR_WIDTH]=
{
0x34,0x43,0x10,0x10,0x01
}; // Define a static TX address

unsigned char rx_buf[TX_PLOAD_WIDTH];
unsigned char tx_buf[TX_PLOAD_WIDTH];
//***************************************************
void setup()
{
pinMode(CE,OUTPUT);
pinMode(SCK, OUTPUT);
pinMode(CSN, OUTPUT);
pinMode(MOSI,OUTPUT);
pinMode(MISO, INPUT);
pinMode(IRQ, INPUT);
//attachInterrupt(1, _ISR, LOW); // interrupt enable
Serial.begin(9600);
init_io(); // Initialize IO port
unsigned char status=SPI_Read(STATUS);
Serial.print("status = ");
Serial.println(status,HEX); // There is read the mode鈥檚 status register, the default value should be 鈥楨鈥?
Serial.println("*****************RX_Mode start******************************R");
RX_Mode(); // set RX mode
}
void loop()
{
for(;;)
{
unsigned char status = SPI_Read(STATUS); // read register STATUS's value
if(status&RX_DR) // if receive data ready (TX_DS) interrupt
{
SPI_Read_Buf(RD_RX_PLOAD, rx_buf, TX_PLOAD_WIDTH); // read playload to rx_buf
SPI_RW_Reg(FLUSH_RX,0); // clear RX_FIFO
for(int i=0; i<32; i++)
{
Serial.print(" ");
Serial.print(rx_buf[i],HEX); // print rx_buf
}
Serial.println(" ");
}
SPI_RW_Reg(WRITE_REG+STATUS,status); // clear RX_DR or TX_DS or MAX_RT interrupt flag
delay(1000);
}
}

//**************************************************
// Function: init_io();
// Description:
// flash led one time,chip enable(ready to TX or RX Mode),
// Spi disable,Spi clock line init high
//**************************************************
void init_io(void)
{
digitalWrite(IRQ, 0);
digitalWrite(CE, 0); // chip enable
digitalWrite(CSN, 1); // Spi disable
}

/**************************************************
* Function: SPI_RW();
*
* Description:
* Writes one unsigned char to nRF24L01, and return the unsigned char read
* from nRF24L01 during write, according to SPI protocol
**************************************************/
unsigned char SPI_RW(unsigned char Byte)
{
unsigned char i;
for(i=0;i<8;i++) // output 8-bit
{
if(Byte&0x80)
{
digitalWrite(MOSI, 1); // output 'unsigned char', MSB to MOSI
}
else
{
digitalWrite(MOSI, 0);
}
digitalWrite(SCK, 1); // Set SCK high..
Byte <<= 1; // shift next bit into MSB..
if(digitalRead(MISO) == 1)
{
Byte |= 1; // capture current MISO bit
}
digitalWrite(SCK, 0); // ..then set SCK low again
}
return(Byte); // return read unsigned char
}
/**************************************************/

/**************************************************
* Function: SPI_RW_Reg();
*
* Description:
* Writes value 'value' to register 'reg'
/**************************************************/
unsigned char SPI_RW_Reg(unsigned char reg, unsigned char value)
{
unsigned char status;

digitalWrite(CSN, 0); // CSN low, init SPI transaction
status = SPI_RW(reg); // select register
SPI_RW(value); // ..and write value to it..
digitalWrite(CSN, 1); // CSN high again

return(status); // return nRF24L01 status unsigned char
}
/**************************************************/

/**************************************************
* Function: SPI_Read();
*
* Description:
* Read one unsigned char from nRF24L01 register, 'reg'
/**************************************************/
unsigned char SPI_Read(unsigned char reg)
{
unsigned char reg_val;

digitalWrite(CSN, 0); // CSN low, initialize SPI communication...
SPI_RW(reg); // Select register to read from..
reg_val = SPI_RW(0); // ..then read register value
digitalWrite(CSN, 1); // CSN high, terminate SPI communication

return(reg_val); // return register value
}
/**************************************************/

/**************************************************
* Function: SPI_Read_Buf();
*
* Description:
* Reads 'unsigned chars' #of unsigned chars from register 'reg'
* Typically used to read RX payload, Rx/Tx address
/**************************************************/
unsigned char SPI_Read_Buf(unsigned char reg, unsigned char *pBuf, unsigned char bytes)
{
unsigned char status,i;

digitalWrite(CSN, 0); // Set CSN low, init SPI tranaction
status = SPI_RW(reg); // Select register to write to and read status unsigned char

for(i=0;i<bytes;i++)
{
pBuf[i] = SPI_RW(0); // Perform SPI_RW to read unsigned char from nRF24L01
}

digitalWrite(CSN, 1); // Set CSN high again

return(status); // return nRF24L01 status unsigned char
}
/**************************************************/

/**************************************************
* Function: SPI_Write_Buf();
*
* Description:
* Writes contents of buffer '*pBuf' to nRF24L01
* Typically used to write TX payload, Rx/Tx address
/**************************************************/
unsigned char SPI_Write_Buf(unsigned char reg, unsigned char *pBuf, unsigned char bytes)
{
unsigned char status,i;

digitalWrite(CSN, 0); // Set CSN low, init SPI tranaction
status = SPI_RW(reg); // Select register to write to and read status unsigned char
for(i=0;i<bytes; i++) // then write all unsigned char in buffer(*pBuf)
{
SPI_RW(*pBuf++);
}
digitalWrite(CSN, 1); // Set CSN high again
return(status); // return nRF24L01 status unsigned char
}
/**************************************************/

/**************************************************
* Function: RX_Mode();
*
* Description:
* This function initializes one nRF24L01 device to
* RX Mode, set RX address, writes RX payload width,
* select RF channel, datarate & LNA HCURR.
* After init, CE is toggled high, which means that
* this device is now ready to receive a datapacket.
/**************************************************/
void RX_Mode(void)
{
digitalWrite(CE, 0);
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // Use the same address on the RX device as the TX device
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01); // Enable Auto.Ack:Pipe0
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);// Enable Pipe0
SPI_RW_Reg(WRITE_REG + RF_CH, 40); // Select RF channel 40
SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); // Select same RX payload width as TX Payload width
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x07); // TX_PWR:0dBm, Datarate:2Mbps, LNA:HCURR
SPI_RW_Reg(WRITE_REG + CONFIG, 0x0f); // Set PWR_UP bit, enable CRC(2 unsigned chars) & Prim:RX. RX_DR enabled..
digitalWrite(CE, 1); // Set CE pin high to enable RX device
//This device is now ready to receive one packet of 16 unsigned chars payload from a TX device sending to address
//'3443101001', with auto acknowledgment, retransmit count of 10, RF channel 40 and datarate = 2Mbps.
}
/**************************************************/
把程序分别烧进2块板子后,把发射端接一个9V的电源,接收端用USB连电脑,打开Arduino IDE 的串口监视器,就可以看到运行的结果:

捕获.PNG

2012-6-16 14:59 上传
(98.01 KB)


via - 极客工坊

标签: Arduino教程