野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 10287|回复: 9

2.4G nRF24L01无线通信

[复制链接]
发表于 2017-8-27 18:27:09 | 显示全部楼层 |阅读模式
火哥,flyleaf哥,各位坛友,最近在调试2.4G nRF24L01无线通信,按照官方提供的程序两个板子已经调通了,主从之间可以正常的收发数据,但是前提就是官方说明中提到的必须先给从机供电,再给主机供电才能正常的通信,现在想做的先给主机供电(主机一直被供电),再给从机供电,完成主从之间的通信,程序流程应该怎么修改??
回复

使用道具 举报

发表于 2017-8-28 09:32:53 | 显示全部楼层
改成用按键发送,按按 键才发送数据,平时一直在接收状态等待
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-8-28 11:34:12 | 显示全部楼层
flyleaf 发表于 2017-8-28 09:32
改成用按键发送,按按 键才发送数据,平时一直在接收状态等待

flyleaf哥,我的应用里不能用按键发送,要让主机自动发送,并且主机一直处于工作状态,当有从机时,从机接收数据,并把收到的数据再发给主机,这样应该怎么解决??
回复 支持 反对

使用道具 举报

发表于 2017-8-28 11:56:47 | 显示全部楼层
13009621840 发表于 2017-8-28 11:34
flyleaf哥,我的应用里不能用按键发送,要让主机自动发送,并且主机一直处于工作状态,当有从机时,从机 ...

那主机就一直发,从机就一直收就好了
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-8-29 15:36:58 | 显示全部楼层
flyleaf 发表于 2017-8-28 11:56
那主机就一直发,从机就一直收就好了

不行啊,我想让从机收到的数据再发给主机,主从机要有收发功能,这该怎么办
回复 支持 反对

使用道具 举报

发表于 2017-8-29 16:14:45 | 显示全部楼层
13009621840 发表于 2017-8-29 15:36
不行啊,我想让从机收到的数据再发给主机,主从机要有收发功能,这该怎么办

主从机的中断接口和自动应答功能要打开,利用好中断信号,使用起来就比较方便了。空闲时从机一直处于接受状态,主机处于发送状态。主机发送数据后等待发送完成中断,主机检测到发送完成信号后随即进入接收状态(未检测到发送完成信号就一直发送数据)。从机接收到主机发送的数据后随即进入发送模式发送数据,从机检测到发送完成信号后随即进入接收模式(整个过程中在有需要的地方加入容错机制)。实测,通讯非常稳定哦,不存在必须那方先后通电的问题。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-8-29 18:52:07 | 显示全部楼层
马贞茂 发表于 2017-8-29 16:14
主从机的中断接口和自动应答功能要打开,利用好中断信号,使用起来就比较方便了。空闲时从机一直处于接受 ...

我的程序里就是按您说的流程走的,主机程序:
        while(1)
                {
                   //主机端 进入自应答发送模式
                 NRF_TX_Mode();                        
                //开始发送数据       
                status = NRF_Tx_Dat(txbuf);                            
                 //判断发送状态
                 switch(status)
                  {
                           case MAX_RT:
                // 主机端 没接收到应答信号,发送次数超过限定值,发送失败。
                                LEDG_ON();        //绿灯                       
                                 break;
       
                          case ERROR:
               //未知原因导致发送失败。
                                LEDR_ON();        //红灯                                  
                                 break;       

                          case TX_DS:
                // 主机端 接收到 从机端 的应答信号,发送成功!
                                LEDB_ON();        //蓝灯                                                 
                                 break;                                                                 
                          }                                  
       
                 //主机端 进入接收模式。       
                NRF_RX_Mode();       
                        //等待接收数据
                status = NRF_Rx_Dat(rxbuf);       
                        //判断接收状态
                        switch(status)
                        {
                         case RX_DR:    //主机端 接收到 从机端 发送的数据为:rxbuf
                                 for(i=0;i<4;i++)
                                {                                               
                                        if(txbuf == rxbuf)
                                        {
                                        count++;
                                        }
                                }
                           if(count>=4)
                                 {
                                  count=0;
                                  LEDB_ON();
                                  Delay_MS(500);
                                  LEDB_OFF();
                                  Delay_MS(500);               
                                 }
                                 else
                                 {
                                  count=0;
                                  LEDR_ON();
                                  Delay_MS(500);
                                  LEDR_OFF();
                                  Delay_MS(500);
                                 }                                        
                                  break;
       
                         case ERROR:      //主机端 未接收任何数据
                                  {
                                  LEDR_ON();
                                  Delay_MS(500);
                                  LEDR_OFF();
                                  Delay_MS(500);
                                 }       
                                  break;                 
                        }
                }

