微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 无线和射频 > 射频无线通信设计 > z-stack 2.51A 之二 CC2530 之 z-stack按键流程

z-stack 2.51A 之二 CC2530 之 z-stack按键流程

时间:10-02 整理:3721RD 点击:


1,Z-STACK里面包含了一个OSAL ,所以要为用户分配任务,任务中任何事情的交互都要靠事件,按键也不列外。SampleApp.c中先要注册按键事件,否则事件和响应事件不会关联起来。

事件: 注册事件 搜寻事件发送到OSAL OSAL响应事件

void SampleApp_Init( uint8 task_id )
{
SampleApp_TaskID = task_id;
SampleApp_NwkState = DEV_INIT;
SampleApp_TransID = 0;
// Device hardware initialization can be added here or in main() (Zmain.c).
// If the hardware is application specific - add it here.
// If the hardware is other parts of the device add it in main().
#if defined ( BUILD_ALL_DEVICES )
// The "Demo" target is setup to have BUILD_ALL_DEVICES and HOLD_AUTO_START
// We are looking at a jumper (defined in SampleAppHw.c) to be jumpered
// together - if they are - we will start up a coordinator. Otherwise,
// the device will start as a router.
if ( readCoordinatorJumper() )
zgDeviceLogicalType = ZG_DEVICETYPE_COORDINATOR;
else
zgDeviceLogicalType = ZG_DEVICETYPE_ROUTER;
#endif // BUILD_ALL_DEVICES
#if defined ( HOLD_AUTO_START )
// HOLD_AUTO_START is a compile option that will surpress ZDApp
// from starting the device and wait for the application to
// start the device.
ZDOInitDevice(0);
#endif
// Setup for the periodic message's destination address
// Broadcast to everyone
SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast;
SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_Periodic_DstAddr.addr.shortAddr = 0xFFFF;
// Setup for the flash command's destination address - Group 1
SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)afAddrGroup;
SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP;
// Fill out the endpoint description.
SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;
SampleApp_epDesc.task_id = &SampleApp_TaskID;
SampleApp_epDesc.simpleDesc
= (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc;
SampleApp_epDesc.latencyReq = noLatencyReqs;

// Register the endpoint description with the AF
afRegister( &SampleApp_epDesc );

// Register for all key events - This app will handle all key events
RegisterForKeys( SampleApp_TaskID );

// By default, all devices start out in Group 1
SampleApp_Group.ID = 0x0001;
osal_memcpy( SampleApp_Group.name, "Group 1", 7 );
aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group );
#if defined ( LCD_SUPPORTED )
HalLcdWriteString( "SampleApp", HAL_LCD_LINE_1 );
#endif
}

uint8 RegisterForKeys( uint8 task_id )
{
// Allow only the first task
if ( registeredKeysTaskID == NO_TASK_ID )
{
registeredKeysTaskID = task_id;
return ( true );
}
else
return ( false );
}

2,按键初始化,这里面主要设置IO的方向和上拉之类的:
void HalKeyInit( void )
{
/* Initialize previous key to 0 */
halKeySavedKeys = 0;
HAL_KEY_SW_6_SEL &= (HAL_KEY_SW_6_BIT); /* Set pin function to GPIO */
HAL_KEY_SW_6_DIR &= (HAL_KEY_SW_6_BIT); /* Set pin direction to Input */
HAL_KEY_JOY_MOVE_SEL &= (HAL_KEY_JOY_MOVE_BIT); /* Set pin function to GPIO */
HAL_KEY_JOY_MOVE_DIR &= (HAL_KEY_JOY_MOVE_BIT); /* Set pin direction to Input */
/* Initialize callback function */
pHalKeyProcessFunction = NULL;//回调函数暂时还没配置
/* Start with key is not configured */
HalKeyConfigured = FALSE;//这里说明还没配置好按键
}

