📄 ping_pong.c
字号:
/*
V0.1 Initial Release 10/July/2006
*2006/08/16 WXL 2.0
*/
/*
This is a two node test, requires a Coordinator 这是一个两个节点的测试,需要一个协调器和一个终端设备。
and an RFD. The coordinator and node simply 这个协调器和终端设备来回传送数据包。并且输出信号强度字节。
ping-pong a packet back and forth, and print 在数据返回之前,终端设备处于等待状态。而此时协调器快速反应。
out the RSSI byte. The RFD waits before
bouncing it back, while the coordinator responds
immediately.
Expects coordinator, and one RFD. 如果使用一个协调器和终端设备,那这个拓扑结构必须是由:
The topology to test should be: 协调器 -> 终端设备1
Coordinator -> RFD1
Start the coordinator first, then 先打开协调器,然后打开终端设备1。如果终端设备1加入网络失败,就再次尝试。
RFD1. If a RFD1 fails to join the network, try 终端设备1会提示用户来按一个键位来启动来回传送数据包。
again. The RFD1 will prompt the user to hit
a key to start the ping-pong.
You can connect multiple RFDs if desired. 如果需要,你可以连接多个终端设备。
You can also ping-pong through a router; see 同样,你也可以通过 路由器 来来回传送数据包。请查看usrJoinVerifyCallback()
the note in usrJoinVerifyCallback(). The topology的说明。拓扑结构将是:
for a router would be: 协调器 -> 路由器 -> 终端设备1
-> 终端设备2
coord -> router -> RFD1 -> 终端设备n
-> RFD2
-> ..RFDn
This requires Virtual Boards to be running, 这个试验需要使用开发板因为我们需要用按键来启动数据来回传送试验。
since a switch press is needed to start the pinging.
*/
#include "wx_lrwpan.h"
#ifndef LRWPAN_COORDINATOR
#define PING_DELAY 2 //wait before bouncing back 在反弹之前处于等待状态
#else
#define PING_DELAY 0 //coordinator does not wait 协调器不等待
#endif
#define RX_PING_TIMEOUT 5 //seconds
//this is assumed to be the long address of our coordinator, in little endian order
//used to test LONG ADDRESSING back to coordinator
//这是为协调器定义一个长地址,以短字节结尾是为了用于测试返回到协调器的长地址。
UINT16 ping_cnt;
UINT32 my_timer;
UINT32 last_tx_start;
extern struct UART_BUF
{
UINT8 Buf[12];
UINT8 Counter;
UINT8 NewData;
}Rx;
LADDR_UNION dstADDR;
typedef enum _PP_STATE_ENUM {
PP_STATE_START_RX,
PP_STATE_WAIT_FOR_RX,
PP_STATE_SEND,
PP_STATE_WAIT_FOR_TX
}PP_STATE_ENUM;
PP_STATE_ENUM ppState;
BYTE rxFlag; //set from within usrRxPacketCallback
BYTE payload[2];
UINT16 numTimeouts;
BOOL first_packet;
void PingPong(void);
void PingPong (void ) {
apsFSM();
switch (ppState) {
case PP_STATE_START_RX: // 开始接收状态
if (!first_packet) {
my_timer= halGetMACTimer();
ppState = PP_STATE_WAIT_FOR_RX;
}else if (rxFlag) {
//on first packet, do not start timer, just wait for a packet.
ppState = PP_STATE_WAIT_FOR_RX;
first_packet = FALSE;
}
break;
case PP_STATE_WAIT_FOR_RX:
//rxFlag is set from within usrRxPacketCallback
if (rxFlag || halMACTimerNowDelta(my_timer) > MSECS_TO_MACTICKS( RX_PING_TIMEOUT *1000 )) {
if (!rxFlag) numTimeouts++; //got tired of waiting for a response, send again
rxFlag = 0; //clear flag
if (EVB_LED1_STATE()) EVB_LED1_OFF(); else EVB_LED1_ON();
//start timer
my_timer= halGetMACTimer();
ppState = PP_STATE_SEND;
}
break;
case PP_STATE_SEND:
if ((halMACTimerNowDelta(my_timer))> MSECS_TO_MACTICKS(PING_DELAY*1000)){
MemDump();
//increment ping counter
ping_cnt++; //this was value received by this node
//received packet, ping it back
//format the packet
payload[0] = (BYTE) ping_cnt;
payload[1] = (BYTE) (ping_cnt>>8);
ppState = PP_STATE_WAIT_FOR_TX;
last_tx_start = halGetMACTimer();
aplSendMSG (APS_DSTMODE_SHORT,
&dstADDR,
2, //dst EP
0, //cluster is ignored for direct message
1, //src EP
&payload[0],
2, //msg length
apsGenTSN(),
FALSE); //No APS ack requested
ppState = PP_STATE_WAIT_FOR_TX;
}
break;
case PP_STATE_WAIT_FOR_TX:
if (apsBusy()) break; //status not ready yet if busy.
if (aplGetStatus() == LRWPAN_STATUS_SUCCESS) {
ppState = PP_STATE_START_RX;
//compute the latency of this TX send operation
//aplGetLastTxTime gets the time that the LAST tx operation finished.
//this will be the latency of the TX stack operation only if no mac retries were required
last_tx_start = aplMacTicksToUs(aplGetLastTxTime() - last_tx_start);
conPrintROMString("TX Stack latency(us): ");
conPrintUINT32(last_tx_start);
conPCRLF();
}else {
conPrintROMString("Ping Send failed! Restarting timer to try again\n");
my_timer= halGetMACTimer();
ppState = PP_STATE_SEND;
}
break;
}
}
void main (void){
//this initialization set our SADDR to 0xFFFF,
//这个初始化是设置短地址
//PANID to the default PANID
//HalInit, evbInit will have to be called by the user 由用户手动初始化芯片
UINT8 i;
numTimeouts = 0;
my_timer = 0;
first_packet = TRUE;
halInit(); //硬件初始化
evbInit(); //芯片初始化
aplInit(); //init the stack 协议栈初始化
conPrintConfig(); //设置字符输出。
ENABLE_GLOBAL_INTERRUPT(); //enable interrupts 开全局中断
EVB_LED1_OFF(); //led初始化
EVB_LED2_OFF();
ping_cnt = 0;
rxFlag = 0;
//debug_level = 10;
#ifdef LRWPAN_COORDINATOR //定义为协调器
aplFormNetwork(); //硬件初始化一个新网络
while(apsBusy()) {apsFSM();} //wait for finish apsFSM();//应用层无线数据收发处理
conPrintROMString("Network formed, waiting for RX\n");
EVB_LED1_ON();
ppState = PP_STATE_START_RX; //开始接收数据
#else //如果不是协调器
do {
aplJoinNetwork(); //初始化 加入网络 的函数
while(apsBusy()) {apsFSM();} //wait for finish //如果新网络还没初始化好,继续等待网络初始化。
if (aplGetStatus() == LRWPAN_STATUS_SUCCESS) { //成功加入网络
EVB_LED1_ON();
conPrintROMString("Network Join succeeded!\n");
conPrintROMString("My ShortAddress is: ");
conPrintUINT16(aplGetMyShortAddress());
conPCRLF(); //串口输出换行
conPrintROMString("Parent LADDR: ")
conPrintLADDR(aplGetParentLongAddress()); //获取父节点长地址。
conPrintROMString(", Parent SADDR: ");
conPrintUINT16(aplGetParentShortAddress()); //获取父节点短地址。
conPCRLF(); //串口输出换行
break;
}else {
conPrintROMString("Network Join FAILED! Waiting, then trying again\n");
my_timer= halGetMACTimer(); //等2秒钟
//wait for 2 seconds
while ((halMACTimerNowDelta(my_timer))< MSECS_TO_MACTICKS(2*1000));
}
} while(1);
#endif
#ifdef LRWPAN_RFD //如果是终端节点
//now send packets
dstADDR.saddr = 0; //RFD sends to the coordinator FRD发送数据的目的地址为协调器,短地址。
ppState = PP_STATE_SEND;
conPrintROMString("Hit any switch to start!\n");
while (!(EVB_SW1_PRESSED() || EVB_SW2_PRESSED())) {evbPoll();} //如果SW1 SW2没按下,继续查询等待。
#endif
#if (defined(LRWPAN_RFD) || defined(LRWPAN_COORDINATOR))
//WARNING - this is only for latency testing, max MAC retries is normally
//set to aMaxFrameRetries (value=3) as defined in mac.h. Setting this to 0 means
//that there will be no automatic retransmissions of frames if we do not get a MAC ACK back.
//only do this in your normal code if you want to disable automatic retries
//这段程序是用于默认的测试。MAC尝试次数一般设置为3次(在mac.h通过aMaxFrameRetries()函数设置。)
//如果设置为0意味着如果我们不设置MAC结束返回信号将不会有自动中继帧。
//如果你想禁止自动尝试可以在此设置。
aplSetMacMaxFrameRetries(0);
while (1) {
if(Rx.NewData)
{
for(i=0; i<10; i++)
{
halPutch(Rx.Buf[i]); //输出缓存里的数据
}
halPutch('\n');
Rx.NewData = 0;
}
PingPong();
}
#endif
#ifdef LRWPAN_ROUTER //路由节点。
//router does nothing, just routes 路由节点啥都不做,仅仅是路由功能。
DEBUG_PRINTNEIGHBORS(DBG_INFO);
conPrintROMString("Router, doing its thing.!\n");
while(1) {apsFSM();}
#endif
}
//########## Callbacks ########## 回调信号
//callback for anytime the Zero Endpoint RX handles a command
//user can use the APS functions to access the arguments
//and take additional action is desired.
//the callback occurs after the ZEP has already taken
//its action.
//
LRWPAN_STATUS_ENUM usrZepRxCallback(void){
#ifdef LRWPAN_COORDINATOR
if (aplGetRxCluster() == ZEP_END_DEVICE_ANNOUNCE) {
//a new end device has announced itself, print out the
//the neightbor table and address map
dbgPrintNeighborTable();
}
#endif
return LRWPAN_STATUS_SUCCESS;
}
//callback from APS when packet is received
//user must do something with data as it is freed
//within the stack upon return.
LRWPAN_STATUS_ENUM usrRxPacketCallback(void) {
BYTE len, *ptr;
//just print out this data
conPrintROMString("User Data Packet Received: \n");
conPrintROMString("SrcSADDR: ");
conPrintUINT16(aplGetRxSrcSADDR());
conPrintROMString(", DstEp: ");
conPrintUINT8(aplGetRxDstEp());
conPrintROMString(", Cluster: ");
conPrintUINT8(aplGetRxCluster());
conPrintROMString(", MsgLen: ");
len = aplGetRxMsgLen();
conPrintUINT8(len);
conPrintROMString(",RSSI: ");
conPrintUINT8(aplGetRxRSSI());
conPCRLF();
conPrintROMString("PingCnt: ");
ptr = aplGetRxMsgData();
ping_cnt = *ptr;
ptr++;
ping_cnt += ((UINT16)*ptr)<<8;
conPrintUINT16(ping_cnt);
conPrintROMString(", RxTimeouts: ");
conPrintUINT16(numTimeouts);
rxFlag = 1;//signal that we got a packet
//use this source address as the next destination address
dstADDR.saddr = aplGetRxSrcSADDR();
conPCRLF();
return LRWPAN_STATUS_SUCCESS;
}
#ifdef LRWPAN_FFD
//Callback to user level to see if OK for this node
//to join - implement Access Control Lists here based
//upon IEEE address if desired
BOOL usrJoinVerifyCallback(LADDR *ptr, BYTE capinfo){\
#if 0 //set this to '1' if you want to test through a router
//only accept routers.
//only let routers join us if we are coord
#ifdef LRWPAN_COORDINATOR
if (LRWPAN_GET_CAPINFO_DEVTYPE(capinfo)) {
//this is a router, let it join
conPrintROMString("Accepting router\n");
return TRUE;
}else {
conPrintROMString("Rejecting non-router\n");
return FALSE;
}
#else
return TRUE;
#endif
#else
return TRUE;
#endif
}
BOOL usrJoinNotifyCallback(LADDR *ptr){
//allow anybody to join
conPrintROMString("Node joined: ");
conPrintLADDR(ptr);
conPCRLF();
DEBUG_PRINTNEIGHBORS(DBG_INFO);
return TRUE;
}
#endif
//called when the slow timer interrupt occurs
#ifdef LRWPAN_ENABLE_SLOW_TIMER
void usrSlowTimerInt(void ) {}
#endif
//general interrupt callback , when this is called depends on the HAL layer.
void usrIntCallback(void){}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -