当前位置:   article > 正文

2.4g无线跳频(三)_2.4g 无线跳频

2.4g 无线跳频

2.4g无线跳频(三)

一、跳频过程分析

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

  带序列的跳频示意图:


二、代码

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

  1. #ifdef NRF24LXX_MASTER       //主机代码
  2. void TIM3_IRQHandler(void)   //TIM3中断
  3. {
  4. static u8 i=0 ;
  5. if ( TIM_GetITStatus( TIM3, TIM_IT_Update) != RESET)    //检查中断源 
  6. {
  7.    TIM_ClearITPendingBit( TIM3, TIM_IT_Update  );  //清除TIMx的中断待处理位
  8. if( NRF_CH_SIZE == i)  //序列周期到了
  9. {
  10. i=0;  
  11. revflag=1;
  12. rsq_st.seed = *(u32*)(tmp_Rbuf+4) ;   //接收种子 
  13. BuildRandomSequence( rsq_st.rsq, NRF_CH_SIZE, rsq_st.seed);//利用种子生成特定序列
  14. }
  15. rsq_st.rsqval = rsq_st.rsq[i];
  16. tmp_Tbuf[0] = i+'@';
  17. tmp_Tbuf[1] = i+'@';
  18. semflag = 0;//  
  19. i++;  
  20. }
  21. }
  22. #else  //从机代码
  23. void TIM3_IRQHandler(void)   
  24. {
  25. static u8 i=0  ;
  26. if (TIM_GetITStatus( TIM3, TIM_IT_Update) != RESET)  
  27. {
  28.   TIM_ClearITPendingBit( TIM3, TIM_IT_Update  );   
  29.  if( NRF_CH_SIZE == i )
  30. {
  31. i=0;
  32. revflag=1;
  33. BuildRandomSequence( rsq_st.rsq, NRF_CH_SIZE, rsq_st.seed);//利用种子生成特定序列
  34. }
  35. NRF24L01_SET_rfch( rsq_st.rsq[i] ) ;  //根据序列跳频
  36. NRF24L01_TX_Mode(1); 
  37. tmp_Tbuf[0] = i+'@'; //改变其中一个发射值
  38. tmp_Tbuf[1] = i+'@'; //改变其中一个发射值
  39. NRF24L01_TxPacket( tmp_Tbuf);
  40. semflag = 0;  
  41. i++;
  42. }
  43. }
  44. #endif
  45. /*生成随机种子并装载至发生内存*/
  46. u32 mySequence()
  47. {
  48. rsq_st.seed = get_random();//随机种子
  49. *(u32*)(tmp_Tbuf+4) = rsq_st.seed;
  50. return rsq_st.seed;
  51. }
  1. # ifdef NRF24LXX_MASTER    //主机代码
  2.         static u8 i=0;
  3. NRF24L01_RX_Mode(1);//接收模式,开启自动应答
  4. BuildRandomSequence( rsq_st.rsq, NRF_CH_SIZE, rsq_st.seed);//利用种子生成特定序列
  5. while(1)
  6. {
  7.  switch( semflag)
  8. {
  9. case 0:
  10. NRF24L01_SET_rfch( rsq_st.rsqval ) ;  //根据序列跳频
  11. NRF24L01_RX_Mode(1);  
  12. semflag++;
  13. break ;
  14. case 1:
  15. if( print_flag )//打印数据
  16.     {
  17. print_flag=0;
  18. fz+= i;fm+=NRF_CH_SIZE;
  19. printf (" %d:%d:%.4f:", temp, i, fz/ fm);
  20. pdatas[ i]='\r',pdatas[ i+1]='\n';
  21. myUSART_Sendarr( USART1, pdatas  , i+2) ;
  22. i=0
  23.     }
  24. semflag++;
  25. break ;
  26. case 2:
  27. if( TIMXCNT <30000)
  28.     {
  29. if(NRF24L01_RxPacket( tmp_Rbuf)==0)//接收到信息 
  30. {
  31. temp= TIM3->CNT ;
  32. TIM3->CNT=1800 ;
  33. pdatas[ i]= tmp_Rbuf[0];
  34. i++;
  35. }
  36. }
  37. else 
  38. semflag++;
  39. break ;
  40. case 3:
  41. NRF24L01_TX_Mode(1);  //发送模式,开启自动应答自动从发  
  42.     semflag++;
  43. break ;
  44. case 4:
  45. NRF24L01_TxPacket( tmp_Tbuf);
  46.     if( semflag==4) semflag++;
  47.     mySequence();//生成随机种子并装载发送内存,为下一周期准备
  48. break ;
  49.         case 5:  
  50. break ;
  51. }  
  52. }
  53. }
  54. #else  //从机代码
  55. {
  56.    static u16 temp ;
  57. static u8 i=0;
  58. NRF24L01_TX_Mode(1);//发送模式,开启自动应答自动从发
  59. mySequence(); //生成随机数并装载发送内存,为下周期准备
  60. while(1)
  61. {
  62. if( TIMXCNT >20000) //时间到了开始接收模式
  63. {
  64.   if( semflag == 0
  65. NRF24L01_RX_Mode(1);  //接收模式,开启自动应答
  66. semflag++;  
  67. }
  68. else if(TIMXCNT <49500)
  69. {
  70. if(NRF24L01_RxPacket( tmp_Rbuf)==0) //接收到信息 
  71. {
  72. temp=TIM3->CNT ;   //用于观察计数器
  73. pdatas[i]= tmp_Rbuf[0];//取第一个数装载至pdatas ,用来测试
  74. i++;
  75. }  
  76. }
  77. }
  78. if( print_flag )  //打印数据
  79. {
  80. print_flag=0;
  81. fz+= i;fm+= NRF_CH_SIZE;
  82. printf ("%d:%d:%.4f:", temp, i, fz/ fm);//串口打印
  83. pdatas[i]='\r',pdatas[i+1]='\n';
  84. myUSART_Sendarr( USART1, pdatas, i+2); //串口打印数组
  85. i=0;
  86. }    
  87. };
  88. }
  89. #endif

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

三、验证

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


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/天景科技苑/article/detail/850021
推荐阅读
相关标签
  

闽ICP备14008679号