这里面我自己定义了一个数组ceshi[],用来测试主机发给从机,从机接收到数据后再原样发回来,数据和之前的一不一样。用到中断的地方就是您说的发送完成中断和接收完成中断,程序贴在下面:
u8 NRF_Tx_Dat(u8 *txbuf)     //发送数据函数
{
        u8 state;  
         /*ce为低,进入待机模式1*/
        NRF_CE_LOW();
        /*写数据到TX BUF 最大 32个字节*/                                               
   SPI_NRF_WriteBuf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);
      /*CE为高,txbuf非空,发送数据包 */   
         NRF_CE_HIGH();                 
          /*等待发送完成中断 */                           
        while(NRF_Read_IRQ()!=0);                
        /*读取状态寄存器的值 */                              
        state = SPI_NRF_ReadReg(STATUS);
         /*清除TX_DS或MAX_RT中断标志*/                  
        SPI_NRF_WriteReg(NRF_WRITE_REG+STATUS,state);        
        SPI_NRF_WriteReg(FLUSH_TX,NOP);    //清除TX FIFO寄存器
         /*判断中断类型*/   
        if(state&MAX_RT)                     //达到最大重发次数
                         return MAX_RT;
        else if(state&TX_DS)                  //发送完成
                         return TX_DS;
         else                                                  
                        return ERROR;                 //其他原因发送失败
}


u8 NRF_Rx_Dat(u8 *rxbuf)        //接收数据函数
{
        u8 state;
        NRF_CE_HIGH();         //进入接收状态
         /*等待接收中断*/
        while(NRF_Read_IRQ()!=0);        
        NRF_CE_LOW();           //进入待机状态
        /*读取status寄存器的值  */               
        state=SPI_NRF_ReadReg(STATUS);         
        /* 清除中断标志*/      
        SPI_NRF_WriteReg(NRF_WRITE_REG+STATUS,state);
        /*判断是否接收到数据*/
        if(state&RX_DR)                                 //接收到数据
        {
          SPI_NRF_ReadBuf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//读取数据
             SPI_NRF_WriteReg(FLUSH_RX,NOP);          //清除RX FIFO寄存器
          return RX_DR;
        }
        else   
                return ERROR;                    //没收到任何数据
}


是不是在把配置寄存器配置为0x0e,然后下面是从机的程序:
  while(1)
  {                          
        //从机端 进入接收模式
        NRF_RX_Mode();         
        //等待接收数据
        status = NRF_Rx_Dat(rxbuf);
        //判断接收状态
        if(status == RX_DR)
        {
         for(i=0;i<4;i++)
         {       
                 //从机端 接收到 主机端 发送的数据为:rxbuf
                if(ceshi == rxbuf)
                   {
                count++;
                txbuf = rxbuf;
                }
         }
         if(count>=4)
         {
          count=0;
          LEDG_ON(); LEDR_ON();LEDB_ON();
          Delay_MS(500);
          LEDG_OFF(); LEDR_OFF();LEDB_OFF();
          Delay_MS(500);               
         }
         else
         {
          count=0;
          LEDB_ON();
          Delay_MS(500);
          LEDB_OFF();
          Delay_MS(500);
         }                  
   }  
  if( Key_Scan(GPIOB,GPIO_Pin_8) == KEY_ON  )
        {
         LEDG_OFF(); LEDR_OFF();LEDB_OFF();       
        }  
                //从机端 进入自应答发送模式
                  NRF_TX_Mode();
                //不断重发,直至发送成功          
         do
           {           
                status = NRF_Tx_Dat(txbuf);
                }while(status == MAX_RT);
  }

从机端的发送数据函数和接收数据函数和主机端的一样,麻烦您帮我看看我这个问题出在哪,这基本上是野火官方提供的程序,我只是加了一下指示灯和一些简单的判断,如果您方便的话能把您的程序给我发一下吗,2294166974@qq.com,谢谢您

回复 支持 反对

使用道具 举报

发表于 2017-8-29 19:49:30 | 显示全部楼层
本帖最后由 马贞茂 于 2017-8-29 19:53 编辑

