您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 交通运输 > ZigBee学习之35—按键部分及系统调用时钟的分析2
#1楼主:【原创】ZigBee学习之35——按键部分及系统调用时钟的分析2文章发表于:2010-02-1723:57/*Timer2最为系统任务的时钟系统*/OnboardTimerIntEnable=FALSE;HalTimerConfig(OSAL_TIMER,//8bittimer2HAL_TIMER_MODE_CTC,//ClearTimeronCompareHAL_TIMER_CHANNEL_SINGLE,//Channel1-defaultHAL_TIMER_CH_MODE_OUTPUT_COMPARE,//OutputComparemodeOnboardTimerIntEnable,//UseinterruptOnboard_TimerCallBack);//ChannelMode//函数执行后得到系统任务时钟(HAL_TIMER_2)的配置结构:halTimerRecord[hwtimerid].configured=TRUE;halTimerRecord[hwtimerid].opMode=HAL_TIMER_MODE_CTC;halTimerRecord[hwtimerid].channel=HAL_TIMER_CHANNEL_SINGLE;halTimerRecord[hwtimerid].channelMode=HAL_TIMER_CH_MODE_OUTPUT_COMPARE;halTimerRecord[hwtimerid].intEnable=FALSE;halTimerRecord[hwtimerid].callBackFunc=Onboard_TimerCallBack;//Onboard_TimerCallBack()为处理系统时钟的回调函数,这个函数什么时候会被调用呢?是个问题//一些相关宏的定义如下://#defineHAL_TIMER_MODE_CTC0x02//ClearTimerOnCompare//#defineHAL_TIMER_CHANNEL_SINGLE0x01//SingleChannel-default//#defineHAL_TIMER_CH_MODE_OUTPUT_COMPARE0x02//ChannelModeOutput_Compare//现在系统任务时钟所需要使用的定时器已经配置好了,但是如何启动的呢?启动定时器必须要对TxCTL寄存器启动位置位才能启动啊!我们回到ZMain.c中的main()中,在InitBoard(OB_COLD);下面接着执行的是HalDriverInit()函数,在此函数中最开始就是初始化了定时器HalTimerInit();进去一看发现任然没有启动定时器!仅仅只是对定时器的寄存器进行了一个别名配置而已,增加了如下的配置:halTimerRecord[HW_TIMER_4].prescale=HAL_TIMER4_8_PRESCALE;halTimerRecord[HW_TIMER_4].clock=HAL_TIMER_32MHZ;halTimerRecord[HW_TIMER_4].prescaleVal=HAL_TIMER4_8_PRESCALE_VAL;/*SetupTimer4Channelstructure*/halTimerChannel[HW_TIMER_4].TxCCTL=TCHN_T4CCTL;halTimerChannel[HW_TIMER_4].TxCCL=TCHN_T4CCL;halTimerChannel[HW_TIMER_4].TxCCH=TCHN_T4CCH;halTimerChannel[HW_TIMER_4].TxOVF=TCNH_T4OVF;halTimerChannel[HW_TIMER_4].ovfbit=TCHN_T4OVFBIT;halTimerChannel[HW_TIMER_4].intbit=TCHN_T4INTBIT;那么是不是初始在main()中的osal_init_system();【OSAL.c】函数中,好,那我们来看一下,是不是这里启动了系统时钟定时器。在这个函数中又调用了一个函数嫌疑最大:osalTimerInit();【OSAL_Timers.c】voidosalTimerInit(void){//初始化了两个变量//#defineTICK_TIME1000//#defineTIMER_DECR_TIME1tmr_count=TICK_TIME;tmr_decr_time=TIMER_DECR_TIME;//这里是停止了系统时钟定时器OSAL_TIMERosal_timer_activate(false);timerActive=false;osal_systemClock=0;}//看来在这个函数中也没有启动系统定时器,反而调用了停止系统时钟定时器的函数,莫非是黎明前的黑暗,呵呵!接着在main()函数中找嫌疑犯!再往下是打开了总中断osal_int_enable(INTS_ALL);剩下的可能在就是osal_start_system()中启动系统时钟了,我们来找一下。//在此函数中调用了Hal_ProcessPoll()【hal_drivers.c】voidHal_ProcessPoll(){/*TimerPoll*/HalTimerTick();//这个函数又是个跟时钟相关的函数,会不会在这里面启动系统时钟呢?来看一下/*UARTPoll*/#if(definedHAL_UART)&&(HAL_UART==TRUE)HalUARTPoll();#endif}//【hal_timer.c】voidHalTimerTick(void){//前面调用的InitBoard()中已经设置halTimerRecord[hwtimerid].intEnable=FALSE;//再根据HAL_TIMER_2--HWTimer4,所以会执行以下函数:…………if(!halTimerRecord[HW_TIMER_4].intEnable){halProcessTimer4();}}//继续跟踪。这个函数在定时器发生中断的时候就会执行,因为在定时器4中断中有调用此函数:HAL_ISR_FUNCTION(halTimer4Isr,T4_VECTOR){halProcessTimer4();}voidhalProcessTimer4(void){if(halTimerRecord[halTimerRemap(HAL_TIMER_2)].channelMode==HAL_TIMER_CH_MODE_OUTPUT_COMPARE){if(TIMIF&TIMIF_T4CH0IF){//定时器4通道0产生中断TIMIF&=~(TIMIF_T4CH0IF);//清除中断标志halTimerSendCallBack(HAL_TIMER_2,HAL_TIMER_CHANNEL_A,HAL_TIMER_CH_MODE_OUTPUT_COMPARE);//调用前面初始化的回调函数,对系统时钟+1}if(TIMIF&TIMIF_T4CH1IF){TIMIF&=~(TIMIF_T4CH1IF);halTimerSendCallBack(HAL_TIMER_2,HAL_TIMER_CHANNEL_B,HAL_TIMER_CH_MODE_OUTPUT_COMPARE);}}…………}//貌似还没有看到启动系统时钟的定时器啊!呵呵别急,我们现在回过来看按键程序,我们接着分析这个函数:byteosal_start_timerEx(bytetaskID,UINT16event_id,UINT16timeout_value){halIntState_tintState;osalTimerRec_t*newTimer;HAL_ENTER_CRITICAL_SECTION(intState);//Holdoffinterrupts.//为此任务和事件填充一个新定时器数据结构,这个结构中将包含计数时间,要传递的时间,接收事件的任务newTimer=osalAddTimer(taskID,event_id,timeout_value);if(newTimer){#ifdefPower_SAVING//Updatetimerregistersosal_retune_timers();(void)timerActive;#endifif(timerActive==FALSE){//这里要注意了,回想一下我们对系统时钟启动的分析,只发现停止了系统时钟,初始timerActive==FALSE,现在终于启动定时器了。而且处于开中断的状态下,这样的话当计时器溢出的时候当然会产生中断就去执行中断函数了。所以我们得出系统时钟也不是每时每刻都在运行的!(在中断方式下启动定时器)osal_timer_activate(TRUE);}}HAL_EXIT_CRITICAL_SECTION(intState);//Re-enableinterrupts.return((newTimer!=NULL)?ZSUCCESS:NO_TIMER_AVAIL);}}//我们再来看一下中断服务函数,我的是用P1口:HAL_ISR_FUNCTION(halKeyPort1Isr,P1INT_VECTOR){//刚开始是对芯片版本的判断,这个部重要了,可以去掉判断直接清除P1IF标志位if(CHVER=REV_D){P1IF=0;}//这个函数是清除端口每一位的子中断,然后继续进行先前的任务,即发送按键事件HAL_KEY_EVENT给指定的任务halProcessKeyInterrupt();if(CHVER=REV_E){//大于版本E的清除中断后进入睡眠模式P1IF=0;CLEAR_SLEEP_MODE();}}//注意在ZStack1.4.3-1.2.1中对于任务的管理是通过任务表来进行的,每个任务由初始化函数和事件处理函数构成,任务的初始化通过osalInitTasks()进行,然后OSAL利用任务表来调用任务函数,注意任务表中的顺序必须和任务初始化的顺序一致//任务处理函数表,在后面可以添加自己的任务处理函数【sapi.c】constpTaskEventHandleRFntasksArr[]={macEventLoop,nwk_event_loop,Hal_ProcessEvent,#ifdefined(MT_TASK)MT_ProcessEvent,#endifAPS_event_loop,ZDApp_event_loop,SAPI_ProcessEvent};voidosalInitTasks(void){uint8taskID=0;tasksEvents=(uint16*)osal_mem_alloc(sizeof(uint16)*tasksCnt);osal_memset(tasksEvents,0,(sizeof(uint16)*tasksCnt));macTaskInit(taskID++);nwk_init(taskID++);Hal_Init(taskID++);#ifdefined(MT_TASK)MT_TaskInit(taskID++);#endifAPS_Init(taskID++);ZDApp_Init(taskID++);SAPI_Init(taskID);}//有一条主线:osal_set_event()将事件存入tasksEvents数组中【或者:通过HalTimerConfig()配置定时器的回调函数——对指定任务和事件调用osal_start_timerEx()等指定超时时间到达后通过调用回调函数来调用osal_set_event()】——系统主循环中检查到tasksEvents数组中有事件——调用相应的接收事件的函数(tasksArr[idx])(idx,events)——Hal_ProcessEven
本文标题:ZigBee学习之35—按键部分及系统调用时钟的分析2
链接地址:https://www.777doc.com/doc-2829776 .html