1 实验说明
学习zstack协议栈时,最简单的实验莫过于点对点的实验。而本篇将介绍的点对点实验有只是实现了一个最简单功能:当终端节点加入协调器创建的网络时,其网络状态将发生改变。当终端节点的网络状态改变时,终端节点发送一个数据(AF无线的方式)给协调器节点。协调器节点收到数据后,进行解析,如收到的数据为“LED”则将其板载的LED2置为闪烁状态。
2 协调器节点代码
/*********************************************************************
* INCLUDES
*/
#include "OSAL.h"
#include "AF.h"
#include "ZDApp.h"
#include "ZDObject.h"
#include "ZDProfile.h"
#include "Coordinator.h"
#include "DebugTrace.h"
#include <string.h>
#if !defined( WIN32 )
#include "OnBoard.h"
#endif
/* HAL */
#include "hal_lcd.h"
#include "hal_led.h"
#include "hal_key.h"
#include "hal_uart.h"
此处为若干的头文件定义,没什么特别的,无需交代什么。
/*********************************************************************
* GLOBAL VARIABLES
*/
// This list should be filled with Application specific Cluster IDs.
const cId_t GenericApp_ClusterList[GENERICAPP_MAX_CLUSTERS] =
{
GENERICAPP_CLUSTERID
};
const SimpleDescriptionFormat_t GenericApp_SimpleDesc =
{
GENERICAPP_ENDPOINT, // int Endpoint;
GENERICAPP_PROFID, // uint16 AppProfId[2];
GENERICAPP_DEVICEID, // uint16 AppDeviceId[2];
GENERICAPP_DEVICE_VERSION, // int AppDevVer:4;
GENERICAPP_FLAGS, // int AppFlags:4;
GENERICAPP_MAX_CLUSTERS, // byte AppNumInClusters;
(cId_t *)GenericApp_ClusterList, // byte *pAppInClusterList;
0, // byte AppNumInClusters;
(cId_t *)NULL // byte *pAppInClusterList;
};
// This is the Endpoint/Interface description. It is defined here, but
// filled-in in GenericApp_Init(). Another way to go would be to fill
// in the structure here and make it a "const" (in code space). The
// way it's defined in this sample app it is define in RAM.
endPointDesc_t GenericApp_epDesc;
/*********************************************************************
* EXTERNAL VARIABLES
*/
/*********************************************************************
* EXTERNAL FUNCTIONS
*/
/*********************************************************************
* LOCAL VARIABLES
*/
byte GenericApp_TaskID; // Task ID for internal task/event processing
// This variable will be received when
// GenericApp_Init() is called.
devStates_t GenericApp_NwkState;
byte GenericApp_TransID; // This is the unique message ID (counter)
afAddrType_t GenericApp_DstAddr;
unsigned char uartbuf[128];
以上为各种变量的定义。
/*********************************************************************
* LOCAL FUNCTIONS
*/
static void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pckt );
//static void GenericApp_SendTheMessage( void );
static void rxCB(uint8 port,uint8 event);
以上为
各个函数的定义。
/*********************************************************************
* @fn GenericApp_Init
*
* @brief Initialization function for the Generic App Task.
* This is called during initialization and should contain
* any application specific initialization (ie. hardware
* initialization/setup, table initialization, power up
* notificaiton ... ).
*
* @param task_id - the ID assigned by OSAL. This ID should be
* used to send messages and set timers.
*
* @return none
*/
void GenericApp_Init( uint8 task_id )
{
halUARTCfg_t uartConfig;
GenericApp_TaskID = task_id;
GenericApp_TransID = 0;
// Fill out the endpoint description.
GenericApp_epDesc.endPoint = GENERICAPP_ENDPOINT;
GenericApp_epDesc.task_id = &GenericApp_TaskID;
GenericApp_epDesc.simpleDesc
= (SimpleDescriptionFormat_t *)&GenericApp_SimpleDesc;
GenericApp_epDesc.latencyReq = noLatencyReqs;
// Register the endpoint description with the AF
afRegister( &GenericApp_epDesc );
uartConfig.configured = TRUE;
uartConfig.baudRate = HAL_UART_BR_115200;
uartConfig.flowControl = FALSE;
uartConfig.callBackFunc = rxCB;
HalUARTOpen(0,&uartConfig);
}
Generic App Task初始化函数。
/*********************************************************************
* @fn GenericApp_ProcessEvent
*
* @brief Generic Application Task event processor. This function
* is called to process all events for the task. Events
* include timers, messages and any other user defined events.
*
* @param task_id - The OSAL assigned task ID.
* @param events - events to process. This is a bit map and can
* contain more than one event.
*
* @return none
*/
uint16 GenericApp_ProcessEvent( uint8 task_id, uint16 events )
{
afIncomingMSGPacket_t *MSGpkt;
if ( events & SYS_EVENT_MSG )
{
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );
while ( MSGpkt )
{
switch ( MSGpkt->hdr.event )
{
case AF_INCOMING_MSG_CMD:
GenericApp_MessageMSGCB( MSGpkt );
break;
default:
break;
}
// Release the memory
osal_msg_deallocate( (uint8 *)MSGpkt );
// Next
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );
}
// return unprocessed events
return (events ^ SYS_EVENT_MSG);
}
// Discard unknown events
return 0;
}
Generic Application的事件处理函数。在系统的消息队列中如果收到了接收到无线数据包的消息,则程序将跳转到case AF_INCOMING_MSG_CMD:即调用GenericApp_MessageMSGCB()函数对收到的消息进行处理。
/*********************************************************************
* LOCAL FUNCTIONS
*/
/*********************************************************************
* @fn GenericApp_MessageMSGCB
*
* @brief Data message processor callback. This function processes
* any incoming data - probably from other devices. So, based
* on cluster ID, perform the intended action.
*
* @param none
*
* @return none
*/
static void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{
unsigned char buffer[4] = " ";
switch ( pkt->clusterId )
{
case GENERICAPP_CLUSTERID:
osal_memcpy(buffer,pkt->cmd.Data,3);
if(buffer[0] == 'L' && buffer[1] == 'E' && buffer[2] == 'D')
{
HalLedBlink(HAL_LED_2,0,50,2000);
}
else
{
HalLedSet(HAL_LED_2,HAL_LED_MODE_ON);
}
break;
}
}
GenericApp_MessageMSGCB()函数对收到的消息进行处理为:判断收到的数据是否为“LED”。如果收到的是“LED”则将LED2进行闪烁,如果收到的数据不是“LED”则将LED2置为长亮。
/*********************************************************************
* @fn rxCB
*
* @brief
*
* @param port -
* @param event -
*
* @return
*/
static void rxCB(uint8 port,uint8 event)
{
HalUARTRead(0,uartbuf,16);
if(osal_memcmp(uartbuf,"www.wlwmaker.com",16))
{
HalUARTWrite(0,uartbuf,16);
HalUARTWrite(0,"\n",1);
}
return ;
}
这段代码在本例程中其实没起到作用,rxCB()函数为串口的回调函数。用于串口收到数据后进行的处理工作。至此,协调器的程序到此结束。
3 终端节点代码
const SimpleDescriptionFormat_t GenericApp_SimpleDesc =
{
GENERICAPP_ENDPOINT, // int Endpoint;
GENERICAPP_PROFID, // uint16 AppProfId[2];
GENERICAPP_DEVICEID, // uint16 AppDeviceId[2];
GENERICAPP_DEVICE_VERSION, // int AppDevVer:4;
GENERICAPP_FLAGS, // int AppFlags:4;
0, // byte AppNumInClusters;
(cId_t *)NULL, // byte *pAppInClusterList;
GENERICAPP_MAX_CLUSTERS, // byte AppNumInClusters;
(cId_t *)GenericApp_ClusterList // byte *pAppInClusterList;
};
终端节点的这部分代码与协调器有区别,输入、输出命令簇的设定正好相反。
afAddrType_t GenericApp_DstAddr;
unsigned char uartbuf[128];
这两句代码在
终端节点中去掉。关于串口的操作部分也去掉。
halUARTCfg_t uartConfig;
uartConfig.configured = TRUE;
uartConfig.baudRate = HAL_UART_BR_115200;
uartConfig.flowControl = FALSE;
uartConfig.callBackFunc = rxCB;
HalUARTOpen(0,&uartConfig);
uint16 GenericApp_ProcessEvent( uint8 task_id, uint16 events )
{
afIncomingMSGPacket_t *MSGpkt;
if ( events & SYS_EVENT_MSG )
{
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );
while ( MSGpkt )
{
switch ( MSGpkt->hdr.event )
{
case ZDO_STATE_CHANGE:
GenericApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
if (GenericApp_NwkState == DEV_END_DEVICE)
{
GenericApp_SendTheMessage();
}
break;
default:
break;
}
// Release the memory
osal_msg_deallocate( (uint8 *)MSGpkt );
// Next
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );
}
// return unprocessed events
return (events ^ SYS_EVENT_MSG);
}
// Discard unknown events
return 0;
}
终端节点的事件处理函数与协调器不同,代码如上,在该代码中不涉及无线接收数据包,相反在其网络状态发生变化时发送数据包。调用的函数为GenericApp_SendTheMessage(),其代码为:
/*********************************************************************
* @fn GenericApp_SendTheMessage
*
* @brief Send "the" message.
*
* @param none
*
* @return none
*/
static void GenericApp_SendTheMessage( void )
{
char theMessageData[4] = "LED";
afAddrType_t my_DstAddr;
my_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
my_DstAddr.endPoint = GENERICAPP_ENDPOINT;
my_DstAddr.addr.shortAddr = 0x0000;
if ( AF_DataRequest( &my_DstAddr, &GenericApp_epDesc,
GENERICAPP_CLUSTERID,
(byte)osal_strlen( theMessageData ) + 1,
(byte *)&theMessageData,
&GenericApp_TransID,
AF_DISCV_ROUTE, AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
{
// Successfully requested to be sent.
HalLedBlink(HAL_LED_2,0,50,1000);
}
else
{
// Error occurred in request to send.
}
}
By:霜月孤鸟
2016.1.2