2015.07.28 STC15单片机学习日记--NRF24L01 6通道调试

历尽千辛万苦,失败了无数回……终于把NRF24L01所有通道全调通了。之前调通是1对多,现在多对一也可以啦。在调试过程中,总结了一些经验
总体来看,NRF24L01+模块最麻烦的就是寄存器配置问题了,搞定了各个寄存器的配置,模块就通了。而通道设置也到处是寄存器的身影,一不小心就会通信失败,所以在准备调试NRF24L01前一定要准备好资料。如果失败了,不要着急,一点一点来,排除所有可能的故障,如果人品不错的话,一会就搞定了……(╮(╯▽╰)╭我是没这个运气了……)
我的程序原版是从—— NRF24L01无线模块多机通信单片机程序 上位机+下位机(出处:  51电子论坛)——这里搞的,在此感谢huyun的无私奉献……然后我也来回报一下社会吧……
很多人卡在通道调试这里,那就说说NRF24L01+通道的事情吧,一共有6个通道(数据手册里的pipe),其中通道0最容易了,去网上随便找个程序就搞定,比如我找的这个,连通道1也稍带上了。关键是剩下的那几个,尤其是通道2(2~5是极其相似的),在网上看到了很多人调不通,可是又没有专门的解决办法,只有多对一的通信范例,最后还是不知道问题出在哪。今天我试了一下,确实不易……但是经过大量实验,发现了很多不容易想到问题,都是不能调通的原因。

通道1调试:
发送部分:
通道1其实不只是把通道0程序里有关通道0的部分直接改成通道1的那么简单,别的通道更麻烦一点,这就是很多人调不通的原因。我刚开始也是直接改的,果然失败了……(⊙﹏⊙)b……然后又去看原来的程序,看到发送的数据不论是哪个通道,都装给了通道0的地址,不知道为什么,但是实验证明,确实必须这样……其中TX_ADDR地址要和发送的地址一样。
1.  
2.  SPI_Write_Buf(WRITE_REG + TX_ADDR,(uint8_t*)ADDRn, TX_ADR_WIDTH);//写TX节点地址    
3.  SPI_Write_Buf(WRITE_REG+ RX_ADDR_P0, (uint8_t*)ADDRn, RX_ADR_WIDTH);//设置TX节点地址,主要为了使能ACK        

不论通道是几,其中要改动的只有(uint8_t*)ADDRn这个东西,其实就是对应的通道地址。不要动RX_ADDR_P0。
然后是寄存器配置,原贴里的注释有这么一行:“ 要配置第N个​的通道,前N个通道也必须被配置,要不然配置不成功。”瞬间恍然大悟(⊙ o ⊙ )!,上回太心急,拿了程序就走了……正如原帖代码所示:
 
1.        SPI_Write_Reg(WRITE_REG+ EN_AA, 0x3f); //使能通道所有的自动应答  
2.                SPI_Write_Reg(WRITE_REG+ EN_RXADDR, 0x3f);//使能通道所有的接收地址

这个是发送函数voidNRF24L01_Init_TX(uint8_t*ADDRn)里的一段,作者把所有通道都打开了。其实经过试验,这里的通道 必须把当前配置的通道和它前面的都配置。比如现在是通道1,就要至少使能为0x03,而不能是只打开通道1的0x02。
下面的选择通道n有效数据宽度,实验证明没有用,我一次只发1个字节,宽度设置成32,发过来还是1个字节……所以可以去掉。不过留着也不会出错。

