1、void InitBoard( byte level )
{
……
OnboardKeyIntEnable = HAL_KEY_INTERRUPT_DISABLE;//使用轮询方式
HalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback);
}
}
2、
void HalKeyConfig (bool interruptEnable, halKeyCBack_t cback)
{
#if (HAL_KEY == TRUE)
/* Enable/Disable Interrupt or */
Hal_KeyIntEnable = interruptEnable;
/* Register the callback fucntion */
pHalKeyProcessFunction = cback;//注册回调函数
/* Determine if interrupt is enable or not */
if (Hal_KeyIntEnable)//中断方式
{
else /* Interrupts NOT enabled */轮询方式
{
/*
Work around for CC2430DB when interrupt is enabled and SW5 (center joystick)
is used. This SW5 uses P2 which also has debug lines connected to it. This
causes contant interruption on P2INT_VECTOR. Disable the usage of P2 interrupt
will stop this problem.
*/
#if defined (HAL_BOARD_CC2430DB)
#define HAL_KEY_SW_5_ENABLE /* Allow SW5 only when key interrupt is disable */
#endif
#if defined (HAL_KEY_SW_6_ENABLE)
HAL_KEY_SW_6_ICTL &= ~(HAL_KEY_SW_6_ICTLBIT);/* Clear interrupt enable bit */
HAL_KEY_SW_6_IEN &= ~(HAL_KEY_SW_6_IENBIT);
#endif
#if defined (HAL_KEY_SW_5_ENABLE)
HAL_KEY_SW_5_ICTL &= ~(HAL_KEY_SW_5_ICTLBIT); /* Clear interrupt enable bit */
HAL_KEY_SW_5_IEN &= ~(HAL_KEY_SW_5_IENBIT);
#endif
osal_start_timerEx (Hal_TaskID, HAL_KEY_EVENT, HAL_KEY_POLLING_VALUE); /* Kick off polling */------开启轮询事件
}
/* Key now is configured */
HalKeyConfigured = TRUE;
#endif /* HAL_KEY */
}
3、
uint16 Hal_ProcessEvent( uint8 task_id, uint16 events )
{
if (events & HAL_KEY_EVENT)
{
#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;
}
说明:该事件触发了函数HalKeyPoll()来检测是否有按键按下,并且如果按键配置为非中断,即轮询方式,会开启定时器在100ms后再次触发事件 HAL_KEY_EVENT。以此来实现按键的轮询。
4、
void HalKeyPoll (void)
{
#if (HAL_KEY == TRUE)
uint8 keys = 0;//初始键值为0
* If interrupts are enabled, get the status of the interrupt-driven keys from halSaveIntKey
* which is updated by the key ISR. If Polling, read these keys directly.
*/
#if defined (HAL_KEY_SW_6_ENABLE)
if (!(HAL_KEY_SW_6_PORT & HAL_KEY_SW_6_BIT)) /* Key is active low */
{
keys |= HAL_KEY_SW_6;//如果按键6被按下,则将按键6的值赋给keys
}
#endif
#if defined (HAL_KEY_SW_5_ENABLE)
if (HAL_KEY_SW_5_PORT & HAL_KEY_SW_5_BIT) /* Key is active high */
{
keys |= HAL_KEY_SW_5;//如果按键5被按下,则将按键5的值赋给keys
}
#endif
/* Exit if polling and no keys have changed */
if (!Hal_KeyIntEnable)//如果是轮询方式执行以下代码
{
if (keys == halKeySavedKeys)
{
return;
}
halKeySavedKeys = keys; /* Store the current keys for comparation next time */
}
/* Invoke Callback if new keys were depressed */
if (keys && (pHalKeyProcessFunction))
{
(pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);
}
#endif /* HAL_KEY */
}
5、
void OnBoard_KeyCallback ( uint8 keys, uint8 state )
{
uint8 shift;
……
shift = (OnboardKeyIntEnable == HAL_KEY_INTERRUPT_ENABLE) ? false : ((keys & HAL_KEY_SW_6) ? true : false);
if ( OnBoard_SendKeys( keys, shift ) != ZSuccess )//调用OnBoard_SendKeys将信息发送到上层
{
……
}
}
6、
byte OnBoard_SendKeys( byte keys, byte state )
{
keyChange_t *msgPtr;
if ( registeredKeysTaskID != NO_TASK_ID )//这里必须要被注册
{
// Send the address to the task
msgPtr = (keyChange_t *)osal_msg_allocate( sizeof(keyChange_t) );//分配内存空间
if ( msgPtr )
{
msgPtr->hdr.event = KEY_CHANGE;
msgPtr->state = state;
msgPtr->keys = keys;
osal_msg_send( registeredKeysTaskID, (uint8 *)msgPtr );
}
return ( ZSuccess );
}
else
return ( ZFailure );
}
说明
1)、注册,通过注册的机制实现数据在层之间的传递。
在应用层:
RegisterForKeys( SampleApp_TaskID );
函数说明:
byte RegisterForKeys( byte task_id )
{
// Allow only the first task
if ( registeredKeysTaskID == NO_TASK_ID ) //判断条件,确定没有被注册
{
registeredKeysTaskID = task_id;//将传来的ID赋给了registeredKeysTaskID
return ( true );
}
else
return ( false );
}
通过task_id的传递,registeredKeysTaskID已经为应用层的任务ID了,如果使用该ID可直接将任务事件发送到应用层。
osal_msg_send( registeredKeysTaskID, (uint8 *)msgPtr )就是将msgPtr发送给了 registeredKeysTaskID层,即应用层。
2)、消息打包:
msgPtr = (keyChange_t *)osal_msg_allocate( sizeof(keyChange_t) );//分配内存空间
//以下为装载信息:
msgPtr->hdr.event = KEY_CHANGE;//装载事件
msgPtr->state = state;//装载状态
msgPtr->keys = keys;//装载键值
7、
byte osal_msg_send( byte destination_task, byte *msg_ptr )
{
//检查消息的有效性
if ( msg_ptr == NULL )
return ( INVALID_MSG_POINTER );
if ( destination_task >= tasksCnt )
{
osal_msg_deallocate( msg_ptr );
return ( INVALID_TASK );
}
// Check the message header
if ( OSAL_MSG_NEXT( msg_ptr ) != NULL ||
OSAL_MSG_ID( msg_ptr ) != TASK_NO_TASK )
{
osal_msg_deallocate( msg_ptr );
return ( INVALID_MSG_POINTER );
}
//将事件加入到系统任务队列里
OSAL_MSG_ID( msg_ptr ) = destination_task;
// queue message
osal_msg_enqueue( &osal_qHead, msg_ptr );
// Signal the task that a message is waiting
osal_set_event( destination_task, SYS_EVENT_MSG );//触发事件
return ( ZSUCCESS );
}
说明:在最后触发了SYS_EVENT_MSG事件,其任务ID为destination_task,即SampleApp_TaskID。
8、
byte osal_set_event( byte task_id, UINT16 event_flag )
{
if ( task_id < tasksCnt )
{
halIntState_t intState;
HAL_ENTER_CRITICAL_SECTION(intState); // Hold off interrupts
tasksEvents[task_id] |= event_flag; // Stuff the event bit(s)
//task_id 为SampleApp_TaskID。
HAL_EXIT_CRITICAL_SECTION(intState); // Release interrupts
}
else
return ( INVALID_TASK );
return ( ZSUCCESS );
}
9、
void osal_start_system( void )
{
for(;;)
{
uint8 idx = 0;
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);
//tasksEvents[task_id] |= event_flag;使得跳出循环
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);
}
}
}
10、
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
{
afIncomingMSGPacket_t *MSGpkt;
if ( events & SYS_EVENT_MSG )
{
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
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;
……
}
消息解包过程,队列中读取MSGpkt消息,然后检测其event,我们打包按键是event为KEY_CHANGE。所以在switch语句中最终会之心函数SampleApp_HandleKeys().。同时将MSG的state和keys传递到函数中,即我们打包时按键的状态和按键的数值。
11、
void SampleApp_HandleKeys( uint8 shift, uint8 keys )
{
if ( keys & HAL_KEY_SW_1 )//如果按键值keys&HAL_KEY_SW_1 为1,执行以下代码
{
SampleApp_SendFlashMessage( SAMPLEAPP_FLASH_DURATION );
}
if ( keys & HAL_KEY_SW_2 )//如果按键值keys&HAL_KEY_SW_2 为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 );
}
}