BLE 协议栈中对于触发任务事件大可分为三种方式:
1 通过设置一个“软件定时器”,当其溢出时触发事件。osal_start_timerEx()—osalTimerUpdate()— osal_set_event() ;
2 通过调用系统消息传递机制触发事件。osal_msg_send()—osal_set_event()
3 直接调用osal_set_event()触发事件。
自定义消息的发送与接收
这三种划分方式算是前人之鉴吧,自己看的时候值分出了前两种,不过最终归到事件触发上都调用了osal_set_event()函数
看了两天的消息触发事件,终于看出头了 下面是发送消息的一个例子!
***************** 自定义 消息的发送 ****************************************/
#define king_come 0xFC // 定义消息标志位
注意 自定义消息的标志位的值只能是0xE0 到 0xFC 之间
static int right_come=0;
typedef struct
{
osal_event_hdr_t hdr;
uint8 mark;
}myUartMsg_t; // 定义消息的结构体
void xy_come(void) // 配置消息参数
{
myUartMsg_t *myUartMsg;
myUartMsg=(myUartMsg_t*)osal_msg_allocate(sizeof(myUartMsg_t));
myUartMsg->hdr.event=king_come;
myUartMsg->mark=right_come;
osal_msg_send(simpleBLETaskId,(uint8 *)myUartMsg);
}
消息的发送是通过置位SYS_EVENT_MSG来实现的(在 osal_msg_send中使用osal_set_event( destination_task, SYS_EVENT_MSG );置位)
在这个例子中将xy_come()放在了串口的回调函数中,这样一但受到了数据,就会发送一条消息给osal ,并被osal_msg_receive接收
/**************************** 消息的接收 *************************************/
在系统下一次轮询的时候,会进入SimpleBLECentral_ProcessEvent事件
并被 if ( events & SYS_EVENT_MSG )响应
通过osal_msg_receive( simpleBLETaskId )接收消息
uint16 SimpleBLECentral_ProcessEvent( uint8 task_id, uint16 events )
{
VOID task_id; // OSAL required parameter that isn't used in this function
if ( events & SYS_EVENT_MSG )
{
uint8 *pMsg;
if ( (pMsg = osal_msg_receive( simpleBLETaskId )) != NULL )//接收到消息
{
simpleBLECentral_ProcessOSALMsg( (osal_event_hdr_t *)pMsg ); // 处理函数
VOID osal_msg_deallocate( pMsg ); // 注意这里已经删除消息
}
return (events ^ SYS_EVENT_MSG);
}
}
消息处理:
进入 simpleBLECentral_ProcessOSALMsg中进行消息处理
case king_come:
/* do something */
LCD_WRITE_STRING( "AAA", HAL_LCD_LINE_1 );// 消息处理
break;
对于按键来说可以分为三个部分:按键的硬件配置,按键消息的配置,以及按键触发事件的配置.
按键的硬件配置:
/*********************** 按键功能的 初始化 *******************************/
第一步 : 定义按键状态
#if defined ( CC2540_MINIDK )
/* SW_1 is at P0.0 */
#define HAL_KEY_SW_1_PORT P0
#define HAL_KEY_SW_1_BIT BV(0)
#define HAL_KEY_SW_1_SEL P0SEL
#define HAL_KEY_SW_1_DIR P0DIR
第二步: 初始化按键
HAL_KEY_SW_1_SEL &= ~(HAL_KEY_SW_1_BIT); /* Set pin function to GPIO */
HAL_KEY_SW_1_DIR &= ~(HAL_KEY_SW_1_BIT); /* Set pin direction to Input */
第三步: 按键中断配置
PICTL |= HAL_KEY_SW_1_EDGEBIT; /* Set the edge bit to set falling edge to give int */
HAL_KEY_SW_1_ICTL |= HAL_KEY_SW_1_ICTLBIT; /* enable interrupt generation at port */
HAL_KEY_SW_1_IEN |= HAL_KEY_SW_1_IENBIT; /* enable CPU interrupt */ HAL_KEY_SW_1_PXIFG = ~(HAL_KEY_SW_1_BIT); /* Clear any pending interrupt */
第四步: 清除中断标志位
HAL_KEY_SW_1_ICTL &= ~(HAL_KEY_SW_1_ICTLBIT); /* don't generate interrupt */
HAL_KEY_SW_1_IEN &= ~(HAL_KEY_SW_1_IENBIT); /* Clear interrupt enable bit */
第5 步: 设置中断处理
halProcessKeyInterrupt() 中断处理函数中,清除标志位,并更新key事件的定时器,25ms进行去抖延时
if( HAL_KEY_SW_1_PXIFG & HAL_KEY_SW_1_BIT) /* Interrupt Flag has been set by SW1 */
{
HAL_KEY_SW_1_PXIFG = ~(HAL_KEY_SW_1_BIT); /* Clear Interrupt Flag */
valid = TRUE;
}
并在中断处理函数 HAL_ISR_FUNCTION( halKeyPort0Isr, P0INT_VECTOR )中调用,清除标志位。(编程时可直接写中断处理函数)
在Central 工程的中断函数中只做了清除中断标志位以及按键去抖的操作,并没有发送消息给osal!
这一步其实很简单,只需要像普通8051编程一样,定义好按键的状态以及中断即可。
按键消息的配置:
按键消息的标志位定义在comdef.h
#define KEY_CHANGE 0xC0 // Key Events
Note : 消息标志位(一共16bit)并不是事件标志位(32bit)
例如事件标志:#define SYS_EVENT_MSG 0x8000
按键的消息传递定义放在了 OnBoard.h中
typedef struct
{
osal_event_hdr_t hdr;
uint8 state; // shift
uint8 keys; // keys
} keyChange_t;
消息的配置和发送放在了OnBoard.c中
在InitBoard函数中
HalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback);
OnBoard_KeyCallback函数的OnBoard_SendKeys函数中。
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 );
//在OnBoard_KeyCallback中使用osal_msg_send向simpleBLETaskId发送消息
}
return ( SUCCESS );
}
else
return ( FAILURE );
}
在HalKeyConfig中还加入了事件处理回调函数:
pHalKeyProcessFunction = cback;
在HalKeyConfig中把OnBoard_KeyCallback赋值给了pHalKeyProcessFunction
并且在HalKeyConfig的最后调用osal_set_event(Hal_TaskID, HAL_KEY_EVENT); 开启事件
按键触发事件的配置:
按键状态的监测是使用的一个定时器
按键事件是 Hal_ProcessEvent函数进行监测和处理的
事件的标志定义在hal_drivers.h中
#define HAL_KEY_EVENT 0x0010 // key事件的定时器标志
事件的处理是在Hal_ProcessEvent中
if (events & HAL_KEY_EVENT) // 100ms 监测一次按键状态
{
HalKeyPoll();
if (!Hal_KeyIntEnable)
{
osal_start_timerEx( Hal_TaskID, HAL_KEY_EVENT, 100);
}
return events ^ HAL_KEY_EVENT;
}
在HalKeyPoll里监测key的状态,并且调用
pHalKeyProcessFunction (keys, HAL_KEY_STATE_NORMAL);(在HalKeyPoll函数中) 做出相应的处理(例如监测到了按键按下,给osal发送消息处理)
/////////////////////////////////////按键监测流程图:////////////////////////////////////////////////////////////////////
第一次事件的标志的注册在InitBoard中
HalKeyConfig->
osal_set_event(Hal_TaskID, HAL_KEY_EVENT);
之后循环在定时器中:
Hal_ProcessEven->
HalKeyPoll->
pHalKeyProcessFunction{当前值=OnBoard_KeyCallback}->
HalKeyConfig->
osal_set_event(Hal_TaskID, HAL_KEY_EVENT);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////