这里说明一点,火哥的这个NRF程序注重的是功能的实现,做开发的话还有待优化。
  1. while(1)
  2. {
  3.         //主机端 进入自应答发送模式
  4.         NRF_TX_Mode();                        
  5.         //开始发送数据        
  6.         status = NRF_Tx_Dat(txbuf);                           
  7.         //判断发送状态
  8.         switch(status)
  9.         {
  10.                 case MAX_RT:
  11.                 // 主机端 没接收到应答信号,发送次数超过限定值,发送失败。
  12.                 LEDG_ON();        //绿灯                        
  13.                 break;

  14.                 case ERROR:
  15.                 //未知原因导致发送失败。
  16.                 LEDR_ON();        //红灯                                   
  17.                 break;        

  18.                 case TX_DS:
  19.                 // 主机端 接收到 从机端 的应答信号,发送成功!
  20.                 LEDB_ON();        //蓝灯                                                  
  21.                 break;                                                                  
  22.         }                                   

  23.         //主机端 进入接收模式。        
  24.         NRF_RX_Mode();       //(从以上程序可以看出来,不管主机数据是不是发送成功,都会进入接收模式)
  25.         //等待接收数据
  26.         status = NRF_Rx_Dat(rxbuf);        
  27.         //判断接收状态
  28.         switch(status)
  29.         {
  30.                 case RX_DR:    //主机端 接收到 从机端 发送的数据为:rxbuf
  31.                 for(i=0;i<4;i++)
  32.                 {                                                
  33.                         if(txbuf == rxbuf)
  34.                         {
  35.                         count++;
  36.                         }
  37.                 }
  38.                 if(count>=4)
  39.                 {
  40.                         count=0;
  41.                         LEDB_ON();
  42.                         Delay_MS(500);
  43.                         LEDB_OFF();
  44.                         Delay_MS(500);               
  45.                 }
  46.                 else
  47.                 {
  48.                         count=0;
  49.                         LEDR_ON();
  50.                         Delay_MS(500);
  51.                         LEDR_OFF();
  52.                         Delay_MS(500);
  53.                 }                                         
  54.                 break;

  55.                 case ERROR:      //主机端 未接收任何数据
  56.                 {
  57.                         LEDR_ON();
  58.                         Delay_MS(500);
  59.                         LEDR_OFF();
  60.                         Delay_MS(500);
  61.                 }        
  62.                 break;                  
  63.         }
  64. }

  65. //这里面我自己定义了一个数组ceshi[],用来测试主机发给从机,从机接收到数据后再原样发回来,数据和之前的一不一样。用到中断的地方就是您说的发送完成中断和接收完成中断,程序贴在下面:
  66. u8 NRF_Tx_Dat(u8 *txbuf)     //发送数据函数
  67. {
  68.         u8 state;  
  69.         /*ce为低,进入待机模式1*/
  70.         NRF_CE_LOW();
  71.         /*写数据到TX BUF 最大 32个字节*/                                                
  72.         SPI_NRF_WriteBuf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);
  73.         /*CE为高,txbuf非空,发送数据包 */   
  74.         NRF_CE_HIGH();                  
  75.         /*等待发送完成中断 */                           
  76.         while(NRF_Read_IRQ()!=0);                 
  77.         /*读取状态寄存器的值 */                              
  78.         state = SPI_NRF_ReadReg(STATUS);
  79.         /*清除TX_DS或MAX_RT中断标志*/                  
  80.         SPI_NRF_WriteReg(NRF_WRITE_REG+STATUS,state);         
  81.         SPI_NRF_WriteReg(FLUSH_TX,NOP);    //清除TX FIFO寄存器
  82.         /*判断中断类型*/   
  83.         if(state&MAX_RT)                     //达到最大重发次数
  84.                 return MAX_RT;
  85.         else if(state&TX_DS)                  //发送完成
  86.                 return TX_DS;
  87.         else                                                  
  88.                 return ERROR;                 //其他原因发送失败
  89. }


  90. u8 NRF_Rx_Dat(u8 *rxbuf)        //接收数据函数
  91. {
  92.         u8 state;
  93.         NRF_CE_HIGH();         //进入接收状态
  94.         /*等待接收中断*/
  95.         while(NRF_Read_IRQ()!=0);        //(假如没接收到数据,程序是不是会死在这里?估计你先后上电得问题就出在这里)
  96.         NRF_CE_LOW();           //进入待机状态
  97.         /*读取status寄存器的值  */               
  98.         state=SPI_NRF_ReadReg(STATUS);         
  99.         /* 清除中断标志*/      
  100.         SPI_NRF_WriteReg(NRF_WRITE_REG+STATUS,state);
  101.         /*判断是否接收到数据*/
  102.         if(state&RX_DR)                                 //接收到数据
  103.         {
  104.                 SPI_NRF_ReadBuf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//读取数据
  105.                 SPI_NRF_WriteReg(FLUSH_RX,NOP);          //清除RX FIFO寄存器
  106.                 return RX_DR;
  107.         }
  108.         else   
  109.                 return ERROR;                    //没收到任何数据
  110. }


  111. //是不是在把配置寄存器配置为0x0e,然后下面是从机的程序:
  112. while(1)
  113. {                           
  114.         //从机端 进入接收模式
  115.         NRF_RX_Mode();         
  116.         //等待接收数据
  117.         status = NRF_Rx_Dat(rxbuf);
  118.         //判断接收状态
  119.         if(status == RX_DR)
  120.         {
  121.                 for(i=0;i<4;i++)
  122.                 {        
  123.                 //从机端 接收到 主机端 发送的数据为:rxbuf
  124.                         if(ceshi == rxbuf)       //(这两个不变的数组指针在这里比较四次是什么意思?)
  125.                         {
  126.                                 count++;
  127.                                 txbuf = rxbuf;
  128.                         }
  129.                 }
  130.                 if(count>=4)
  131.                 {
  132.                         count=0;
  133.                         LEDG_ON(); LEDR_ON();LEDB_ON();
  134.                         Delay_MS(500);
  135.                         LEDG_OFF(); LEDR_OFF();LEDB_OFF();
  136.                         Delay_MS(500);               
  137.                 }
  138.                 else
  139.                 {
  140.                         count=0;
  141.                         LEDB_ON();
  142.                         Delay_MS(500);
  143.                         LEDB_OFF();
  144.                         Delay_MS(500);
  145.                 }                  
  146.         }  
  147.         if( Key_Scan(GPIOB,GPIO_Pin_8) == KEY_ON  )
  148.         {
  149.                 LEDG_OFF(); LEDR_OFF();LEDB_OFF();        
  150.         }  
  151.         //从机端 进入自应答发送模式
  152.         NRF_TX_Mode();
  153.         //不断重发,直至发送成功         
  154.         do
  155.         {           
  156.                 status = NRF_Tx_Dat(txbuf);
  157.         }while(status == MAX_RT);
  158. }

  159. /***********分割线************/
  160. 这里贴出我的部分代码,仅供参考,不足的地方欢迎指正。

  161. extern         uint8_t        TX_End_Flag;
  162. void NRF_Tx_Dat(u8 *txbuf)
  163. {
  164.         while(TX_End_Flag);
  165.         SPI_NRF_WriteBuf(WR_TX_PLOAD,txbuf,PLOAD_WIDTH); /*写数据到TX BUF 最大 32个字节*/
  166.         TX_End_Flag=1;                     
  167. }

  168. uint8_t                RX_Buf[32];
  169. uint8_t                TX_End_Flag=0;
  170. void EXTI4_IRQHandler(void)
  171. {
  172.         uint8_t states;
  173.         if((EXTI->PR&EXTI_Line4)==EXTI_Line4)
  174.         {
  175.                 states = SPI_NRF_ReadReg(STATUS);
  176.                 SPI_NRF_WriteReg(NRF_WRITE_REG+STATUS,states);
  177.                 switch(states&0x70)
  178.                 {
  179.                         case RX_DR:                                                                                //接收中断
  180.                                 SPI_NRF_ReadBuf(RD_RX_PLOAD,RX_Buf,PLOAD_WIDTH);
  181.                                 break;
  182.                         case TX_DS:                                                                                //发送中断
  183.                                 TX_End_Flag=0;
  184.                                 break;
  185.                         case MAX_RT:                                                                        //达到最大重发次数中断
  186.                                 SPI_NRF_WriteReg(FLUSH_TX,NOP);
  187.                                 TX_End_Flag=0;
  188.                                 break;
  189.                 }
  190.                 EXTI->PR = EXTI_Line4;
  191.         }
  192. }
复制代码


回复 支持 反对

使用道具 举报

发表于 2017-8-29 19:56:14 | 显示全部楼层
源码不方便给你(商用的)。另外在仔细考虑一下我这句话的意思“主从机的中断接口和自动应答功能要打开,利用好中断信号,使用起来就比较方便了。空闲时从机一直处于接受状态,主机处于发送状态。主机发送数据后等待发送完成中断,主机检测到发送完成信号后随即进入接收状态(未检测到发送完成信号就一直发送数据)。从机接收到主机发送的数据后随即进入发送模式发送数据,从机检测到发送完成信号后随即进入接收模式(整个过程中在有需要的地方加入容错机制)。”
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-8-31 20:49:21 | 显示全部楼层
马贞茂 发表于 2017-8-29 19:56
源码不方便给你(商用的)。另外在仔细考虑一下我这句话的意思“主从机的中断接口和自动应答功能要打开,利 ...

好吧,还是谢谢您
回复 支持 反对

使用道具 举报

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

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2025-1-16 17:06 , Processed in 0.065492 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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