https://blog.csdn.net/scgaliguodong123_/article/details/41680863
协议栈已经自带了按键的驱动和使用函数,所以将按键改到任意 IO 口也不是问题 。
本ZigBee开发套件按键S1连接的是P0.0口,按键S2连接的是P0.1口。
===========================================
ZMain.c的main主函数中跟按键相关的有:
HalDriverInit();
InitBoard( OB_READY );
1、
HalDriverInit()中的HalKeyInit()有
hal_drivers.c
/* KEY */
#if (defined HAL_KEY) && (HAL_KEY == TRUE)
HalKeyInit();
hal_key.c
void HalKeyInit( void )
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_SW_6_BIT就是对应P01,
#define BV(n) (1<<(n))
===========================================
2、
OnBoard.c
InitBoard( OB_READY )
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);
}
#define OB_COLD 0
按键检测有两种方式,
一种为中断,一种为定时检测;定时检测的话,在 配置时就会直接启动HAL_KEY_EVENT事件。
#define HAL_KEY_INTERRUPT_DISABLE 0x00 //定时检测
#define HAL_KEY_INTERRUPT_ENABLE 0x01 //中断 一般采用中断方式,更加节省系统资源
定时检测方式
HalKeyConfig(HAL_KEY_INTERRUPT_DISABLEE, OnBoard_KeyCallback);
/* Determine if interrupt is enable or not */
if (Hal_KeyIntEnable)
{
}
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 */
//启动HAL_KEY_EVENT事件
osal_set_event(Hal_TaskID, HAL_KEY_EVENT);
}
处理HAL_KEY_EVENT的 函数Hal_ProcessEvent()
hal_drivers.c
uint16 Hal_ProcessEvent( uint8 task_id, uint16 events )
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;
}
hal_key.c
void HalKeyPoll (void)
{
if (!Hal_KeyIntEnable)
{
if (keys == halKeySavedKeys)
{
/* Exit - since no keys have changed */
return;
}
/* Store the current keys for comparation next time */
halKeySavedKeys = keys;
}
else
{
/* Key interrupt handled here */
}
//检测按键 S2 是否按下这里需要改成低电平按下
if (HAL_PUSH_BUTTON1())
{
keys |= HAL_KEY_SW_6;
}
if (keys && (pHalKeyProcessFunction))
{
(pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);
}
}
----------------------------------------------------------------
#define PUSH1_POLARITY ACTIVE_LOW
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
{
}
此函数注册到 SampleApp_TaskID 中了,就是说按键信息会传递到此任务中。
{
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;
(void)shift; // Intentionally unreferenced parameter
if ( keys & HAL_KEY_SW_6 )
{
HalUARTWrite(0, "key S2\n", 7);
}
----------------------------------------------------------------
按键总体框架图
中断方式
HalKeyConfig(HAL_KEY_INTERRUPT_ENABLE, OnBoard_KeyCallback);
这样就会更加节省系统资源,所以一般都是使用中断方式来检测按键。
当按下按键时会进入 P0 口中断服务函数
HAL_ISR_FUNCTION( halKeyPort0Isr, P0INT_VECTOR )
{
halProcessKeyInterrupt();
}
void halProcessKeyInterrupt (void)
{
bool valid=FALSE;
if (HAL_KEY_SW_6_PXIFG & HAL_KEY_SW_6_BIT) /* Interrupt Flag has been set */
{
HAL_KEY_SW_6_PXIFG = ~(HAL_KEY_SW_6_BIT); /* Clear Interrupt Flag */
valid = TRUE;
}
if (valid)
{
osal_start_timerEx (Hal_TaskID, HAL_KEY_EVENT, HAL_KEY_DEBOUNCE_VALUE);
}
}