2.4g无线跳频(三)

2.4g无线跳频(三)
一、跳频过程分析
1.主从建立连接,开启定时器。
2.对于主机,每个定时周期内,前部分处于发送模式,后部分处于接收模式;
   对于从机,每个定时周期内,前部分处于接收模式,后部分处于发送模式;发送时间应安排小于接收时间;
3.主机发送数据后,在规定的时间后转换为接收模式;从机接收到数据后马上调整自身时间,以达到同步的目的;
   主机发送数据的时间要求准时,因为从机接收到信息后会马上调整定时器的计数,同步从机与主机的时间;
4.定时时间一到便开始跳频,注意设法让接收方先于发送方跳。
   跳频示意图:


  带序列的跳频示意图:

二、代码

#define TIMXCNT TIM3->CNT
#define NRF_CH_SIZE 32      //频道数目
typedef struct 
{
    u8 rsq[NRF_CH_SIZE];   //序列
    u32 seed ;  //随机种子
    u32 rsqval; //当前序列值
} _rsq_st ;         //与随机序列有关的变量
_rsq_st rsq_st;
 
 
u8 semflag=0;      //全局标志变量,用于同步线程
u8 print_flag=0;   //用于串口打印输出的标志变量
/*字节对齐,方便读写*/
#pragma pack(push)
#pragma pack(4)
u8 tmp_Tbuf[NRF_CH_SIZE]; 
u8 tmp_Rbuf[NRF_CH_SIZE];  
#pragma pack(pop)
 
u8 pdatas[255]={0}; //用于打印测试
 
TIM3_Int_Init(50000-1 ,72-1 );  // 定时arr=50000 

#ifdef NRF24LXX_MASTER       //主机代码
void TIM3_IRQHandler(void)   //TIM3中断
{
            static u8 i=0 ;
            if ( TIM_GetITStatus( TIM3, TIM_IT_Update) != RESET)    //检查中断源 
        {
            TIM_ClearITPendingBit( TIM3, TIM_IT_Update  );  //清除TIMx的中断待处理位
 
 
            if( NRF_CH_SIZE == i)  //序列周期到了
            {
                i=0;  
                revflag=1;
                rsq_st.seed = *(u32*)(tmp_Rbuf+4) ;   //接收种子 
                BuildRandomSequence( rsq_st.rsq, NRF_CH_SIZE, rsq_st.seed);//利用种子生成特定序列
            }
            
            rsq_st.rsqval = rsq_st.rsq[i];
            tmp_Tbuf[0] = i+'@';
            tmp_Tbuf[1] = i+'@';
            semflag = 0;//  
            i++;     
        }
}
#else  //从机代码
void TIM3_IRQHandler(void)   
{
    static u8 i=0  ;
    if (TIM_GetITStatus( TIM3, TIM_IT_Update) != RESET)  
    {
       TIM_ClearITPendingBit( TIM3, TIM_IT_Update  );   
        
          if( NRF_CH_SIZE == i )
            {
                i=0;
                revflag=1;
                BuildRandomSequence( rsq_st.rsq, NRF_CH_SIZE, rsq_st.seed);//利用种子生成特定序列
            }
            
            NRF24L01_SET_rfch( rsq_st.rsq[i] ) ;  //根据序列跳频
            NRF24L01_TX_Mode(1); 
            tmp_Tbuf[0] = i+'@'; //改变其中一个发射值
            tmp_Tbuf[1] = i+'@'; //改变其中一个发射值
            NRF24L01_TxPacket( tmp_Tbuf);
            semflag = 0;  
            i++;        
    }
}
#endif
 
 
/*生成随机种子并装载至发生内存*/
u32 mySequence()
{
    rsq_st.seed = get_random();//随机种子
    *(u32*)(tmp_Tbuf+4) = rsq_st.seed;
    return rsq_st.seed;

# ifdef NRF24LXX_MASTER    //主机代码
                static u8 i=0;
        NRF24L01_RX_Mode(1);//接收模式,开启自动应答
        BuildRandomSequence( rsq_st.rsq, NRF_CH_SIZE, rsq_st.seed);//利用种子生成特定序列
        while(1)
        {        
          switch( semflag)
            {
                case 0:                         
                    NRF24L01_SET_rfch( rsq_st.rsqval ) ;  //根据序列跳频
                    NRF24L01_RX_Mode(1);  
                    semflag++;
                break ;
                case 1:
                    if( print_flag )//打印数据
                       {
                        print_flag=0;
                        fz+= i;fm+=NRF_CH_SIZE;
                        printf (" %d:%d:%.4f:", temp, i, fz/ fm);
                        pdatas[ i]='\r',pdatas[ i+1]='\n';
                        myUSART_Sendarr( USART1, pdatas  , i+2) ;
                        i=0; 
                        }
                    semflag++;
                break ;
                case 2:
                    if( TIMXCNT <30000)
                       {    
                        if(NRF24L01_RxPacket( tmp_Rbuf)==0)//接收到信息 
                        {
                            temp= TIM3->CNT ;
                            TIM3->CNT=1800 ;
                            pdatas[ i]= tmp_Rbuf[0];
                            i++;    
                        }
                    }
                    else 
                    semflag++;
                break ;
                case 3:
                    NRF24L01_TX_Mode(1);  //发送模式,开启自动应答自动从发  
                        semflag++;
                break ;
                case 4:
                     NRF24L01_TxPacket( tmp_Tbuf);
                         if( semflag==4) semflag++;
                         mySequence();//生成随机种子并装载发送内存,为下一周期准备
                break ;
                        case 5:     
                break ;
            }                   
        }    
    }
#else  //从机代码
    {                    
        static u16 temp ;
        static u8 i=0;
 
 
        NRF24L01_TX_Mode(1);//发送模式,开启自动应答自动从发
        mySequence(); //生成随机数并装载发送内存,为下周期准备
        while(1)
        {
            if( TIMXCNT >20000) //时间到了开始接收模式
            {
               if( semflag == 0) 
                 { 
                    NRF24L01_RX_Mode(1);  //接收模式,开启自动应答
                    semflag++;  
                 }
                 else if(TIMXCNT <49500)
                 {
                     if(NRF24L01_RxPacket( tmp_Rbuf)==0) //接收到信息 
                    {
                        temp=TIM3->CNT ;       //用于观察计数器
                        pdatas[i]= tmp_Rbuf[0];//取第一个数装载至pdatas ,用来测试
                        i++;    
                    }                         
                 }
            }
                
            if( print_flag )  //打印数据
            {    
                print_flag=0;
                fz+= i;fm+= NRF_CH_SIZE;
                printf ("%d:%d:%.4f:", temp, i, fz/ fm);//串口打印
                pdatas[i]='\r',pdatas[i+1]='\n';
                myUSART_Sendarr( USART1, pdatas, i+2); //串口打印数组
                i=0;
            }            
        };
    }
#endif 

以上代码,注意主函数进程与定时器中断服务进程之间的同步,绝不要让两个进程同时访问相同的硬件(这里是无线IC)。

三、验证

两个模块,串口接收如下;

注意第一个数据是各自接收到数据时的定时器读数,而后面1.0000代表丢失率为0,数据接收质量还不错。

————————————————
版权声明:本文为CSDN博主「林子xxx」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wangzibigan/article/details/77510187

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值