hal_driver.c
void HalDriverInit (void)
{
/* TIMER */
#if (defined HAL_TIMER) && (HAL_TIMER == TRUE)
#error "The hal timer driver module is removed."
#endif

/* ADC */
#if (defined HAL_ADC) && (HAL_ADC == TRUE)
HalAdcInit();
#endif

/* DMA */
#if (defined HAL_DMA) && (HAL_DMA == TRUE)
// Must be called before the init call to any module that uses DMA.
HalDmaInit();
#endif

/* AES */
#if (defined HAL_AES) && (HAL_AES == TRUE)
HalAesInit();
#endif

/* LCD */
#if (defined HAL_LCD) && (HAL_LCD == TRUE)
HalLcdInit();
#endif

/* LED */
#if (defined HAL_LED) && (HAL_LED == TRUE)
HalLedInit();
#endif

/* UART */
#if (defined HAL_UART) && (HAL_UART == TRUE)
HalUARTInit();
#endif
/* KEY */
#if (defined HAL_KEY) && (HAL_KEY == TRUE)
HalKeyInit();
#endif
/* SPI */
#if (defined HAL_SPI) && (HAL_SPI == TRUE)
HalSpiInit();
#endif
/* HID */
#if (defined HAL_HID) && (HAL_HID == TRUE)
usbHidInit();
#endif
}

void HalKeyInit( void )
{
/* Initialize previous key to 0 */
halKeySavedKeys = 0;

HAL_KEY_SW_6_SEL &= (HAL_KEY_SW_6_BIT); /* Set pin function to GPIO */
HAL_KEY_SW_6_DIR &= (HAL_KEY_SW_6_BIT); /* Set pin direction to Input */

HAL_KEY_JOY_MOVE_SEL &= (HAL_KEY_JOY_MOVE_BIT); /* Set pin function to GPIO */
HAL_KEY_JOY_MOVE_DIR &= (HAL_KEY_JOY_MOVE_BIT); /* Set pin direction to Input */

/* Initialize callback function */
pHalKeyProcessFunction = NULL;

/* Start with key is not configured */
HalKeyConfigured = FALSE;
}

3,首先按键模式设置,其次是设置回调函数 onboard.c 中 InitBoard ==》HalKeyConfig干这个事,是中断还是不是中断。其实说中断时定时中断然后查询按键。不是真的按键中断。所以下面的函数有两个参数。
HAL_KEY.C中

void HalKeyConfig (bool interruptEnable, halKeyCBack_t cback)

{

/* Enable/Disable Interrupt or */

Hal_KeyIntEnable = interruptEnable;

/* Register the callback fucntion */

pHalKeyProcessFunction = cback;

/* Determine if interrupt is enable or not */

if (Hal_KeyIntEnable)

{

/* Rising/Falling edge configuratinn */

PICTL &= (HAL_KEY_SW_6_EDGEBIT); /* Clear the edge bit */

/* For falling edge, the bit must be set. */

#if (HAL_KEY_SW_6_EDGE == HAL_KEY_FALLING_EDGE)

PICTL |= HAL_KEY_SW_6_EDGEBIT;

#endif

/* Interrupt configuration:

* - Enable interrupt generation at the port

* - Enable CPU interrupt

* - Clear any pending interrupt

*/

HAL_KEY_SW_6_ICTL |= HAL_KEY_SW_6_ICTLBIT;

HAL_KEY_SW_6_IEN |= HAL_KEY_SW_6_IENBIT;

HAL_KEY_SW_6_PXIFG = (HAL_KEY_SW_6_BIT);

/* Rising/Falling edge configuratinn */

HAL_KEY_JOY_MOVE_ICTL &= (HAL_KEY_JOY_MOVE_EDGEBIT); /* Clear the edge bit */

/* For falling edge, the bit must be set. */

#if (HAL_KEY_JOY_MOVE_EDGE == HAL_KEY_FALLING_EDGE)

HAL_KEY_JOY_MOVE_ICTL |= HAL_KEY_JOY_MOVE_EDGEBIT;

#endif

/* Interrupt configuration:

* - Enable interrupt generation at the port

* - Enable CPU interrupt

* - Clear any pending interrupt

*/

HAL_KEY_JOY_MOVE_ICTL |= HAL_KEY_JOY_MOVE_ICTLBIT;

HAL_KEY_JOY_MOVE_IEN |= HAL_KEY_JOY_MOVE_IENBIT;

HAL_KEY_JOY_MOVE_PXIFG = (HAL_KEY_JOY_MOVE_BIT);

/* Do this only after the hal_key is configured - to work with sleep stuff */

if (HalKeyConfigured == TRUE)

{

osal_stop_timerEx(Hal_TaskID, HAL_KEY_EVENT); /* Cancel polling if active */

}

}

else /* Interrupts NOT enabled */

{

HAL_KEY_SW_6_ICTL &= (HAL_KEY_SW_6_ICTLBIT); /* don't generate interrupt */

HAL_KEY_SW_6_IEN &= (HAL_KEY_SW_6_IENBIT); /* Clear interrupt enable bit */

osal_set_event(Hal_TaskID, HAL_KEY_EVENT);

//启动第一次定时按键事件,后面就在Hal_ProcessEvent中 osal_start_timerEx( Hal_TaskID, HAL_KEY_EVENT, 100);//定时出现按键查询事件

}

/* Key now is configured */

HalKeyConfigured = TRUE;

}

