加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

zigbee任务的处理流程

发布时间:2020-12-15 18:44:10 所属栏目:百科 来源:网络整理
导读:http://hi.baidu.com/lee112168/item/9bc4db721043dc01d1dcb3f7 zigbee任务的处理流程(一) 1、??添加任务 在协议栈中的OSAL.c文件中,byte osal_init_system( void )函数的功能是初始化OS、添加任务到OS任务表中。在这个函数中通过调用osalAddTasks()函数

http://hi.baidu.com/lee112168/item/9bc4db721043dc01d1dcb3f7

zigbee任务的处理流程(一)

1、??添加任务

在协议栈中的OSAL.c文件中,byte osal_init_system( void )函数的功能是初始化OS、添加任务到OS任务表中。在这个函数中通过调用osalAddTasks()函数来定制项目所需要应用的任务,该函数属于应用层和OS之间的接口函数,一般项目的建立需要根据系统的需要自己编写改函数,并将函数放到应用层。osalAddTasks()函数是通过osalTaskAdd()函数完成任务添加。

?????? 值得注意的是在一个空的协议栈里osalAddTasks()只是在OSAL_Custom.h中申明,并未写出具体操作,需要我们在自己在接口处编写,osalTaskAdd()函数也是自己加进去的

osalTaskAdd()已经不支持,现在用下面的方法添加任务

在协议栈ZStack-CC2430-1.4.3中是这样添加任务的:

1)任务初始化函数的添加

main ()

--->byte osal_init_system( void )?【OSAL.c】

--->osalInitTasks()【OSAL_SampleApp.c】 //初始化系统任务

---> void SampleApp_Init( uint8 task_id )【SampleApp.c】//应用初始化

2)任务处理函数的流程

首先在任务函数列表中添加处理函数

const pTaskEventHandlerFn tasksArr[] = {

??macEventLoop,

??nwk_event_loop,

??Hal_ProcessEvent,

#if defined( MT_TASK )

??MT_ProcessEvent,

#endif

??APS_event_loop,

??ZDApp_event_loop,

??SampleApp_ProcessEvent

};

该列表中处理函数的出现的顺序需要和osalInitTasks()函数中初始化的顺序一致

oid osalInitTasks( void )

{

uint8 taskID = 0;

?

tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);

osal_memset( tasksEvents,(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++ );

SampleApp_Init( taskID ); //注意顺序要和pTaskEventHandlerFn中处理函数一致

}

?

?

?

2、??任务初始化--- void SampleApp_Init( uint8 task_id )【SampleApp.c】

命名规则:应用名_init()

?????? 初始化内容:

????????????? 初始化Application Objects对应的变量

????????????? 相应Application Objects的实例化—afRegister()

????????????? 注册应用OSAL或HAL系统服务—RegisterForKeys()

