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);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////