调用这个的函数是在onboard.c的InitBoard

void InitBoard( uint8 level )

{

if( level == OB_COLD )

{

// IAR does not zero-out this byte below the XSTACK.

*(uint8 *)0x0 = 0;

// Interrupts off

osal_int_disable( INTS_ALL );

// Check for Brown-Out reset

ChkReset();

}

else // !OB_COLD

{

/* Initialize Key stuff */

HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE, OnBoard_KeyCallback);

}

}

到此,按键模式设置和回调函数的指向已经确定了。


4,系统怎么查按键呢?

Hal_ProcessEvent==>HalKeyPoll 这里查到按键值并发送消息

Hal_ProcessEvent也有 osal_start_timerEx,让按键定时查询

这个里面

hal_driver.c:

uint16 Hal_ProcessEvent( uint8 task_id,uint16 events )

{

uint8 *msgPtr;


(void)task_id; // Intentionallyunreferenced parameter


if( events & SYS_EVENT_MSG

{

msgPtr = osal_msg_receive(Hal_TaskID);


while (msgPtr)

{

/* Do something here - for now, just deallocate the msg and move on */


/* De-allocate */

osal_msg_deallocate( msgPtr );

/* Next */

msgPtr = osal_msg_receive( Hal_TaskID );

}

return events ^ SYS_EVENT_MSG;

}


if( events & HAL_LED_BLINK_EVENT )

{

#if (defined (BLINK_LEDS)) &&(HAL_LED == TRUE)

HalLedUpdate();

#endif /* BLINK_LEDS && HAL_LED */

return events ^ HAL_LED_BLINK_EVENT;

}


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;

}


#ifdef POWER_SAVING

if( events & HAL_SLEEP_TIMER_EVENT )

{

halRestoreSleepLevel();

return events ^ HAL_SLEEP_TIMER_EVENT;

}

#endif


#ifdef CC2591_COMPRESSION_WORKAROUND

if( events & PERIOD_RSSI_RESET_EVT )

{

macRxResetRssi();

return (events ^ PERIOD_RSSI_RESET_EVT);

}

#endif

/*Nothing interested, discard the message */

return 0;


}


HalKeyPoll 也在hal_key.c中

void HalKeyPoll (void)

{

uint8 keys = 0;

//这里注意了,ZSTACK的工程师们把这里定义了很多宏,其实我们懂51的,不用那么复杂,直接的吧哪些宏干掉还看得舒服点,哈哈。

if (P0_2 ==0)

{

keys |= HAL_KEY_SW_1;////////

}

if (!HAL_PUSH_BUTTON1())

{

keys |= HAL_KEY_SW_2;////////HAL_KEY_SW_6;

}

//按键是哪一个放到keys

/* Invoke Callback if new keys were depressed */

if (keys && (pHalKeyProcessFunction))

{

(pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);//这里调用回调函数处理发送keys按键消息到OSAL

}

}

