点对点通信sppc.docx
《点对点通信sppc.docx》由会员分享,可在线阅读,更多相关《点对点通信sppc.docx(17页珍藏版)》请在冰点文库上搜索。
![点对点通信sppc.docx](https://file1.bingdoc.com/fileroot1/2023-4/29/afb7b99c-533c-4f0b-b613-29b4aeb913f2/afb7b99c-533c-4f0b-b613-29b4aeb913f21.gif)
点对点通信sppc
/******************************************************************************
Filename:
spp.c
Target:
cc2430
Revised:
16/12-2005
Revision:
1.0
******************************************************************************/
#include
#include"cul.h"
#include
//protos
voidrxCallBack(void);/*接收回调函数*/
voidackTimeout(void);/*应答超时函数*/
BOOLackReceived(BYTEsourceAddress);/*应答接收函数*/
voidsendAck(SPP_RX_STRUCT*receivedPacket);/*应答发送函数*/
voidwaitForAck(void);/*等待应答函数*/
staticDMA_DESC*dmaTx; //pointertotheDMAdescriptorfortransmit.
staticDMA_DESC*dmaRx; //pointertotheDMAdescriptorforreceive.
staticBYTEdmaNumberTx=0;//numberindicatingwhichDMAchannelisusedfortransmit.
staticBYTEdmaNumberRx=0;//numberindicatingwhichDMAchannelisusedforreceive.
staticBYTEmyAddress;
volatileBYTEsppRxStatus=0; //spp接收状态
volatileBYTE sppTxStatus=0;//spp发送状态
staticBYTEpAckBuffer[7];
staticSPP_TX_STRUCT*pAckData;
staticvolatileUINT8retransmissionCounter;//重发的次数
staticUINT8ackTimerNumber;
staticFUNCTION*rxCallBackFunction;
//-----------------------------------------------------------------------------
//Seecul.hforadescriptionofthisfunction.
/*
Thisfunctionisusedtosetauser-specifiedcall-backfunction
toberunwhenacorrectpacketaddressedformeisreceived.
*/
//-----------------------------------------------------------------------------
//设置用户指定的回调函数,在接收到一个正确的数据包时运行
//通过这个函数可以用程序来改变正确接收数据包后的动作。
//callBackFunction用户指定的函数
//rxCallBackFunction指向FUNCTION的全局变量指针变量
voidsppSetRxCallBackFunction(FUNCTION*callBackFunction)
{
rxCallBackFunction=callBackFunction;
}//EndssppSetRxCallBackFunction()
//发送应答
//SPP_RX_STRUCT定义在cul.h
//SFR( RFD , 0xD9 ) //RFD:
RFData定义在ioCC2430.h
//myAddress全局变量
//ACKcul.h中宏定义
//ISTXONhal.h中宏定义
//srcAddress源地址
voidsendAck(SPP_RX_STRUCT*receivedPacket)//发送应答函数
{
RFD=SPP_HEADER_AND_FOOTER_LENGTH+SPP_ACK_LENGTH;
RFD=receivedPacket->srcAddress; //源地址
RFD=myAddress; //目的地址
RFD=ACK;
RFD=0;
RFIF&=~IRQ_TXDONE;
ISTXON;//RFST=0xE3;
while(!
(RFIF&IRQ_TXDONE));
return;
}
//------------------------------------------------------------------------------------------------------
//voidrxCallBack(...)
//
// Description:
// ThisfunctioniscalledbytheinterruptroutinewhentheRxDMAchannel
// finishesthedatatransfer.Thereceivedpacket'sdestinationaddress
// ischecked.Ifnotaddressedtothisnode,oriftheCRCvalueisnot
// correct,thepacketiserased.AnACKissentifthepacket
// tellsto.Auserdefinedcallbackfunctionmayisrunifset(set
// withsetRxCallBackFunction())
//在RxDAM 通道完成数据传输后由中断程序调用。
检查接收包掉的目的地址,如果地址不是
//这个节点的,或CRC值是错误的,数据包将被擦除。
如果数据包被告知将发送一个应答。
//一个用户定义的回调函数可以运行如果定义了的话。
// Arguments:
// void
//
// Returnvalue:
// void
//-----------------------------------------------------------------------------
//#define RXFIFOCNT XREG(0xDF53) /* ReceiveFIFOCount定义在ioCC2430.h
//ISFLUSHRX清RXFIFO命令滤波.hal.h命令滤波中定义
//GET_DMA_DEST(dmaRx)hal.h中的宏定义,取得一个DMA通道的目标地址
//staticDMA_DESC*dmaRx指向设备DMA描述符的指针,全局变量.DMA_DESCDMA配置结构。
//*@param SPP_TX_STRUCT* pPacketPointer
// Pointertothestructcontainingthetransferdata.
voidrxCallBack(void)
{
SPP_RX_STRUCT__xdata*receivedPacket;
BYTEres=FALSE;
if(RXFIFOCNT>0)//ReceiveFIFOCount
{
ISFLUSHRX;//清RXFIFO命令滤波
ISFLUSHRX;
}
//Investigatingthereceivedpacket.检验接收数据包
//CheckingthedestinationaddressandthattheCRCisOK.
//ThemessageisACK'edifittellsto.
//CRC:
循环冗余码校验
receivedPacket=(SPP_RX_STRUCT__xdata*)GET_DMA_DEST(dmaRx);//(指针)指向DMA通道目标地址(DMA数据描述结构体)
receivedPacket->payloadLength=receivedPacket->payloadLength-SPP_HEADER_AND_FOOTER_LENGTH;//减去头和尾长度
if((receivedPacket->destAddress==myAddress)||(receivedPacket->destAddress==BROADCAST_ADDRESS))//数据包目的地是本节点地址或广播地址
{
if(receivedPacket->payload[receivedPacket->payloadLength+1]&0x80) //CRC正确,注意前面已经减去头尾长度了
{
if(receivedPacket->flags==ACK)//收到了应答包
{
res=ackReceived(receivedPacket->srcAddress);
}
else //收到普通数据包
{
sppRxStatus=PACKET_RECEIVED; //ssp接收状态=收到数据包
res=TRUE;
if(receivedPacket->flags&DO_ACK) //要求收到后发应答
{
sendAck(receivedPacket); //发应答
}
sppRxStatus=RX_COMPLETE; //ssp接收状态=接收完成
if(rxCallBackFunction)
{
rxCallBackFunction(); //调用用户指定回调函数
}
}
}
}
if(res==FALSE)//函数一开始res=FALSE,如果接收成功则上面程序改变
{ //res值,那这里if()语句就是接收不成功的时候,那接
//下来就清空RXFIFO,重置DMA通道等待接收数据。
ISFLUSHRX; //清RXFIFO
ISFLUSHRX;
//rearmingDMAchannel
DMA_ARM_CHANNEL(dmaNumberRx);
RFIM|=IRQ_SFD;
sppRxStatus=RX_WAIT;//接收等待
}
return;
} //endsrxCallBack
//-----------------------------------------------------------------------------
//voidackTimeout(...)
//
// Description:
// ThisfunctionresendsapacketifitisnotACK'edbytherecipient
// within_ACK_TIMEOUT_m-seconds.Themessageisresent_ACK_RETRIES_times.
// Ifthemessageremainsun-ACK'ed,transmissionisabortedandsppTX
// statusissettoDEST_UNREACHABLE.
//如果没有收到接收器返回的应答,将重新发送数据包
// Arguments:
// void
//
// Returnvalue:
// void
//-----------------------------------------------------------------------------
//TIMER4_RUN()宏函数在hal.h中定义
//#defineACK_RETRIES 3在hal.h中的宏定义常数
voidackTimeout(void)/*(未接收到应答,则在限定次数内重发数据包)*/
{
culTimer4AdmClear(ackTimerNumber);
if(pAckData!
=NULL)//所发送的应答数据包不为空(要应答?
?
?
?
)
{
if(retransmissionCounter {
//Resendingthemessage.
pAckData->flags|=RETRANSMISSION; //数据包标志=重发
TIMER4_RUN(FALSE); //停止定时器4
sppSend(pAckData); //发送数据包pAckData
T4CNT=0; //定时器4计数清零
TIMER4_RUN(TRUE); //定时器4开始运行
retransmissionCounter++; //重发次数加1
}
else //重发次数>=限定次数
{ //Thepackethasbeenresenttoomanytimes.
//Assumingthatthenodeisunreacheble.
pAckData=0;
retransmissionCounter=0;
sppTxStatus=DEST_UNREACHABLE; //ssp发送状态=发送不成功
RFIM&=~IRQ_FIFOP;
}
}
return;
}//endsackTimeout
//-----------------------------------------------------------------------------
//Seecul.hforadescriptionofthisfunction.
//初始化简单的数据包装协议SimplePacketProtocol(SPP)
//从DMA管理器申请两个DMA通道,用于分别从RxFIFO和TxFIFO传输数据。
定时器4
//管理器同样被设置,这个单元用于在数据包发送后接收器在一定时间内没有返回应答时
//产生中断。
无线部分配置为发送,工作在特定的频率,在发送时自动计算和插入和检查CRC值。
/*
*@param UINT32frequency
* ThedesiredRadioFrequencyinkHz.
*@param BYTE address
* Thisnodesaddress.
*/
//-----------------------------------------------------------------------------
BOOLsppInit(UINT32frequency,BYTEaddress)
{
BYTEres=0;
BOOLstatus=TRUE;
sppSetAddress(address);//Thisfunctionchangesthelocaladdress.
//Clearingthestatesofthespp.
sppTxStatus=TX_IDLE; //在cul.hTX和RX状态标志部分宏定义
sppRxStatus=RX_IDLE; //同上
retransmissionCounter=0;
ackTimerNumber=0;
pAckData=0;
//ClearingtheRFinterruptflagsandenablemaskandenablingRFinterrupts
RFIF=0;
RFIM=0;
INT_SETFLAG(INUM_RF,INT_CLR);
INT_ENABLE(INUM_RF,INT_ON);
//Settingthefrequencyandinitialisingtheradio
res=halRfConfig(frequency);//在rfconfig.c
if(res==FALSE)
{
status=FALSE;
}
//SettingthenumberofbytestoasserttheFIFOPflag
IOCFG0=7;
INT_SETFLAG(INUM_RFERR,INT_CLR);
INT_ENABLE(INUM_RFERR,INT_ON);
//FlushingbothTxandRxFiFo.Theflush-RxisissuedtwicetoresettheSFD.
//Calibrating(校准)theradioandturningonRxtoevaluatetheCCA.
//SFD开始帧定界符
SRXON;
SFLUSHTX;
SFLUSHRX;
SFLUSHRX;
STXCALN;
ISSTART;
//Usingthetimer4administratortogenerateinterrupttocheckifamessageisunacked...
culTimer4AdmInit();
//InitialisingtheDMAadministrator
culDmaInit();
//请求一条通道:
TX
//RequestingaDMAchannelfortransmitingdata.Nocallbackfunctionisused.InsteadtheTX_DONE
//interruptisusedtodeterminewhenatransferisfinished.ConfiguringtheDMAchannelfor
//transmit.Thedataaddressandlengthwillbesetpriortoeachspecifictransmission.
dmaTx=culDmaAllocChannel(&dmaNumberTx,0);
if((dmaNumberTx==0)||(dmaNumberTx>4)){
status=FALSE;
}
culDmaToRadio(dmaTx,0,0,FALSE);
//请求一条通道:
RX
//RequestingaDMAchannelforreceivingdata.Givingtheaddressofthecallbackfunction.
//ConfiguringtheDMAchannelforreceive.Thedataaddresswillbesetpriortoeachspecific
//reception.
dmaRx=culDmaAllocChannel(&dmaNumberRx,&rxCallBack);
if((dmaNumberRx==0)||(dmaNumberRx>4)){
status=FALSE;
}
culDmaFromRadio(dmaRx,0,TRUE);
//Makingsurethatnoneofthechannelsarearmed.
DMA_ABORT_CHANNEL(dmaNumberRx);
DMA_ABORT_CHANNEL(dmaNumberTx);
INT_ENABLE(INUM_DMA,INT_ON);
returnstatus;
}//endssppInit
//-----------------------------------------------------------------------------
//Seecul.hforadescriptionofthisfunction.
/*
*@brief
* Thisfunction