打印
[应用方案]

nRF24L01一对六通信

[复制链接]
1180|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
cowboy2014|  楼主 | 2016-4-26 11:21 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

nRF24L01是NORDIC公司生产的一款无线通信芯片,采用FSK调制,内部集成NORDIC自己的Enhanced ShortBurst协议。可以实现点对点或者是1对6的无线通信。无线通信速度可以达到2Mbps。

但是具体如何实现一对六通信,芯片手册中也只是简单的介绍只要6路数据通道的发送地址和接收地址匹配即可。但是如何匹配并没有给出明确的说明。这就产生了一个问题。对于0和1通道,接收端和发送端的地址是可以都写成5个字节的地址,当然可以两端是同样的地址,很容易就实现了通信;但是对于2、3、4、5通道,接收端的地址只有低字节可以设置,发送端的发送地址却是5个字节的。如何相同是个问题。

查找网络上有很多人分享的程序,虽然他们说着是1对6的程序,但是下载下来试了2~5通道都不能用,其中包括广为流传的Bluebird的程序也是不能用的。FLY2000开发板的技术部人员说不能实现一对六,他们只做过点对点;迅通科技的工程师说需要组网和跳频才能实现。我只能说我很无语。

通过求教他人和仔细阅读数据手册,最后把一对六调通了,其中也遇到了一个小问题,就是如何判断接收数据通道号的问题。芯片的状态寄存器STATUS,其中RX_P_NO这三位就是代表了接收数据通道号,在我们读这个寄存器的值得时候却一直出现0x0E这个值,数据明明是接收到了,这个值却是错了,下面也会给出原因和解决方法。

下面想把已经调试通过的NRF24L01一对六的程序写出来,但是eeeeeee额,不知道为么,最重要的地址部分一提交博文就看不到了,难道内容**??那我只能把需要注意的点提出来:

接收部分的地址设置:

uchar code TX_ADDRESS[TX_ADR_WIDTH] = {0x78,0x78,0x78,0x78,0x78}; // 本地地址  

uchar code RX_ADDRESS0[TX_ADR_WIDTH] = {0x78,0x78,0x78,0x78,0x78};//写地址寄存器是先写低字节,因此后面几个字节相同

uchar code RX_ADDRESS1[TX_ADR_WIDTH] = {0xF1,0xB6,0xB5,0xB4,0xB3};//写地址寄存器是先写低字节,因此后面几个字节相同
uchar code RX_ADDRESS2[1] = {0xCD};
uchar code RX_ADDRESS3[1] = {0xA3};
uchar code RX_ADDRESS4[1] = {0x0F};
uchar code RX_ADDRESS5[1] = {0x05};



void init_NRF24L01(void)
{
    inerDelay_us(600);
  CE=0;    // chip enable
  CSN=1;   // Spi  disable
  SCK=0;   //
SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);    // 写本地地址
  _nop_();
  _nop_();
  _nop_();
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS0, TX_ADR_WIDTH); // 写接收端0地址
SPI_Write_Buf(WRITE_REG + RX_ADDR_P1, RX_ADDRESS1, TX_ADR_WIDTH); // 写接收端1地址
SPI_Write_Buf(WRITE_REG + RX_ADDR_P2, RX_ADDRESS2, 1); // 写接收端2地址
SPI_Write_Buf(WRITE_REG + RX_ADDR_P3, RX_ADDRESS3, 1); // 写接收端3地址
SPI_Write_Buf(WRITE_REG + RX_ADDR_P4, RX_ADDRESS4, 1); // 写接收端4地址
SPI_Write_Buf(WRITE_REG + RX_ADDR_P5, RX_ADDRESS5, 1); // 写接收端5地址

SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH);  // 接收通道0选择和发送通道相同有效数据宽度,32字节长度
   SPI_RW_Reg(WRITE_REG + RX_PW_P1, TX_PLOAD_WIDTH);//32字节长度
   SPI_RW_Reg(WRITE_REG + RX_PW_P2, TX_PLOAD_WIDTH);//32字节长度
   SPI_RW_Reg(WRITE_REG + RX_PW_P3, TX_PLOAD_WIDTH);//32字节长度
   SPI_RW_Reg(WRITE_REG + RX_PW_P4, TX_PLOAD_WIDTH);//32字节长度
   SPI_RW_Reg(WRITE_REG + RX_PW_P5, TX_PLOAD_WIDTH);//32字节长度
  _nop_();
  _nop_();
  _nop_();
SPI_RW_Reg(WRITE_REG + EN_AA, 0x3f);      //  所有通道自动 ACK应答允许
  _nop_();
  _nop_();
  _nop_();
//SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);  //  允许接收地址只有频道0,如果需要多频道可以参考Page21
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x3f);  //使能所有接受通道
     _nop_();
  _nop_();
  _nop_();
SPI_RW_Reg(WRITE_REG + RF_CH, 0);        //   设置信道工作为2.4GHZ,收发必须一致
  _nop_();
  _nop_();
  _nop_();
  
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x0F);    //设置发射速率为1MHZ,发射功率为最大值0dB
CE=1;
}
送端的库函数:因为0和1通道的发送端的发送地址(本地地址)和接收端的P0、P1一样即可,现只给出2通道的例子,剩下的3、4、5通道的设置就和2的类似。
uint const TX_ADDRESS[TX_ADR_WIDTH] = {0xCD,0xB6,0xB5,0xB4,0xB3}; //本地地址
uint const RX_ADDRESS[TX_ADR_WIDTH] = {0xCD,0xB6,0xB5,0xB4,0xB3}; //接收地址

void init_NRF24L01(void)
{
    inerDelay_us(600);
  CE=0;    // chip enable
  CSN=1;   // Spi  disable
  SCK=0;   //
SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);    // 写本地地址
  _nop_();
  _nop_();
  _nop_();
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH);
  _nop_();
  _nop_();
  _nop_();
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);      //  频道0自动 ACK应答允许
  _nop_();
  _nop_();
  _nop_();
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);  //  允许接收地址只有频道0,如果需要多频道可以参考Page21
     _nop_();
  _nop_();
  _nop_();
SPI_RW_Reg(WRITE_REG + RF_CH, 0);        //   设置信道工作为2.4GHZ,收发必须一致
  _nop_();
  _nop_();
  _nop_();
SPI_RW_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //设置接收数据长度,本次设置为32字节
  _nop_();
  _nop_();
  _nop_();
SPI_RW_Reg(WRITE_REG + RF_SETUP, 0x0F);    //设置发射速率为1MHZ,发射功率为最大值0dB
CE=1;
}



沙发
cowboy2014|  楼主 | 2016-4-26 11:21 | 只看该作者
接收主函数:
void main(void)
{
    uchar tf=0;
    init_NRF24L01() ;
    P0=0x00;
    Delay(6000);

while(1)
  {
     SetRX_Mode(); //设定为接收模式
     Delay(1000);
     nRF24L01_RxPacket(RxBuf); //接收数据
     Delay(2000);   
    tf=SPI_RW_Reg(READ_REG + STATUS);
    Sendchar(tf);   //读数据通道号     
  }

发送主函数:
void main(void)
{
    init_NRF24L01();
    P0=0x00;
    Delay(6000);

nRF24L01_TxPacket(TxBuf); // Transmit Tx buffer data
   Delay(2000);
   SPI_RW_Reg(FLUSH_TX,0x00);
   SPI_RW_Reg(WRITE_REG+STATUS,0x7F);//关系着是否能顺利通信和接收端的数据通道号能否正确读出。数据手册中有这么一句话:如果MAX_RX中断产生则必须清除后才能进行通讯。
}

使用特权

评论回复
板凳
wahahaheihei| | 2016-4-26 20:08 | 只看该作者
以前我只用过点到点的通信,这个芯片在好多无线鼠标里用的很多

使用特权

评论回复
地板
bitofnoone| | 2016-4-26 20:41 | 只看该作者
那么收发的时候是如何处理的呢?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

78

主题

821

帖子

5

粉丝