10 在ZStack里的按键驱动

到目前我们可以通过设置任务的事件信息,从而让任务的事件处理函数触发。但除了事件外如还需要传递额外的数据(消息)给另一任务时,就需要用下面的函数功能:

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值