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,数据接收质量还不错。


  • 16
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值