OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5282|回复: 12

【求助】NRF2401始终不能实现双向通信,调了好多天也是时灵时不灵,求教各路大神

[复制链接]

1

主题

4

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2018-4-27
在线时间
3 小时
发表于 2018-4-27 20:42:21 | 显示全部楼层 |阅读模式
4金钱
各位大神晚上好,我接触32位单片机刚刚两个月,前几天看原子哥的视频看到无线通信的内容,想自己动手做一个双向通信的小程序,实现上位机对下位机的LED进行控制,同时下位机通过DS18B20温度传感器将温度传递给上位机的功能。但是始终不能如愿,只能实现单向通信,要么就是只能是下位机给上位机温度信号,要么就是上位机给下位机控制信号,但是就是不能同时进行。烦请各路大神帮我看看我的程序哪里有问题,感激不尽 感激不尽!程序都是原子哥的程序。以下是上位机程序:
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "spi.h"
#include "key.h"
#include "24l01.h"
#include "ds18b20.h"

const u8 TEXT_Buffer[]={"Explorer STM32F4 SPI TEST"};
#define SIZE sizeof(TEXT_Buffer)       
u8 tmp_buf[33];               
       
int main(void)
{
        u8 key,mode;
        u8 t=0;       
        short tem;

        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
        delay_init(168);
        uart_init(115200);       
        LED_Init();                               
        LCD_Init();                               
        KEY_Init();                                       
        NRF24L01_Init();       
        DS18B20_Init();

        POINT_COLOR=RED;
        LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");       
        LCD_ShowString(30,70,200,16,16,"NRF24L01 TEST");       
        LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
        LCD_ShowString(30,110,200,16,16,"2014/5/9");
        while(NRF24L01_Check())
        {}
        mode = 1;
while(1)
{
        if(mode == 0)
        {
                NRF24L01_RX_Mode();
                while(NRF24L01_RxPacket(tmp_buf)!=0);               
                                tem = tmp_buf[1];
                                tem<<=8;
                                tem= tem+tmp_buf[2];
                                tem=(double)tem*0.625;
                        LCD_ShowNum(30,190,tem,3,12);
                                tem = tmp_buf[3];
                                tem<<=8;
                                tem= tem+tmp_buf[4];
                                tem=(double)tem*0.625;
                        LCD_ShowNum(70,190,tem,3,12);
                        mode = 1;
                        delay_ms(10);
               
        }       

        if(mode == 1)
        {
                NRF24L01_TX_Mode();
                key = KEY_Scan(1);
                switch(key)
                {
                        case 0 : tmp_buf[0] = 0;break;
                        case 1 : tmp_buf[0] = 1;break;
                        case 2 : tmp_buf[0] = 2;break;
                        case 3 : tmp_buf[0] = 3;break;
                        case 4 : tmp_buf[0] = 4;break;
                }
                while(NRF24L01_TxPacket(tmp_buf)!=TX_OK)
                {
                        LED0 = 0;
                        delay_ms(300);
                        LED0 = 1;
                        delay_ms(300);
                }
                mode  = 0;
                delay_ms(10);
        }       
}

以下是下位机程序:
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "spi.h"
#include "key.h"
#include "24l01.h"
#include "ds18b20.h"



const u8 TEXT_Buffer[]={"Explorer STM32F4 SPI TEST"};
#define SIZE sizeof(TEXT_Buffer)       
u8 tmp_buf[33];               
       
int main(void)
{
        u8 key,mode;
        u8 t=0;       
        short tem;

        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
        delay_init(168);
        uart_init(115200);       
        LED_Init();                                       
        LCD_Init();                                       
        KEY_Init();                               
        NRF24L01_Init();       
        DS18B20_Init();


       

        POINT_COLOR=RED;
        LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");       
        LCD_ShowString(30,70,200,16,16,"NRF24L01 TEST");       
        LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
        LCD_ShowString(30,110,200,16,16,"2014/5/9");
        while(NRF24L01_Check())
        {
        }
        mode  = 1;
while(1)
{
        if(mode ==1)
        {
                NRF24L01_RX_Mode();
                while(NRF24L01_RxPacket(tmp_buf)!=0);
                                switch(tmp_buf[0])
                                {
                                        case 0 : LED0 = 1; LED1 = 1; break;
                                        case 1 : LED0 = 0;  break;
                                        case 2: LED1 = 0;  break;
                                        case 3 : LED0 = 0; LED1 = 0; break;
                                        case 4 : LED0 = 0; LED1 = 0;delay_ms(500); break;
                                }
                                mode = 0;
                                delay_ms(10);       
        }       

        if(mode  == 0)
        {
                NRF24L01_TX_Mode();
                DS18B20_Get_Temp();
                DS18B20_Get_Temp1();
                while(NRF24L01_TxPacket(tmp_buf)!=TX_OK);
               
                        mode = 1;
                delay_ms(10);
               
        }
}       

最佳答案

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

4

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2018-4-27
在线时间
3 小时
 楼主| 发表于 2018-4-27 20:42:22 | 显示全部楼层
回复

使用道具 举报

1

主题

4

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2018-4-27
在线时间
3 小时
 楼主| 发表于 2018-4-27 20:57:57 | 显示全部楼层
我把工程文件传上去方便各位大神看吧,,,真的搞不明白啊

NRF2401.rar

7.97 MB, 下载次数: 521

回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165309
金钱
165309
注册时间
2010-12-1
在线时间
2108 小时
发表于 2018-4-28 01:14:52 | 显示全部楼层
是我们开发板么?
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

1

主题

4

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2018-4-27
在线时间
3 小时
 楼主| 发表于 2018-4-28 01:19:23 来自手机 | 显示全部楼层
正点原子 发表于 2018-4-28 01:14
是我们开发板么?

肯定是的 不是的话也不至于在这里问求助了 能否麻烦您为我简单的写一下两个板子之间的相互通信?只需要两个板子互相按键控制led就好了
回复

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
12
金钱
12
注册时间
2018-7-24
在线时间
3 小时
发表于 2018-8-2 23:22:56 | 显示全部楼层
请问楼主的问题解决了嘛?  我也遇到了这个问题
回复

使用道具 举报

22

主题

203

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
378
金钱
378
注册时间
2017-11-29
在线时间
135 小时
发表于 2018-8-2 23:33:04 | 显示全部楼层
我实现了
回复

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
12
金钱
12
注册时间
2018-7-24
在线时间
3 小时
发表于 2018-8-2 23:58:43 | 显示全部楼层

你好  请问可以分享一下嘛?   如何实现的  我的时灵时不灵
回复

使用道具 举报

22

主题

203

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
378
金钱
378
注册时间
2017-11-29
在线时间
135 小时
发表于 2018-8-3 09:49:55 | 显示全部楼层
下面是双向通信的基本原理和方法,只是说明大体结构,NRF函数是调用原子大哥的,简单容易理解;

#define Recon_Delay_Cnt 2                          //重连延时计数,范围在1~255,值越大重连延时越大;也可以理解为是最大发送接收次数

u8 Tx_Cnt=0;                                                   //发送次数计数
u8 Rx_Cnt=0;                                                   //接收次数计数
u8 NRF24L01_Mode=0;                                           //0表示发送模式,1表示接收模式
u8 tmp_buf_Tx[32],tmp_buf_Rx[32];   //发送接收缓冲数组

NRF24L01_TX_Mode();
while(1)                                                        //NRF24L01工作在一个无限循环体内
{                                                                       
    if(NRF24L01_Mode==0)
        {               
                tmp_buf_Tx[0]=0x11;                                
                if(NRF24L01_TxPacket(tmp_buf_Tx)==TX_OK)
                {                                       
                        Tx_Cnt=0;
                        NRF24L01_Mode=1;
                        NRF24L01_RX_Mode();   //一旦发送成功则变成接收模式;
                }                       
                Tx_Cnt++;
                if(Tx_Cnt==Recon_Delay_Cnt) //如果连续发送Recon_Delay_Cnt次都失败,则切换为接收模式
                {                                                       
                        Tx_Cnt=0;
                        NRF24L01_Mode=1;
                        NRF24L01_RX_Mode();
                }
        }
        else
        {
                if(NRF24L01_RxPacket(tmp_buf_Rx)==0)//一旦接收成功则变成发送模式;
                {
                        Rx_Cnt=0;
                        NRF24L01_Mode=0;
                        NRF24L01_TX_Mode();
                }
                Rx_Cnt++;
                if(Rx_Cnt==Recon_Delay_Cnt)//如果连续接收Recon_Delay_Cnt次都失败,则切换为发送模式
                {
                        Rx_Cnt=0;
                        NRF24L01_Mode=0;
                        NRF24L01_TX_Mode();
                }
        }       
        delay_ms(10);          //延时大发送接收慢,延时小发送接收快,太小了可能影响通信可靠性;
}

说明:测试通过,并且应用到我的小四轴上了;
        测试条件:原子的开发板,一个stm32f103c8t6最小系统;
        测试时利用上面的程序进行如下修改;
                                                                        原子开发板部分:程序和上面的一样;
                                                                        最小系统部分:延时变为delay_ms(2);取消了断线重连功能,因为只有有一端有这个功能就会连接成功;
                                                                        程序如下:
u8 NRF24L01_Mode=1;                                                                       
NRF24L01_RX_Mode();                                                                       
while(1)                                                        //NRF24L01工作在一个无限循环体内
{                                                                       
    if(NRF24L01_Mode==0)
        {               
                tmp_buf_Tx[0]=0x11;                                
                if(NRF24L01_TxPacket(tmp_buf_Tx)==TX_OK)
                {                                       
                        NRF24L01_Mode=1;
                        NRF24L01_RX_Mode();   //一旦发送成功则变成接收模式;
                }                                       
        }
        else
        {
                if(NRF24L01_RxPacket(tmp_buf_Rx)==0)//一旦接收成功则变成发送模式;
                {
                        NRF24L01_Mode=0;
                        NRF24L01_TX_Mode();
                }
        }       
        delay_ms(2);          //延时大发送接收慢,延时小发送接收快,太小了可能影响通信可靠性;
}
原理分析:为方便分析,将第一段程序称为主机,第二段程序称为从机。
首先明白,不过主机还是从机,都有一个共性,就是一旦接收或发送成功则立即切换模式;
区别是,从机只有在接收或发送成功后才切换模式,不然的话会一直处于当前模式下,无法切换;
对于主机来说,从机的这个特性恰好符合主机达到最大发送接收次数的自动模式切换;
到底怎么个符合呢?

下面举例说明:
正常情况下,主机成功发送一个数据包,立即变成接收模式,从机成功接收到数据包,立即变成发送模式;这样就双向通信;
异常情况下,外界干扰,或者本身延时导致时间上的不匹配,可能主机和从机都变成了接收模式,这时数据停止传输,从机的模式无法切换;
但是当主机达到最大接收次数后,则切换为发送模式,此时从机就可以接收数据了;同时变成发送模式也一样的;
回复

使用道具 举报

6

主题

25

帖子

0

精华

初级会员

Rank: 2

积分
116
金钱
116
注册时间
2018-5-17
在线时间
23 小时
发表于 2018-11-1 16:29:11 | 显示全部楼层
wen619 发表于 2018-8-3 09:49
下面是双向通信的基本原理和方法,只是说明大体结构,NRF函数是调用原子大哥的,简单容易理解;

#define ...

大佬 可不可以把LCD的代码去掉改成用串口助手显示 具体应该怎么更改
回复

使用道具 举报

22

主题

203

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
378
金钱
378
注册时间
2017-11-29
在线时间
135 小时
发表于 2018-11-1 21:39:58 | 显示全部楼层
AdamR 发表于 2018-11-1 16:29
大佬 可不可以把LCD的代码去掉改成用串口助手显示 具体应该怎么更改

我贴的代码中没有LCD显示函数啊
回复

使用道具 举报

6

主题

25

帖子

0

精华

初级会员

Rank: 2

积分
116
金钱
116
注册时间
2018-5-17
在线时间
23 小时
发表于 2018-11-2 10:54:04 | 显示全部楼层
wen619 发表于 2018-11-1 21:39
我贴的代码中没有LCD显示函数啊

啊 我看的是原子哥给我的NRF2401的示例代码 大佬 你这个是直接串口助手显示吗
回复

使用道具 举报

0

主题

286

帖子

0

精华

高级会员

Rank: 4

积分
949
金钱
949
注册时间
2018-4-21
在线时间
264 小时
发表于 2018-11-2 14:00:53 来自手机 | 显示全部楼层
谢谢大家的分享
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 21:56

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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