|
由TI公司开发的ZStack2007是一种比较完善的协议标准,但是它半开源的,这就给我们学习带来了很多不便的地方,
我自己在这一块也是刚入门,所以很多东西我自己也不是很明白,因此不能很系统的对这个进行讲解,
所以只能通过一个例子来介绍下我所知道的一些东西,大家如果觉得有道理就记下,如果感觉不是很对,可以舍弃我的观点,
或与我进行商讨。好了,我们进入SENSOR DEMO这个例子的学习吧。。。
就如很多人介绍的一样,我们从MIAN函数进入。。。。。
在主函数里我们主要了解以下两个函数:
osal_init_system(); 操作系统初始化
osal_start_system(); 进入操作系统
这个大家应该都知道的哈,我就粗略介绍了。。
在 osal_init_system();函数中又有一个函数osalInitTasks();任务初始化函数,在这个函数里
void osalInitTasks( void )
{
uint8 taskID = 0;
tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));
macTaskInit( taskID++ );
nwk_init( taskID++ );
Hal_Init( taskID++ );
#if defined( MT_TASK )
MT_TaskInit( taskID++ );
#endif
APS_Init( taskID++ );
ZDApp_Init( taskID++ );
SAPI_Init( taskID );
}每个层面都对应了一个ID号,这是操作系统所必须的,方便后面的任务实施。
这里了解到这个样子就差不多了,如果追求的太深,反倒搞的自己很晕的。
好,现在我们进入了操作系统了
void osal_start_system( void )
{
#if !defined ( ZBIT ) && !defined ( UBIT )
for(;;) // Forever Loop
#endif
{
uint8 idx = 0;
osalTimeUpdate(); 时间更新,与那个定时设定时间的函数有联系
Hal_ProcessPoll(); // This replaces MT_SerialPoll() and osal_check_timer().
do {
if (tasksEvents[idx]) // Task is highest priority that is ready.
{
break;
}
} while (++idx < tasksCnt);
以上都是查询是否有事件未处理
if (idx < tasksCnt) 若有事件进入下面操作
{
uint16 events;
halIntState_t intState;
HAL_ENTER_CRITICAL_SECTION(intState);
events = tasksEvents[idx];
tasksEvents[idx] = 0; // Clear the Events for this task.
HAL_EXIT_CRITICAL_SECTION(intState);
events = (tasksArr[idx])( idx, events ); 事件在这里被处理了。。。从这里可以对事件进行追踪
HAL_ENTER_CRITICAL_SECTION(intState);
tasksEvents[idx] |= events; // Add back unprocessed events to the current task.
HAL_EXIT_CRITICAL_SECTION(intState);
}
#if defined( POWER_SAVING )
else // Complete pass through all task events with no activity?
{
osal_pwrmgr_powerconserve(); // Put the processor/system into sleep
}
#endif
}
}
操作系统在这里一直查询,是否有事件发生,若有,则进入相应层面的处理函数,
我通过单步调试,发现第一个事件就是网络层的16号事件,由于被屏蔽了,所以无法追踪到具体函数,我感觉应该是组网事件,
还有一个事件是可以确定的,那就是HAL层的按键事件,它在一直扫描按键状态 if (events & HAL_KEY_EVENT) //0x0001
{
#if (defined HAL_KEY) && (HAL_KEY == TRUE)
/* Check for keys */
HalKeyPoll();
/* if interrupt disabled, do next polling */
if (!Hal_KeyIntEnable)
{
osal_start_timerEx( Hal_TaskID, HAL_KEY_EVENT, 100);
}
#endif // HAL_KEY
return events ^ HAL_KEY_EVENT;
}从代码可以看出,这个按键如果采用了中断的话,就是中断触发相应的事件,否则就是由轮询的方式进行检测。
除了这一点确定以外,虽然知道有些事件发生了,但却无法确定其发生的次序,所以我就不好说那个执行的流程了,
根据SENSOR DEMO的说明文档,设置协调器是需要一个UP按键操作,好。。我们就去找到它。。我们就直接找到处理函数了,
至于它是怎么触发的我就不详细介绍了,这个我自己也是一知半解,如果有兴趣的话可以去论坛里面找,有一篇专门讲按键流程的文章,
我只是稍微了解了下,没去深究,这个的处理函数在
if ( keys & HAL_KEY_SW_1 )
{
if ( appState == APP_INIT )
{
// Key 1 starts device as a coordinator
logicalType = ZG_DEVICETYPE_COORDINATOR;
zb_WriteConfiguration(ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType);
// Reset the device with new configuration
zb_SystemReset();
}这就是实现的代码,这个函数主要就是利用了这个函数zb_WriteConfiguration(ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType);
这个函数将设备类型写入到NV中去,据网友介绍,就是一块非易失性存储器,保存设备类型的,论坛也有专门的介绍,自己可以去找到了解下的。
重启以后它就被定性为协调器,以后就靠它组网了,再比较下路由器的操作,可以猜测默认的设备类型是路由器的,
至于是在哪里进行初始化的我就没去仔细找了,终端节点也是直接默认的。到了这一步设备的类型就设置好了。
设置好了设备类型了以后,让我们开始数据传输吧。。首先打开协调器,让它组建网络,
当其稳定下来以后,有个现象就是LED1,LED3常亮,而LED2闪烁,看到了这个现象以后我们就可以开始下一步的操作,
允许绑定,操作是导航键向右,
if ( keys & HAL_KEY_SW_2 )
{
allowBind ^= 1;
if (allowBind)
{
// Turn ON Allow Bind mode infinitly
zb_AllowBind( 0xFF );
HalLedSet( HAL_LED_2, HAL_LED_MODE_ON );
//This node is the gateway node
isGateWay = TRUE;
// Update the display
#if defined ( LCD_SUPPORTED )
HalLcdWriteString( "Gateway Mode", HAL_LCD_LINE_2 );
#endif
}
else
{
// Turn OFF Allow Bind mode infinitly
zb_AllowBind( 0x00 );
HalLedSet( HAL_LED_2, HAL_LED_MODE_OFF );
isGateWay = FALSE;
// Update the display
#if defined ( LCD_SUPPORTED )
HalLcdWriteString( "Collector", HAL_LCD_LINE_2 );
#endif
}
}这是这一步的操作代码,操作成功后小液晶会显示
HalLcdWriteString( "Gateway Mode", HAL_LCD_LINE_2 );
此时你再打开终端节点,那么就会自动地加入网络,建立绑定,最终稳定后的现象是LED1,LED2.LED3快速闪烁,
到了这一步的时候,网络就已经形成了,接下来我们开始传输采集到得信息吧,终端节点导航键向下操作,开始发送报告。!
if ( keys & HAL_KEY_SW_3 )
{
// Start reporting
osal_set_event( sapi_TaskID, MY_REPORT_EVT );
reportState = TRUE;
}这是实现功能的代码,设置了事件
if ( event & MY_REPORT_EVT )
{
if ( appState == APP_REPORT )
{
sendReport();
osal_start_timerEx( sapi_TaskID, MY_REPORT_EVT, myReportPeriod );
}
}事件处理主要由函数sendReport();实现
osal_start_timerEx( sapi_TaskID, MY_REPORT_EVT, myReportPeriod );
这个函数就是设置循环事件,一直都有发送事件需要处理
说到这里应该不需要再继续讲下去了吧,好了,这还只是终端节点采集了信息,然后发送给了协调器而已,接下来我们看看协调器怎么处理这些信息的。。
case AF_INCOMING_MSG_CMD:
pMSGpkt = (afIncomingMSGPacket_t *) pMsg;
SAPI_ReceiveDataIndication( pMSGpkt->srcAddr.addr.shortAddr, pMSGpkt->clusterId,
pMSGpkt->cmd.DataLength, pMSGpkt->cmd.Data);
break;
这是射频模块接受到信息的处理函数。。处理从这里开始
接下来我们进入SAPI_ReceiveDataIndication()看这个函数干了些什么
void SAPI_ReceiveDataIndication( uint16 source, uint16 command, uint16 len, uint8 *pData )
{
#if defined ( MT_SAPI_CB_FUNC )
/* First check if MT has subscribed for this callback. If so , pass it as
a event to MonitorTest and return control to calling function after that */
if ( SAPICB_CHECK( SPI_CB_SAPI_RCV_DATA_IND ) )
{
zb_MTCallbackReceiveDataIndication( source, command, len, pData );
}
else
#endif //MT_SAPI_CB_FUNC
{
#if ( SAPI_CB_FUNC )
zb_ReceiveDataIndication( source, command, len, pData );
#endif
}
}貌似没看到什么有意义的东西啊。。
然后我们继续追踪zb_ReceiveDataIndication()看看它的功能
void zb_ReceiveDataIndication( uint16 source, uint16 command, uint16 len, uint8 *pData )
{
gtwData.parent = BUILD_UINT16(pData[SENSOR_PARENT_OFFSET+ 1], pData[SENSOR_PARENT_OFFSET]);
gtwData.source=source;
gtwData.temp=*pData;
gtwData.voltage=*(pData+1);
// Flash LED 2 once to indicate data reception
HalLedSet ( HAL_LED_2, HAL_LED_MODE_FLASH );
// Update the display
#if defined ( LCD_SUPPORTED )
HalLcdWriteScreen( "Report", "rcvd" );
#endif
// Send gateway report
sendGtwReport(>wData);
}这里就开始有一些处理了,首先这个最明显的就是液晶的显示内容在这里我们可以看到了。。HalLcdWriteScreen( "Report", "rcvd" );
看来我们是追踪对了,,呵呵。。好继续往下查sendGtwReport(>wData); |
评分
-
1
查看全部评分
-
|