回调函数,因为查到按键以后必须通知OSAL操作系统有按键事件了,这里调用回调函数 ==〉里面的OnBoard_SendKeys 来发送按键事件。

void OnBoard_KeyCallback ( uint8 keys, uint8 state )

{

uint8 shift;

(void)state;


shift = (keys & HAL_KEY_SW_6) ? true : false;


if ( OnBoard_SendKeys( keys, shift ) != ZSuccess ) //

{

// Process SW1 here

if ( keys & HAL_KEY_SW_1 ) // Switch 1

{

}

// Process SW2 here

if ( keys & HAL_KEY_SW_2 ) // Switch 2

{

}

// Process SW3 here

if ( keys & HAL_KEY_SW_3 ) // Switch 3

{

}

// Process SW4 here

if ( keys & HAL_KEY_SW_4 ) // Switch 4

{

}

// Process SW5 here

if ( keys & HAL_KEY_SW_5 ) // Switch 5

{

}

// Process SW6 here

if ( keys & HAL_KEY_SW_6 ) // Switch 6

{

}

}

}

onboard.c中:

*********************************************************************/

uint8 OnBoard_SendKeys( uint8 keys, uint8state )

{

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

}


到此,按键的消息到了OSAL
5,下面就是响应消息:
SampleApp.c中调用SampleApp_ProcessEvent响应按键消息

uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
{
afIncomingMSGPacket_t *MSGpkt;
(void)task_id; // Intentionally unreferenced parameter
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;
// Received when a messages is received (OTA) for this endpoint
case AF_INCOMING_MSG_CMD:
SampleApp_MessageMSGCB( MSGpkt );
break;
// Received whenever the device changes state in the network
case ZDO_STATE_CHANGE:
SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
if ( (SampleApp_NwkState == DEV_ZB_COORD)
|| (SampleApp_NwkState == DEV_ROUTER)
|| (SampleApp_NwkState == DEV_END_DEVICE) )
{
// Start sending the periodic message in a regular interval.
osal_start_timerEx( SampleApp_TaskID,
SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );
}
else
{
// Device is no longer in the network
}
break;
default:
break;
}

// Release the memory
osal_msg_deallocate( (uint8 *)MSGpkt );
// Next - if one is available
MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
}
// return unprocessed events
return (events ^ SYS_EVENT_MSG);
}
// Send a message out - This event is generated by a timer
// (setup in SampleApp_Init()).
if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )
{
// Send the periodic message
SampleApp_SendPeriodicMessage();

// Setup to send message again in normal period (+ a little jitter)
osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,
(SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) );
// return unprocessed events
return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT);
}
// Discard unknown events
return 0;
}

/*********************************************************************
* Event Generation Functions
*/
/*********************************************************************
* @fn SampleApp_HandleKeys
*
* @brief Handles all key events for this device.
*
* @param shift - true if in shift/alt.
* @param keys - bit field for key events. Valid entries:
* HAL_KEY_SW_2
* HAL_KEY_SW_1
*
* @return none
*/
void SampleApp_HandleKeys( uint8 shift, uint8 keys )
{
(void)shift; // Intentionally unreferenced parameter

if ( keys & HAL_KEY_SW_1 )
{
/* This key sends the Flash Command is sent to Group 1.
* This device will not receive the Flash Command from this
* device (even if it belongs to group 1).
*/
SampleApp_SendFlashMessage( SAMPLEAPP_FLASH_DURATION );
}

if ( keys & HAL_KEY_SW_2 )
{
/* The Flashr Command is sent to Group 1.
* This key toggles this device in and out of group 1.
* If this device doesn't belong to group 1, this application
* will not receive the Flash command sent to group 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 );
}
}
}

就这几点,还有中间一些蓝色标记的细节。复杂。疏理了下好像是简单了点。贻笑大方了。

写微博啊,内容太少了。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

挺好的 论坛可以弄个说说之类功能的东西

哈哈,补上了。

嘿嘿,搞zigbee的

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top