BasicRF简析剖析.docx

上传人:b****6 文档编号:7306186 上传时间:2023-01-22 格式:DOCX 页数:11 大小:84.87KB
下载 相关 举报
BasicRF简析剖析.docx_第1页
第1页 / 共11页
BasicRF简析剖析.docx_第2页
第2页 / 共11页
BasicRF简析剖析.docx_第3页
第3页 / 共11页
BasicRF简析剖析.docx_第4页
第4页 / 共11页
BasicRF简析剖析.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

BasicRF简析剖析.docx

《BasicRF简析剖析.docx》由会员分享,可在线阅读,更多相关《BasicRF简析剖析.docx(11页珍藏版)》请在冰豆网上搜索。

BasicRF简析剖析.docx

BasicRF简析剖析

BasicRF简析(四:

appSwitch()简析)

appSwitch()在SI中的函数关系如图1所示,其中basicRfInit()和basicRfSendPacket()两个函数比较有内容的,本文主要针对这两个函数进行展开。

图1

      开始之前先介绍三个比较重要的结构体:

basicRfRxInfo_t、basicRfTxState_t和basicRfPktHdr_t

//接收帧信息

typedefstruct{

   uint8seqNumber;     //帧序号;

   uint16srcAddr;        //源地址;

   uint16srcPanId;      //源节点的PANID;

   int8length;              //帧长度;

   uint8*pPayload;      //该指针指向帧数据即:

净载荷数据;

   uint8ackRequest;    //帧控制域的应答位信息;

   int8rssi;                    //接收信号强度指示;

   volatileuint8isReady; //通过CRC校验,数据接收完成,该标志位进行后续读取操作;

   uint8status;             //待定?

}basicRfRxInfo_t;

//发送状态信息

typedefstruct{

   uint8txSeqNumber;    //帧序号;

   volatileuint8ackReceived;  //ACK是否接收完成;

   uint8receiveOn;         //是否处于接收状态;

   uint32frameCounter;  //发送帧计数;

}basicRfTxState_t;

//BasicRf帧头(IEEE802.15.4)

typedefstruct{

   uint8  packetLength;   //帧长度;

   uint8  fcf0;          //FramecontrolfieldLSB

   uint8  fcf1;          //FramecontrolfieldMSB

   uint8  seqNumber;        //帧序号;

   uint16 panId;               //PANID;

   uint16 destAddr;         //目的地址;

   uint16 srcAddr;            //源地址;

   #ifdefSECURITY_CCM //安全选项;

   uint8  securityControl;

   uint8 frameCounter[4];

   #endif

}basicRfPktHdr_t;

(一) 关于basicRfInit()

/***********************************************************************************

*@fn         basicRfInit

*

*@brief      InitialisebasicRFdatastructures.Setschannel,shortaddressand

*             PANidinthechipandconfiguresinterruptonpacketreception

*              初始化BasicRF数据结构,如:

通道选择、短地址、PANID及接收中断的配置;

*@param      pRfConfig-pointertoBASIC_RF_CONFIGstruct.

*                         Thisstructmustbeallocatedbyhigherlayer

*             txState-filescopevariablethatkeepstxstateinfo    //发送状态信息;

*             rxi-filescopevariableinfoextractedfromthelastincoming

*                   frame                                                                     //最新的所接收帧信息;

*

*@return     none

*/

uint8basicRfInit(basicRfCfg_t*pRfConfig)

{

   if(halRfInit()==FAILED)                      //Rf初始化,启用Rf的推荐简单配置,可选的PA模块配置,始终返回Success;

       returnFAILED;

   halIntOff();                                          //关闭总中断;

   //Settheprotocolconfiguration

   pConfig=pRfConfig;                         //指向相关配置信息;

   rxi.pPayload  =NULL;                      //清空本节点的接收载荷数据;

   txState.receiveOn=TRUE;               //halRfInit()中开启接收;

   txState.frameCounter=0;                 //发送帧计数值;

   txState.txSeqNumber=0x88;            //自行修改第一个发送帧序号初始值;

   //Setchannel

   halRfSetChannel(pConfig->channel);   //将定义的通道号写入相关寄存器;

   //WritetheshortaddressandthePANIDtotheCC2520RAM

   halRfSetShortAddr(pConfig->myAddr); //将定义的本节点地址写入相关寄存器;

                                                                   //#defineSHORT_ADDR0    XREG(0x6174)

                                                                  //#defineSHORT_ADDR1    XREG(0x6175)

   halRfSetPanId(pConfig->panId);            //将定义的PANID写入相关寄存器;

                                                                  //#definePAN_ID0        XREG(0x6172)

                                                                  //#definePAN_ID1        XREG(0x6173)

   //ifsecurityisenabled,writekeyandnonce

   #ifdefSECURITY_CCM

   basicRfSecurityInit(pConfig);

   #endif

   //Setupreceiveinterrupt(receiveddataoracknowlegment)

   halRfRxInterruptConfig(basicRfRxFrmDoneIsr); //对函数指针进行赋值,关联相应的中断函数,即:

声明中断程序;

   halIntOn();                                              //开启总中断;

                                                                  //为什么要开闭总中断一次?

先启用发送节点后启用接收节点时,意外的接收中断?

   returnSUCCESS;

}

      basicRfInit()如上代码所示,该函数仅对RF做简单初始化、通道选择、PANID、本节点地址进行配置,最后为RF接收中断声明一个函数指针basicRfRxFrmDoneIsr;

