到目前我们可以通过设置任务的事件信息,从而让任务的事件处理函数触发。但除了事件外如还需要传递额外的数据(消息)给另一任务时,就需要用下面的函数功能:
OSAL/OSAL.h
typedef struct
{
uint8 event; //记录消息的种类,如按键消息则为KEY_CHANGE
uint8 status;
} osal_event_hdr_t; //每种消息都包括此结构体作头部
extern uint8 * osal_msg_allocate(uint16 len ); //动态分配消息所需的空间
extern uint8 osal_msg_deallocate( uint8 *msg_ptr ); //回收消息的空间
extern uint8 osal_set_event( uint8 task_id, uint16 event_flag ); //设置指定号的任务发生event_flag事件. 即tasksEvents[task_id] |= event_flag;
extern uint8 osal_msg_send( uint8 destination_task, uint8 *msg_ptr ); //发出消息到指定号的任务. 调用此函数时会设置指定号的任务发生SYS_EVENT_MSG.即osal_set_event( destination_task, SYS_EVENT_MSG )
extern uint8 *osal_msg_receive( uint8 task_id ); //接收指定号的任务的消息
/
在ZStack里对按键功能的封装在工程的HAL/include/hal_key.h里:
//表示按键的宏,与硬件没有直接关系
#define HAL_KEY_SW_1 0x01 // Joystick up
#define HAL_KEY_SW_2 0x02 // Joystick right
#define HAL_KEY_SW_5 0x04 // Joystick center
#define HAL_KEY_SW_4 0x08 // Joystick left
#define HAL_KEY_SW_3 0x10 // Joystick down
...
typedef void (*halKeyCBack_t) (uint8 keys, uint8 state);
extern bool Hal_KeyIntEnable;
//下需的函数我们不用直接调用, 这些函数应由hal层的任务来调用。当检查有按键按下时,会设置指定任务的事件(KEY_CHANGE),并把包含按键信息的消息发送到指定的任务.
extern void HalKeyInit( void );
extern void HalKeyConfig( bool interruptEnable, const halKeyCBack_t cback);
extern uint8 HalKeyRead( void);
extern void HalKeyPoll ( void );
...
///
按键的初始化过程:
int main( void )
{
...
InitBoard( OB_COLD );
...
InitBoard( OB_READY );
...
}
void InitBoard( uint8 level )
{
...
HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE, OnBoard_KeyCallback);
...
}
void HalKeyConfig (bool interruptEnable, halKeyCBack_t cback)
{
Hal_KeyIntEnable = interruptEnable; //用全局变量 Hal_KeyIntEnable存放按键是否用中断功能
pHalKeyProcessFunction = cback; //用全局函数指针变量pHalKeyProcessFunction存放当按键状态发生变化时需要调用的函数的地址
...
}
//任务需要接收按键消息的初始化
RegisterForKeys(mytask_id); //指定mytask_id任务号的任务接收按键的消息
uint8 RegisterForKeys( uint8 task_id )
{
registeredKeysTaskID = task_id; //用全局变量registeredKeysTaskID来存放要接收按键消息的任务号
...
}
///
//按键在hal任务里的检查:
uint16 Hal_ProcessEvent( uint8 task_id, uint16 events ) // hal任务的事件处理函数
{
...
if (events & HAL_KEY_EVENT)
{
HalKeyPoll(); //检查按键状态,并发出按键消息
if (!Hal_KeyIntEnable)
{
osal_start_timerEx( Hal_TaskID, HAL_KEY_EVENT, 100);
//定时100ms后,给hal任务设置HAL_KEY_EVENT事件。也就是用定时器每隔100ms来检查按键.
}
...
}
void HalKeyPoll (void)
{
uint8 keys = 0;
...
if (!Hal_KeyIntEnable)
{
if (keys == halKeySavedKeys)
{
return;
}
halKeySavedKeys = keys;
}
else
{
}
...
if (HAL_PUSH_BUTTON1()) //检查按键是否按下
{
keys |= HAL_KEY_SW_6;
}
if (keys && (pHalKeyProcessFunction))
{
(pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);
//当有键按下时,需调用OnBoard_KeyCallback函数
}
}
void OnBoard_KeyCallback ( uint8 keys, uint8 state )
{
uint8 shift;
(void)state;
...
if ( OnBoard_SendKeys( keys, shift ) != ZSuccess )
{
}
...
}
typedef struct
{
osal_event_hdr_t hdr; //每种消息都包含此头部
uint8 state; // shift
uint8 keys; // keys
} keyChange_t; //按键的消息类型
uint8 OnBoard_SendKeys( uint8 keys, uint8 state )
{
keyChange_t *msgPtr;
if ( registeredKeysTaskID != NO_TASK_ID )
{
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 ); //往指定的任务发出按键消息, 同时也会设置任务事件:tasksEvents[registeredKeysTaskID] |= SYS_EVENT_MSG. 接收消息的任务通过调用osal_msg_receive函数就可以得到msgPtr数据了
}
return ( ZSuccess );
...
}
/
因现用的开发板与TI原厂的开发板不同,所以又得修改下里面的代码了.
修改:
#define PUSH1_POLARITY ACTIVE_LOW
#define PUSH2_POLARITY ACTIVE_LOW
void HalKeyPoll (void)
{
uint8 keys = 0;
if (HAL_PUSH_BUTTON1())
{
keys |= HAL_KEY_SW_1;
}
if (HAL_PUSH_BUTTON2())
{
keys |= HAL_KEY_SW_2;
}
if (!Hal_KeyIntEnable)
{
if (keys == halKeySavedKeys)
return;
halKeySavedKeys = keys;
}
else
{
}
if (keys && (pHalKeyProcessFunction))
{
(pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);
}
}
///
用两个按键分别控制一个led灯的亮灭
MyApp.c
#include "OnBoard.h"
#include "MyApp.h"
#include "hal_led.h"
#include "hal_key.h"
#define TIME_OUT_EVENT 0x4
#define TIME_LEN 2000
uint8 mytask_id; //用于存放本身的任务号
void MyApp_Init(uint8 task_id )
{
mytask_id = task_id;
HalLedSet(HAL_LED_ALL, HAL_LED_MODE_OFF);
RegisterForKeys(mytask_id); //设置当前任务接收按键消息
}
uint16 MyApp_ProcessEvent(uint8 task_id, uint16 events )
{
keyChange_t *key_evt;
if ( events & SYS_EVENT_MSG ) //当有按键消息时,任务的事件会是SYS_EVENT_MSG
{
key_evt = (keyChange_t *)osal_msg_receive(mytask_id);
if (key_evt->hdr.event == KEY_CHANGE)
{
if (key_evt->keys & HAL_KEY_SW_1)
HalLedSet(HAL_LED_1, HAL_LED_MODE_TOGGLE);
if (key_evt->keys & HAL_KEY_SW_2)
HalLedSet(HAL_LED_2, HAL_LED_MODE_TOGGLE);
}
osal_msg_deallocate( (uint8 *)key_evt ); //回收消息的空间
}
if (events & TIME_OUT_EVENT) //定时器的事件
{
;
}
return 0;
}