?????/*********************************************************************

?* @fn??????SampleApp_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 SampleApp_Init( uint8 task_id )

{

??SampleApp_TaskID = task_id;

??SampleApp_NwkState = DEV_INIT;

??SampleApp_TransID = 0;

?

??// Device hardware initialization can be added here or in main() (Zmain.c).

??// If the hardware is application specific - add it here.

??// If the hardware is other parts of the device add it in main().

??

?#if defined ( SOFT_START )

??// The "Demo" target is setup to have SOFT_START and HOLD_AUTO_START

??// SOFT_START is a compile option that allows the device to start

??//??as a coordinator if one isn't found.

??// We are looking at a jumper (defined in SampleAppHw.c) to be jumpered

??// together - if they are - we will start up a coordinator. Otherwise,

??// the device will start as a router.

??if ( readCoordinatorJumper() )

????zgDeviceLogicalType = ZG_DEVICETYPE_COORDINATOR;

??else

????zgDeviceLogicalType = ZG_DEVICETYPE_ROUTER;

#endif // SOFT_START

??

#if defined ( HOLD_AUTO_START )

??// HOLD_AUTO_START is a compile option that will surpress ZDApp

??//??from starting the device and wait for the application to

??//??start the device.

??ZDOInitDevice(0);

#endif

??

??// Setup for the periodic message's destination address

??// Broadcast to everyone

??SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast;

??SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;

??SampleApp_Periodic_DstAddr.addr.shortAddr = 0xFFFF;

?

??// Setup for the flash command's destination address - Group 1

??SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)afAddrGroup;

??SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;

??SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP;

?

??// Fill out the endpoint description.

??SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;

??SampleApp_epDesc.task_id = &SampleApp_TaskID;

??SampleApp_epDesc.simpleDesc

????????????= (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc;

??SampleApp_epDesc.latencyReq = noLatencyReqs;

?

??// Register the endpoint description with the AF

??afRegister( &SampleApp_epDesc );

?

??// Register for all key events - This app will handle all key events

??RegisterForKeys( SampleApp_TaskID );??//注册按键事件后,按键回调函数将会把OSAl系统事件KEY_CHANGE发送到注册的SampleApp_TaskID

?

??// By default,all devices start out in Group 1??

??SampleApp_Group.ID = 0x0001;

??osal_memcpy( SampleApp_Group.name,"Group 1",7??);

??aps_AddGroup( SAMPLEAPP_ENDPOINT,&SampleApp_Group );

?

#if defined ( LCD_SUPPORTED )

??HalLcdWriteString( "SampleApp",HAL_LCD_LINE_1 );

#endif

}

3、??任务处理---uint16 SampleApp_ProcessEvent( uint8 task_id,uint16 events )【SampleApp.c】

1)当SampleApp_TaskID对应的OSAL事件发生时,在OSAL的主循环函数会调用该处理函数;

2)SYS_EVENT_MSG是全局系统消息,该消息包含以下消息:

--AF_DATA_CONFIRM_CMD

--AF_INCOMING_MSG_CMD

--KEY_CHANGE

--ZDO_STATE_CHANGE

3)如果一个OSAL任务已经注册为按键按下通知,则任何的按键事件将会以KEY_CHANGE系统事件消息的形式接收。有两种可能的程序流程会使一个任务接收到此KEY_CHANGE

?? 物理层按键的程序流程如下:

???--HAL检测按键状态(通过H/W中断或H/W循环检测);

???--HAL OSAL任务检测到一个按键状态变化,并调用OSAL按键变化回调函数;

???--OSAL按键变化回调函数发送OSAL系统事件消息KEY_CHANGE到通过RegisterForKeys()注册的TaskID

4)TransID??其作用是识别消息,可为每个不同的Endpoint或每个clusterID对应的事件设置一TransID以对其进行区别。

?

/*********************************************************************

?* @fn??????SampleApp_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 SampleApp_ProcessEvent( uint8 task_id,uint16 events )

{

??afIncomingMSGPacket_t *MSGpkt;

?

??if ( events & SYS_EVENT_MSG )

??{

????MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );??//从OS的消息队列中接收一个消息

????while ( MSGpkt )

????{

??????switch ( MSGpkt->hdr.event )

??????{

????????// Received when a key is pressed

????????case KEY_CHANGE:

??????????SampleApp_HandleKeys( ((keyChange_t *)MSGpkt)->state,((keyChange_t *)MSGpkt)->keys ); //按键处理函数

??????????break;

?

????????// Received when a messages is received (OTA) for this endpoint

????????case AF_INCOMING_MSG_CMD:

??????????SampleApp_MessageMSGCB( MSGpkt );??//对于接收消息的节点,将执行此函数

??????????break;

zigbee任务的处理流程(二)

??// Release the memory

??????osal_msg_deallocate( (uint8 *)MSGpkt );

?

??????// Next - if one is available

??????MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );??//继续取消息队列中的消息

????}

?

????// return unprocessed events

????return (events ^ SYS_EVENT_MSG);

??}

?

??// Send a message out - This event is generated by a timer

??//??(setup in SampleApp_Init()).

??if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )

??{

????// Send the periodic message

????SampleApp_SendPeriodicMessage();

?

????// Setup to send message again in normal period (+ a little jitter)

????osal_start_timerEx( SampleApp_TaskID,SAMPLEAPP_SEND_PERIODIC_MSG_EVT,

????????(SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) );

?

????// return unprocessed events

????return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT);

??}

?

??// Discard unknown events

??return 0;

}

5)在该实例程序中,按键处理程序SampleApp_HandleKeys对按键进行处理:

???????(1)按键1—向group1的设备发送闪烁消息SampleApp_SendFlashMessage()

?????? 该函数中的SampleApp_Flash_DstAddr为发送的目的地址,该参数在SampleApp_Init()中初始化为组1:

// Setup for the flash command's destination address - Group 1

??SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)afAddrGroup;

??SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;

??SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP;

?所以设备在初始化时初始化为组1,组初始化方法为:

???????aps_Group_t SampleApp_Group;

???????….

???????SampleApp_Group.ID = 0x0001;

???????Osal_memcpy(SampleApp_Group.name,”Group 1”,7);

???????aps_AddGroup(SAMPLEAPP_ENDPOINT,&SampleApp_Group);

??????

???????aps_Group_t结构体为:

???????typedef struct

???????{

??????????????Uint16 ID;

??????????????Uint8 name[APS_GROUP_NAME_LEN];

}aps_Group_t;

?????? 按键1的处理函数为:

void SampleApp_SendFlashMessage( uint16 flashTime )

{

??uint8 buffer[3];

??buffer[0] = (uint8)(SampleAppFlashCounter++);??//发送闪烁消息的次数

??buffer[1] = LO_UINT16( flashTime );??//闪烁频率的计数

??buffer[2] = HI_UINT16( flashTime );

??

??if ( AF_DataRequest( &SampleApp_Flash_DstAddr,??//目的的组地址,group1

&SampleApp_epDesc,??//源EndPoint description

???????????????????????SAMPLEAPP_FLASH_CLUSTERID,//cluster ID

???????????????????????3,//要发送数据的长度

???????????????????????buffer,//发送数据的指针

???????????????????????&SampleApp_TransID,//事物需要指针,若果消息缓存发送,这个函数将会增加此数

???????????????????????AF_DISCV_ROUTE,//发送选项

???????????????????????AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )

??{

??}

??else

??{

????// Error occurred in request to send.

??}

}

?????? 注:AF_DataRequest生命如下

afStatus_t AF_DataRequest( afAddrType_t *dstAddr,

endPointDesc_t *srcEP,

???????????????????????????uint16 cID,

uint16 len,

uint8 *buf,

uint8 *transID,

????????????????????????????uint8 options,

uint8 radius )

该函数中参数option为以下值:

???????AF_ACK_REQUEST 0x10---请求,应用层调用,要求APS应答,这是应用层的应答,只在直接发送(单播)时使用

???????AF_DISCV_ROUNTE 0x20 ---路由发现,总是包含此项

???????AF_SKIP_RONTING 0x80---使设备跳过路由而直接发送消息,终点设备将不向其父亲发送消息

?????? (2)按键2—按一次会使设备脱离组1,再按一次会使设备加入组1

?????????????aps_Group_t *grp;

????grp = aps_FindGroup( SAMPLEAPP_ENDPOINT,SAMPLEAPP_FLASH_GROUP );

????if ( grp )

????{

??????// Remove from the group

??????aps_RemoveGroup( SAMPLEAPP_ENDPOINT,SAMPLEAPP_FLASH_GROUP );

????}

????else

????{

??????// Add to the flash group

??????aps_AddGroup( SAMPLEAPP_ENDPOINT,&SampleApp_Group );

}

????????????????????????i.??????????????接收到的消息处理

若收到AF_INCOMING_MSG_CMD,则调用函数SampleApp_MessageMSGCB()【SampleApp.c】对消息进行处理。

??????????????????????ii.??????????????osal_start_timerEx( )

为指定的task启动定时器,当定时器到时后,指定的event位将会置位

byte osal_start_timerEx( byte taskID,UINT16 event_id,UINT16

timeout_value);

????????taskID—定时器到时时获取event的task ID,即event通知给task ID

????????event_id ---用户定义的event bit,当定时器到时后,会向task id通知event

????????timeout_value---时间(微秒)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读