接收部分:
首先经过试验,不设置TX_ADDR和RX_ADDR_P0没出错,所以可以去掉。
但是然后发生了奇怪的问题,经过大量试验,我这里通道1地址设置完了以后还要重新设置低位地址,不然没法调通,不知道为什么。如代码所示:
SPI_Write_Buf(WRITE_REG +RX_ADDR_P1, RX_ADDRESS1, RX_ADR_WIDTH);//设置RX节点地址,主要为了使能ACK               
SPI_Write_Buf(WRITE_REG +RX_ADDR_P1, RX_ADDRESS1,1);    //设置RX节点地址,主要为了使能ACK   
(奇怪的NRF24L01+(O__O"…),然后我想……我删掉的部分可能在别人那里就不一样了……可能。如果最后调不通就把我删掉的加上试试。)
后面的就是很正常的设置了,可以只开对应通道,比如通道1:0x02,对应数据宽度什么的……不用管别的通道怎么样。

通道2~5调试:
发送部分:
和通道1的调试方法一样,注意:
1. 不要动RX_ADDR_P0。
2.配置第N个​的通道,前N个通道也必须被配置。

接收部分:
也和通道1一样……但是需要注意的是数据地址的写入,在定义数据地址的时候,根据数据手册,通道2~5与通道1共用32位地址,只有低8位可以改变且不能一样。如图:
 

天前 上传

所以改通道2~5地址的话只能通过改通道1的,然后写入对应通道低8位地址。数据手册里的RX_ADDR_P1表格里还有一句话: LSByteiswritten first。(先写最低位。)这很重要。所以根据写入字节的程序,地址要定义为:
 
这样,看懂没?除了通道0,只有地址数组的第0个元素在变化。网上很多程序是最后一个元素在变,好像数据手册的表里似的,这样就会导致只有通道0和1能调通,别的不能用。因为通道0和1是40位地址写入的,随便改,但是后面的地址必须只能改低位,如果高低位弄混了,改错了当然就不能调通了。当然我(Copy)的程序是先写第0个元素,如果别人的程序不一样那要另当别论。
知道了顺序以后就好办了,但是要注意写入的时候先写通道1的40位地址,再写所用通道的低8位地址, 但是经过多次试验,那32位不要重复写入,数值一样也不行。这样就OK,程序如下:
SPI_Write_Buf(WRITE_REG + RX_ADDR_P1, RX_ADDRESS1, RX_ADR_WIDTH);//设置RX节点地址,主要为了使能ACK                   
SPI_Write_Buf(WRITE_REG + RX_ADDR_P2, RX_ADDRESS2,1);    //设置RX节点地址,主要为了使能ACK(地址长度只能是1, 不能多写,写一样的值也不行)
然后剩下的就简单了,数据通道和数据宽度该是几就设置几,不用管别的通道。

对,结束了,其实并不难,只是可能有的问题没想到而已……我把原程序重新改了一下,进行了通道变换的封装,输入对应通道就可以在对应通道上点对点通信了,像这样:
void NRF24L01_Init_TX(uchar pipe)//输入通道值
{   
       
       CE=0;
       CSN=1;
       SCK=0;
       
       SPI_Write_Buf(WRITE_REG + TX_ADDR, pipe_add[pipe],TX_ADR_WIDTH);//写TX节点地址
       SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, pipe_add[pipe],RX_ADR_WIDTH); //设置RX节点地址,主要为了使能ACK 
       
       SPI_Write_Reg(WRITE_REG + EN_AA, 0x3F);//使能所有通道自动应答  
       SPI_Write_Reg(WRITE_REG + EN_RXADDR,0x3F);//使能所有通道的接收地址(这两项定义的通道数不得小于当前使用的通道数,奇怪的NRF24L01+(O__O"…))
       SPI_Write_Reg(WRITE_REG + RF_CH,40);//设置RF通道为40   收发必须一致!
       SPI_Write_Reg(WRITE_REG + SETUP_RETR,0xFF);//自动重发 4000+86us   重发15次
       SPI_Write_Reg(WRITE_REG + RF_SETUP, 0x0F);//设置TX发射参数,0db增益,2Mbps,低噪声增益开启 收发必须一致!                 
       SPI_Write_Reg(WRITE_REG + CONFIG, 0x0E); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,发送模式,开启所有中断                         
}



void NRF24L01_Init_RX(uchar pipe)//输入通道值
{   
       
       CE=0;   
       CSN=1;   
       SCK=0;  
       
       if(pipe ==0)               //通道,对应设置40位地址
       {                            
               SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS0,RX_ADR_WIDTH);  //设置RX节点地址,主要为了使能ACK
               SPI_Write_Buf(WRITE_REG + (RX_ADDR_P0+pipe), RX_ADDRESS0+pipe,RX_ADR_WIDTH);  //设置RX节点地址,主要为了使能ACK
       }
       else                               //其他通道,对应设置通道1公共地址和相应8位地址
       {
           SPI_Write_Buf(WRITE_REG + RX_ADDR_P1, RX_ADDRESS1, RX_ADR_WIDTH);//设置RX节点地址,主要为了使能ACK                  
           SPI_Write_Buf(WRITE_REG + (RX_ADDR_P0+pipe), pipe_add[pipe],1); //设置RX节点地址,主要为了使能ACK(地址长度只能是1,不能多写,写一样的值也不行)                       
       }
       
       SPI_Write_Reg(WRITE_REG + EN_AA, 1<<pipe);//使能通道的自动应答
       SPI_Write_Reg(WRITE_REG + EN_RXADDR, 1<<pipe);//使能通道的接收地址  
       SPI_Write_Reg(WRITE_REG + RF_CH, 40);//设置RF通道为40   收发必须一致!
       SPI_Write_Reg(WRITE_REG + (RX_PW_P0+pipe), RX_PLOAD_WIDTH);//选择通道的有效数据宽度
       SPI_Write_Reg(WRITE_REG + RF_SETUP, 0x0F);//设置TX发射参数,0db增益,2Mbps,低噪声增益开启  收发必须一致!
       SPI_Write_Reg(WRITE_REG + CONFIG, 0x0F);//配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断
}
 
亲测通道0~5均可用。如果想多对一通信,只需增加相应通道即可,反正配置方法已经告诉你了,这下没问题了吧。O(∩_∩)O哈哈~。当然,这样做了没问题却还是调不通的朋友可以在论坛里搜索,搜不到就去百度,百度不到可以用雅虎,不行再用谷歌,不行再用搜狗,不行再用360搜索,不行再用好搜,不行再用搜搜,不行再用Bing……要是还不行,可以选择联系我……w(゚Д゚)w。

 


  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值