剛入手的朋友,對 Z-Stack 非常迷糊的時期,如果能夠跑通幾個例子、看幾個演示,那麼可以大大提高學習興趣;另外如果知道某個例子的大致功能及實現,那麼在去看具體實現過程目的性就非常明確。 首先來看看 TI 究竟有哪些例子: 可以看出其例子是非常豐富的。 GenericApp(設備互相綁定傳送信息-hellow world),Location(定位),SampleApp(設備發送和接收LED燈信息),SimpleApp(溫度和燈開關,和智能家居結合使用的,have Pro
1、GenericApp 實驗說明:首先啓動一個網絡協調器,協調器如果建立網絡成功後,會在 LCD 上顯示該節點爲協調者同時顯示網絡 ID號。然後打開一個終端節點或路由器的電源,此時節點會自動加入網絡。加入網絡成功後,節點會顯示自己的節點類型、網絡地址和父節點的網絡地址。 節點加入網絡成功後,首先把主機模塊的搖桿往右拔一下,然後把要綁定模塊的 RIGHT按一下,如果兩邊的 LED4 都熄滅或是點亮後馬上熄滅,表示綁定成功。綁定成功後,兩個節點就開始相互定時發送數據,並在對方的LCD屏上顯示出來,發送的數據爲”Hello World”。此時如果把相互綁定模塊中的 left 按一下,可以發送 Match Description Request命令,對方則顯示 Match Description Request信息。(以上無線龍手冊提供) 2 關鍵函數分析: 我開始沒搞清楚,功能是個啥 大約瀏覽了下,這個例子似乎還與設備的 所以還決定看看程序來判斷這個例子的功能。 綁定有關係,在key control 描述中發現 //***************** Key control**************************//
SW2: initiates end device binding //–初始化中斷設備綁定
2.1 按建處理程序中發現:
// Initiate an End Device Bind Request for the mandatory endpoi
// Initiate a Match Deion Request (Service Discovery)
if ( AF_DataRequest( &GenericApp_DstAddr, &GenericApp_epDesc,
typedef struct
2、端點描述符:&GenericApp_epDesc |
4、發送數據
數據長度:(byte)osal_strlen( theMessageData ) + 1,
數據載荷: (byte *)&theMessageData,
5、發送 ID:&GenericApp_TransID
6、選項:AF_DISCV_ROUTE
7、發送半徑:AF_DEFAULT_RADIUS
#define AF_DEFAULT_RADIUS DEF_NWK_RADIUS
網絡路由深度,初始化爲: #define DEF_NWK_RADIUS 10
2.3 接收處理函數發現 :
void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt ) ///接收處理函數
{
switch ( pkt->clusterId )
{
case GENERICAPP_CLUSTERID:
// “the” message
// HalLcdWriteScreen( (char*)pkt->cmd.Da
Print8(HAL_LCD_LINE_2,10,” “, 1);
Print8(HAL_LCD_LINE_3,10,” “, 1);
Print8(HAL_LCD_LINE_2,10,(INT8U*)pkt->cmd.Da
Print8(HAL_LCD_LINE_3,16, “WXL Welcome”, 1);
break;
#endif
}
}
接收數據處理函數里居然要通過液晶顯示,本人這裏的液晶暫時沒有移植過來,因爲暫時還不具備那個實力,怪不得看不到發送數據的狀況!這裏本人就自作聰明的把以前 SampleApp 例子裏面的一句話加過來了:
void GenericApp_MessageMSGCB( afIncomingMSGPacket_t *pkt ) //–修改的哦
{
switch ( pkt->clusterId )
{
case GENERICAPP_CLUSTERID:
// “the” message
HalLedBlink( HAL_LED_4, 4, 50, (500) );
HalLcdWriteScreen( (char*)pkt->cmd.Da
#elif defined( WIN32 )
WPRINTSTR( pkt->cmd.Da
#endif
break;
}
}
麼想到啊,這麼一加居然就有反應了!其實這裏很簡單的了,就是接收到數據後閃爍 4 下燈,間隔 0.5S。因爲從:GenericApp_ProcessEvent中有週期性發送函數
2.4 週期性發送函數
if ( events & GENERICAPP_SEND_MSG_EVT )
{
// Send “the” message
GenericApp_SendTheMessage(); //–發送信息
// Setup to send message again
osal_start_timerEx( GenericApp_TaskID,
GENERICAPP_SEND_MSG_EVT,
GENERICAPP_SEND_MSG_TIMEOUT );
// return unprocessed events
return (events ^ GENERICAPP_SEND_MSG_EVT);
}
這裏可以看出,這個例子很明顯僅僅是個發送週期信息的例子。所以 LED4 就週期性的閃爍 4 下,當然是協調器發送,路由器閃爍,路由器發送,協調器閃爍。 該事件是一個用戶事件,不在系統事件內。可以看到調用了發送函數 GenericApp_SendTheMessage();,之後又調用了osal_start_timerEx函數觸發定時發送數據,所以是一個週期發送。 發送了,不一定對方一定能收到,這裏只有匹配描述符的才能接收這個信息。
2.5 再來看看ZDO 響應函數:
void GenericApp_ProcessZDOMsgs( zdoIncomingMsg_t *inMsg )
{
switch ( inMsg->clusterID )
{
case End_Device_Bind_rsp: //–綁定
if ( ZDO_ParseBindRsp( inMsg ) == ZSuccess )
{
// Light LED
HalLedSet( HAL_LED_4, HAL_LED_MODE_ON );
}
else
{
// Flash LED to show failure
HalLedSet ( HAL_LED_4, HAL_LED_MODE_FLASH );
}
#endif
break;
case Match_Desc_rsp: //–描述符匹配
{
ZDO_ActiveEndpointRsp_t *pRsp = ZDO_ParseEPListRsp( inMsg );
if ( pRsp )
{
if ( pRsp->status == ZSuccess && pRsp->cnt )
{
GenericApp_DstAddr.addrMode = (afAddrMode_t)Addr16Bit;
GenericApp_DstAddr.addr.shortAddr = pRsp->nwkAddr;
// Take the first endpoint, Can be changed to search through endpoints
GenericApp_DstAddr.endPoint = pRsp->epList[0];
// Light LED
HalLedSet( HAL_LED_4, HAL_LED_MODE_ON );
}
osal_mem_free( pRsp );
}
}
break;
}
}
這裏兩類事件,主要是針對兩種按鍵操作的響應處理:綁定響應和描述符匹配響應。 可以看到,當綁定成功 G燈點亮,失敗 G燈閃爍。 描述符匹配成功 G燈點亮。此時液晶上也會有顯示。
3. 事件處理函數:
UINT16 GenericApp_ProcessEvent( byte task_id, UINT16 events )
{
afIncomingMSGPacket_t *MSGpkt;
afDataConfirm_t *afDataConfirm;
// Da
byte sentEP;
ZStatus_t sentStatus;
byte sentTransID; // This should match the value sent
if ( events & SYS_EVENT_MSG )
{
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( GenericApp_TaskID );
while ( MSGpkt )
{
switch ( MSGpkt->hdr.event )
{
case ZDO_CB_MSG:
GenericApp_ProcessZDOMsgs( (zdoIncomingMsg_t *)MSGpkt );
break;
case KEY_CHANGE:
GenericApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );
break;
case AF_DA
// This message is received as a confirmation of a da
// The status is of ZStatus_t type [defined in ZComDef.h]
// The message fields are defined in AF.h
afDataConfirm = (afDataConfirm_t *)MSGpkt;
sentEP = afDataConfirm->endpoint;
sentStatus = afDataConfirm->hdr.status;
sentTransID = afDataConfirm->transID;
(void)sentEP;
(void)sentTransID;
// Act
if ( sentStatus != ZSuccess )
{
// The da
}
break;
case AF_INCOMING_MSG_CMD:
GenericApp_MessageMSGCB( MSGpkt );
break;
case ZDO_STATE_CHANGE:
GenericApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
if ( (GenericApp_NwkState == DEV_ZB_COORD)
|| (GenericApp_NwkState == DEV_ROUTER)
|| (GenericApp_NwkState == DEV_END_DEVICE) )
{
// Start sending “the” message in a regular interval.
osal_start_timerEx( GenericApp_TaskID,
GENERICAPP_SEND_MSG_EVT,
GENERICAPP_SEND_MSG_TIMEOUT );
}
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);
}
// Send a message out - This event is generated by a timer
// (setup in GenericApp_Init()).
if ( events & GENERICAPP_SEND_MSG_EVT )
{
// Send “the” message
GenericApp_SendTheMessage();
// Setup to send message again
osal_start_timerEx( GenericApp_TaskID,
GENERICAPP_SEND_MSG_EVT,
GENERICAPP_SEND_MSG_TIMEOUT );
// return unprocessed events
return (events ^ GENERICAPP_SEND_MSG_EVT);
}
// Discard unknown events
return 0;
}
3.1 網絡狀態改變
case ZDO_STATE_CHANGE:
GenericApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
if ( (GenericApp_NwkState == DEV_ZB_COORD)
|| (GenericApp_NwkState == DEV_ROUTER)
|| (GenericApp_NwkState == DEV_END_DEVICE) )
{
// Start sending “the” message in a regular interval.
osal_start_timerEx( GenericApp_TaskID,
GENERICAPP_SEND_MSG_EVT,
GENERICAPP_SEND_MSG_TIMEOUT );
}
break;
一旦網絡設備類型確定,就表示加入網絡成功。那麼就調用了 osal_start_timerEx 函數定期(GENERICAPP_SEND_MSG_TIMEOUT)觸發發送事件,這裏也是週期發送(GENERICAPP_SEND_MSG_EVT)
3.2 ZDO 響應事件
case ZDO_CB_MSG:
GenericApp_ProcessZDOMsgs( (zdoIncomingMsg_t *)MSGpkt );
break;
這裏主要是對鍵盤事件操作後的一個 ZDO層的響應。
3.3 接收信息處理
case AF_INCOMING_MSG_CMD:
GenericApp_MessageMSGCB( MSGpkt );
break;
調用了 GenericApp_MessageMSGCB函數。
總的來說:例子很明顯僅僅是個發送週期信息的例子。所以 LED4 就週期性的閃爍 4 下,當然是協調器發送,路由器閃爍,路由器發送,協調器閃爍(這個是在我改過後的情況)。 這例子裏體現了綁定的概念,應該說是從基本功能上很齊全的一個例子,而且在 ZSTACK 上實現無線網絡數傳,沒有任何多餘的功能。所以該例子是一個典型的 ZSTACK 模板,也就是爲用戶提供了一個通用模板可以通過這個建立自己的應用。關於如何在這個例子上建立、修改成自己的工程和應用項目詳細見文檔: Create New Application For The CC2430DB_F8W-2005-0033_.pdf
我們來看看沒有修改的函數演示現象