/***********************************************************************************

*@fn     halRfRxInterruptConfig

*            

*@brief  ConfigureRXinterrupt.

*             //配置接收中断,将RX中断指向一段可执行程序; 

*@param  none

*

*@return none

*/

voidhalRfRxInterruptConfig(ISR_FUNC_PTRpf)

{

   uint8x;

   HAL_INT_LOCK(x);     //保存EA并将其清零;

   pfISR=pf;                    //将函数指针赋值,而pfISR将在RX中断时被执行;

   HAL_INT_UNLOCK(x); //恢复之前EA的值;

}

 

/************************************************************************************

*@fn         rfIsr

*

*@brief      InterruptserviceroutinethathandlesRFPKTDONEinterrupt.

*                  //RX中断服务程序;

*@param      none

*

*@return     none

*/

HAL_ISR_FUNCTION(rfIsr,RF_VECTOR)       

{

   uint8x;

   HAL_INT_LOCK(x);

   if(RFIRQF0&IRQ_RXPKTDONE)

   {

       if(pfISR){

           (*pfISR)();                //ExecutethecustomISR

                                             //如果pfISR不为空则将调用函数指针所指向的函数basicRfRxFrmDoneIsr();

       }

       S1CON=0;                  //CleargeneralRFinterruptflag

       RFIRQF0&=~IRQ_RXPKTDONE;  //ClearRXPKTDONEinterrupt

   }

   HAL_INT_UNLOCK(x);

}

         RF中断采用了宏声明的方式(协议栈中多采用宏来声明中断,而非常规C语言函数),其声明语句如下:

#defineHAL_ISR_FUNC_DECLARATION(f,v)  _PRAGMA(vector=v)__near_func__interruptvoidf(void) //中断函数声明的宏;

#defineHAL_ISR_FUNC_PROTOTYPE(f,v)    _PRAGMA(vector=v)__near_func__interruptvoidf(void)   //中断函数原型的宏;

#defineHAL_ISR_FUNCTION(f,v)         HAL_ISR_FUNC_PROTOTYPE(f,v);HAL_ISR_FUNC_DECLARATION(f,v)//中断函数定义宏,包括

                                                                                                                                                                                 //原型和声明;

其中rfIsr对应于宏中的f(void),类似于指向其自身HAL_ISR_FUNCTION()。

 

(二)关于basicRfSendPacket()

/***********************************************************************************

*@fnbasicRfSendPacket

*

*@briefSendpacket

*

*@paramdestAddr-destinationshortaddress//目的地址;

*pPayload-pointertopayloadbuffer.Thisbuffermustbe

*allocatedbyhigherlayer.//需要MAC层以上产生要发送的数据(指针或数组);

*length-lengthofpayload//要发送数据的长度;

*txState-filescopevariablethatkeepstxstateinfo//发送状态信息;

*mpdu-filescopevariable.Bufferfortheframetosend//对数据进行封包为物理层协议数据单元;

*

*@returnbasicRFStatus_t-SUCCESSorFAILED

*/

uint8basicRfSendPacket(uint16destAddr,uint8*pPayload,uint8length)

