找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6896|回复: 6
收起左侧

基于STM32驱动NRF24L01 2.4G模块调试之路

  [复制链接]
ID:235201 发表于 2018-10-19 09:58 | 显示全部楼层 |阅读模式
/*
* 您好,欢迎您来到2.4G调式的世界
* 调式之路是非常艰辛和枯燥的
* 如果你没有一鼓作气的决心和毅力!
* 请不要来调式,时间不会陪您打鱼晒网
*/
双方配置确保一致(地址,数据位长度,通信频率等)
请严格按照资料的发送与接收时间来控制(发送控制时间和接收控制时间)
在模块发送数据或者接收数据时尽量不要被打断(关闭中断)
如果你用的是SWD接口下载调试,那么这里请注意,SWD可能会影响2.4G模块的正常工作。

下面是调试的基本方法:           
24L01是收发双方都需要编程的器件,这就对调试方法产生了一定的要求,如果两块一起调,那么通讯不成功,
根本不知道是发的问题还是收的问题,不好意思的说,我当时也是没理清调试思路才浪费了一下午时间看着模块干瞪眼。

所以正确的调试方法应该是先调试发送方,能保证发送正确,再去调接收,这样就可以有针对性的解决问题。
至于怎么去调发送方,先说下发送方的工作流程:

配置寄存器使芯片工作于发送模式后拉高CE端至少10us
读状态寄存器STATUS
判断是否是发送完成标志位置位
清标志
清数据缓冲

网上的程序我也看过,大多都是成品,发送方发送-等应答-(自动重发)-触发中断。
可是这样的流程就已经把接收方给牵涉进来了,就是说一定要接收方正确收到数据并且回送应答信号之后发送方才能触发中断,
结束一次完整的发送。可是这跟我们的初衷不相符,我们想单独调试发送,完全抛开接收,
这样就要去配置一些参数来取消自动应答,取消自动重发,让发送方达到发出数据就算成功的目的。
SPI_RW_Reg(WRITE_REG + EN_AA, 0x00);        // 失能通道0自动应答
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x00);    // 失能接收通道0
SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x00);  // 失能自动重发
1有了以上这三个配置,发送方的流程就变成了发送-触发中断。这样就抛开了接收方,
可以专心去调试发送,可是怎么样才知道发送是否成功呢,要用到另外两个寄存器,STATUS和FIFO_STATUS。


这样就很清晰了,我们可以通过读取STATUS的值来判断是哪个事件触发了中断,寄存器4、5、6位分别对应自动重发完成中断,
数据发送完成中断,数据接收完成中断。也就是说,在之前的配置下,如果数据成功发送,那么STATUS的值应该为0x2e。
这样就可以作为一个检测标准,另外一个标准可以看FIFO_STATUS寄存器,第5位的描述:发送缓冲器满标志,1为满,0为有可用空间;
第4位的描述:发送缓冲器空标志,1为空,0为有数据;同样可以看到接收缓冲器的对应标志。这样在数据发送成功后,发送寄存器当然应该是空的,
接收缓冲因为在之前已经失能,所以也应该是空,也就是说成功发送之后的FIFO_STATUS寄存器值应该是0x11。
有了这两个检测标准,我们即使不用接收方也可以确定发送方是否成功发送。当发送方调试成功之后,
在程序里让它一直发送,然后我们就可以去调试接收方,思路是一样的,同样说下接收方工作流程先。



配置寄存器使芯片工作于接收模式后拉高CE端至少130us
读状态寄存器STATUS
判断是否是接收完成标志位置位
清标志
读取数据缓冲区的数据
清数据缓冲0先0

然后在初始化配置寄存器的时候要和发送方保持一致,比较重要的是要失能自动应答,使能通道0接收:
SPI_RW_Reg(WRITE_REG + EN_AA, 0x00);        // 失能通道0自动应答
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);    // 接收要使能接收通道0
这样就可以了,接收方就可以进入接收模式去接收数据了,这次的调试就会灵活一些,因为是接收数据,可以在接收方添加一个显示设备把数据直观的显示出来,
去对照看是否正确,当然还可以使用和发送方一样的方法:观察STATUS和FIFO_STATUS的值,对照寄存器描述,接收正确时STATUS的值应该是0x40,
对于FIFO_STATUS的情况就多了些,因为数据宽度的不同也会造成寄存器的值不一样,24L01最大支持32字节宽度,就是说一次通讯最多可以传输32个字节的数据,
在这种情况下,接收成功读数据之前寄存器值应该为0x12,读数据之后就会变成0x11;如果数据宽度定义的小于32字节,那么接收成功读数据之前寄存器值应该为0x10,
读数据之后就会变成0x11。这个看起来挺复杂,其实很清晰,大家可以试着分析下,对照数据手册分析每个位的状态就可以得到结果。