{

uint8mpduLength;

uint8status;

//Turnonreceiverifitsnoton

//保证设备处于接收状态,其初始值在halRfInit()中开启接收并在basicRfInit()中被赋值为TRUE;

if(!

txState.receiveOn){

halRfReceiveOn();

}

 

//Checkpacketlength

//取最小的有效数据长度,类似与可变长度域,可变长度值是很有用的例如:

串口透传的数据长度;

//最大数据载荷为

//#defineBASIC_RF_MAX_PAYLOAD_SIZE(127-BASIC_RF_PACKET_OVERHEAD_SIZE-BASIC_RF_AUX_HDR_LENGTH-BASIC_RF_LEN_MIC)

//后面两项为安全选项的附加信息,可根据需要自行调整;

length=min(length,BASIC_RF_MAX_PAYLOAD_SIZE);

 

//Waituntilthetransceiverisidle

//根据SFD和TX_Active状态位来判定设备是否处于空闲状态;

//SFD状态位为0说明设备目前无发送无接收;

halRfWaitTransceiverReady();

 

//TurnoffRXframedoneinterrupttoavoidinterferenceontheSPIinterface

//防止2591冲突?

halRfDisableRxInterrupt();

mpduLength=basicRfBuildMpdu(destAddr,pPayload,length);//根据目的地址、载荷数据及长度信息进行封包;

 

#ifdefSECURITY_CCM

halRfWriteTxBufSecure(txMpdu,mpduLength,length,BASIC_RF_LEN_AUTH,BASIC_RF_SECURITY_M);

txState.frameCounter++;//Incrementframecounterfield

#else

halRfWriteTxBuf(txMpdu,mpduLength);//使用ISFLUSHTX()清空TXFIFO并清除IRQ_TXDONE中断溢出标志位,将MPDU一个字节一个字节的写入RFD;

#endif

 

//TurnonRXframedoneinterruptforACKreception

//仅仅是始能接收中断,为发送完成后自动进入接收模式接收ACK做准备性工作;

//仅作为发送节点且不启用ACK的话,这部分语句都可以省略去;

halRfEnableRxInterrupt();

 

//SendframewithCCA.returnFAILEDifnotsuccessful

//仅仅进行数据发送并没有进行CCA(比较坑爹的注释,事实是自己也没怎么仔细看--!

);

//若发送前进行CCA,需要ISSAMPLECCA再进行ISTXONCCA判断CCA标志位的值进行后续操作;

if(halRfTransmit()!

=SUCCESS){

status=FAILED;

}

 

//Waitfortheacknowledgetobereceived,ifany

//如果启用ACK,则在发送完成后进行进行等待580μs

//实际测试中发送7个字节的数据,两个节点先后发送A和B两个数据帧,两个数据帧的间隔大概需要不小于440μs+580μs+330μs(粗略估计^_^)的时间间隔Sniffer才能捕捉到A的应答帧(这些多出的时间由节点程序准备和结束时间?

)可以确定的是接受节点接收先后两个数据帧的时间间隔要大于580μs,时间间隔太短不能正确接收后一个数据帧,可以通过启用CCA解决这个冲突;

if(pConfig->ackRequest){

txState.ackReceived=FALSE;

//We'llenterRXautomatically,sojustwaituntilwecanbesurethattheackreceptionshouldhavefinished

//Thetimeoutconsistsofa12-symbolturnaroundtime,theackpacketduration,andasmallmargin

halMcuWaitUs((12*BASIC_RF_SYMBOL_DURATION)+(BASIC_RF_ACK_DURATION)+(2*BASIC_RF_SYMBOL_DURATION)+10);

//Ifanacknowledgmenthasbeenreceived(byRxFrmDoneIsr),theackReceivedflagshouldbeset

status=txState.ackReceived?

SUCCESS:

FAILED;

}else{

status=SUCCESS;

}

 

//Turnoffthereceiverifitshouldnotcontinuetobeenabled

//如果不需要继续接收则关闭接收

if(!

txState.receiveOn){

halRfReceiveOff();

}

if(status==SUCCESS){

txState.txSeqNumber++;

}

#ifdefSECURITY_CCM

halRfIncNonceTx();//Incrementnoncevalue

#endif

returnstatus;

}

       根据以上basicRfSendPacket()基本流程:

确保设备处于接收状态→确认数据有效长度→等待设备处于发送空闲状态→构建LEN+MPDU→LEN+MPDU写入TXFIFO→始能接收中断→执行发送选通命令进行数据发送→如果要求有ACK应答,则延时等待ACK→关闭接收状态;另外从上述流程中可以看出,将数据写入TXFIFO并不进行数据的发送,需要通过相关的选通命令在启动发送!

       

      其中basicRfSendPacket()调用basicRfBuildMpdu()对上层(通常为应用层)产生的数据进行封包操作,介绍basicRfBuildMpdu()之前简单介绍下802.15.4数据帧结构。

    图2

 

 以数据帧为例:

 MAC的上层产生Payload作为MACPayload,即:

MSDU;

 MPDU=MHR+MACPayload+MFR,即:

PSDU;

 PPDU=SHR+ PHR+MPDU;//PHR+MHR+MACPayload需要写入TXFIFO,SHR和MFR(AUTOCRC=1时)硬件自动完成;

802.15.4数据帧结构简单介绍完毕,更具体的参见802.15.4协议文档,下面恢复正题;

/***********************************************************************************

*@fn         basicRfBuildMpdu

*

*@brief      Buildsmpdu(MACheader+payload)accordingtoIEEE802.15.4

*             frameformat //根据802.15.4协议的帧结构构建MPDU(MAC帧头+净载荷数据,而由于AUTOCRC=1则FCS不必手动

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 小学教育

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1