好了,到这里对nRF24L01的调试基本上就算通了,但是要明白这些只是调试方法,最终的产品如果不加上应答和重发的话那么数据的稳定性是很难保证的,
所以在基本的通讯建立之后就要把发送的配置改为:
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);       //使能接收通道0自动应答
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);   // 使能接收通道0
SPI_RW_Reg(WRITE_REG + SETUP_RETR, 0x1a);  // 自动重发10次,间隔500us
接收方的配置也要更改:
SPI_RW_Reg(WRITE_REG + EN_AA, 0x01);        // 失能通道0自动应答
SPI_RW_Reg(WRITE_REG + EN_RXADDR, 0x01);    // 接收要使能接收通道0

这样发送和接收就进入了一个标准状态,发送-等应答-(自动重发)-触发中断;接收-应答-触发中断,一切按部就班,程序里加上自己的应用部分就能实现很多功能了。
B9EC9CF6FF9441C8FB8BBC33CC57A017.png

单片机源程序如下:
  1. /***********************************************************************
  2.   *
  3.         *  @{ 创建时间  2018.10.01
  4.         *  @{ 开发者    xiaoxiao
  5.         *  @{ 功能      2.4G通信
  6.         *
  7. ************************************************************************/
  8. #include "sys.h"
  9. u8 tmp_buf[33] = {10,20,30,40};
  10. int main(void)
  11. {
  12.     JTAG_Set(JTAG_SWD_DISABLE);//关闭JTAG接口
  13.     JTAG_Set(SWD_ENABLE);//开启SWD接口,方便调式程序
  14.     //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
  15.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  16.     LED_Init();                          //初始化与LED连接的硬件接口
  17.     delay_init();            //延时函数初始化
  18.     uart_init(115200);
  19.     printf("\r\n 加载串口完成 \r\n");
  20.     printf("\r\n 这是一个 NRF24L01 无线传输实验 \r\n");
  21.     printf("\r\n 这是无线传输 主机端 的反馈信息\r\n");
  22.     printf("\r\n   正在检测NRF与MCU是否正常连接。。。\r\n");
  23.     NRF24L01_Init();

  24.     if(NRF24L01_Check() == 0)
  25.         printf("\r\n      NRF与MCU连接成功!\r\n");
  26.     else
  27.         printf("\r\n  NRF与MCU连接失败,请重新检查接线。\r\n");


  28.     printf("\r\n 主机端 进入自应答发送模式\r\n");
  29.     while(1)
  30.     {
  31.         if(NRF24L01_Check() == 0)
  32.         {
  33.             printf("\r\n 开始配置为发送模式\r\n");
  34.             TX_Mode();
  35.             printf("\r\n 配置完成\r\n");
  36.             printf("\r\n 开始发送\r\n");
  37.             while(1)
  38.             {
  39.                 switch(NRF24L01_TxPacket(tmp_buf))
  40.                 {
  41.                 case MAX_TX:
  42.                     printf("\r\n 主机端 没接收到应答信号,发送次数超过限定值,发送失败。 \r\n");
  43.                     break;

  44.                 case 0xff:
  45.                     printf("\r\n 未知原因导致发送失败。 \r\n");
  46.                     break;

  47.                 case TX_OK:
  48.                     printf("\r\n 主机端 接收到 从机端 的应答信号,发送成功! %d %d %d %d \r\n",tmp_buf[0],tmp_buf[1],tmp_buf[2],tmp_buf[3]);
  49.                     break;
  50.                 }
  51.                 delay_ms(1000);
  52.                                                                 tmp_buf[0]+=1;
  53.                                                                 tmp_buf[1]+=1;
  54.                                                                 tmp_buf[2]+=1;
  55.                                                                 tmp_buf[3]+=1;
  56.             }
  57.         }
  58.     }
  59. }
复制代码

QQ截图20181019095617.png

所有资料51hei提供下载:
2.4G调式.rar (829.3 KB, 下载次数: 255)
回复

使用道具 举报

ID:412302 发表于 2018-10-20 23:25 | 显示全部楼层
請問有RF433教學??
回复

使用道具 举报

ID:251866 发表于 2019-1-14 02:12 | 显示全部楼层
感谢楼组的贡献!谢谢
回复

使用道具 举报

ID:67425 发表于 2019-6-7 05:59 | 显示全部楼层
很好,感谢楼主分享!
回复

使用道具 举报

ID:648247 发表于 2019-11-24 10:47 | 显示全部楼层
非常好的总结,对我很有帮助
回复

使用道具 举报

ID:696335 发表于 2021-4-18 12:41 | 显示全部楼层
请问nrf和单片机怎么接线呢?
回复

使用道具 举报

ID:865915 发表于 2021-7-31 15:21 | 显示全部楼层
请问发送端一直显示已经达到最大重发次数是什么情况啊
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表