广东湘恒智能科技有限公司
主营产品: 西门子PLC代理商,plc变频器,伺服电机,人机界面,触摸屏,线缆,DP接头
SIEMENS山东省济宁市 西门子代理商——西门子华北一级总代理

3.2.1 获取当前时间并决定是否切换列表

























static TickType_t prvSampleTimeNow( BaseType_t * const pxTimerListsWereSwitched ){    TickType_t xTimeNow;    /*静态变量 记录上一次调用时系统节拍值*/    PRIVILEGED_DATA static TickType_t xLastTime = ( TickType_t ) 0U;    /*获取本次调用节拍结束器值*/    xTimeNow = xTaskGetTickCount();
   /*判断节拍计数器是否溢出过*/    if( xTimeNow < xLastTime )    {        /*发生溢出,处理当前链表上所有定时器并切换管理链表*/        prvSwitchTimerLists();        *pxTimerListsWereSwitched = pdTRUE;    }    else    {        *pxTimerListsWereSwitched = pdFALSE;    }    /*更新时间记录*/    xLastTime = xTimeNow;
   return xTimeNow;}

可以看到, 该函数每次调用都会记录当前系统节拍时间(TickCount), 下一次调用,通过比较相邻两次调用的值判断节拍计数器是否溢出。当系统节拍计数器溢出, 必须切换计时器列表。如果当前计时器列表中仍然引用任何计时器,那么它们一定已经过期,应该在切换列表之前进行处理。

切换列表的具体内容如下:


















































static void prvSwitchTimerLists( void ){    TickType_t xNextExpireTime, xReloadTime;    List_t *pxTemp;    Timer_t *pxTimer;    BaseType_t xResult;
   /* 列表非空,循环处理,直至将该列表处理完 */    while( listLIST_IS_EMPTY( pxCurrentTimerList ) == pdFALSE )    {        xNextExpireTime = listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxCurrentTimerList );
       /* 从列表中移除软件定时器 */        pxTimer = ( Timer_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );        ( void ) uxListRemove( &( pxTimer->xTimerListItem ) );        traceTIMER_EXPIRED( pxTimer );
       /*执行回调函数*/        pxTimer->pxCallbackFunction( ( TimerHandle_t ) pxTimer );
       /*对于周期定时器*/        if( pxTimer->uxAutoReload == ( UBaseType_t ) pdTRUE )        {            /*计算重新加载值:下个溢出时间 + 定时周期*/            xReloadTime = ( xNextExpireTime + pxTimer->xTimerPeriodInTicks );            /*如果重新加载值>下个溢出时间,应该将计时器重新插入当前列表,以便在此循环中再次处理它*/            if( xReloadTime > xNextExpireTime )            {                listSET_LIST_ITEM_VALUE( &( pxTimer->xTimerListItem ), xReloadTime );                listSET_LIST_ITEM_OWNER( &( pxTimer->xTimerListItem ), pxTimer );                vListInsert( pxCurrentTimerList, &( pxTimer->xTimerListItem ) );            }            else/*否则,应该发送一个命令来重新启动计时器,以确保它只插入到列表之后列表已被交换*/            {                xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY );                configASSERT( xResult );                ( void ) xResult;            }        }        else        {            mtCOVERAGE_TEST_MARKER();        }    }
   pxTemp = pxCurrentTimerList;    pxCurrentTimerList = pxOverflowTimerList;    pxOverflowTimerList = pxTemp;}

(切换列表这里还没完全弄明白)

下面来看一下如何处理到时(或超时)的定时器:

3.2.2 处理超时的定时器




































/* 处理超时的定时器 */static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ){    BaseType_t xResult;    /* 获取最近的超时定时器 */    Timer_t *const pxTimer = ( Timer_t * )listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList );     /* 将最近的超时定时器从活跃列表中移除 */    (void)uxListRemove( &( pxTimer->xTimerListItem ) );    traceTIMER_EXPIRED(pxTimer);     /* 周期定时 */    if( pxTimer->uxAutoReload == ( UBaseType_t )pdTRUE )    {        /* 重新计算超时时间并加入活跃列表,如果下一次超时时间都已经过了 */        if( prvInsertTimerInActiveList( pxTimer, ( xNextExpireTime + pxTimer->xTimerPeriodInTicks ), xTimeNow, xNextExpireTime ) != pdFALSE )        {            /* 通知守护任务来处理(将定时器插入活跃列表) */            xResult = xTimerGenericCommand( pxTimer, tmrCOMMAND_START_DONT_TRACE, xNextExpireTime, NULL, tmrNO_DELAY );            configASSERT( xResult );            ( void )xResult;        }        else        {            mtCOVERAGE_TEST_MARKER();        }    }    else    {        mtCOVERAGE_TEST_MARKER();    }     /* 调用回调函数 */    pxTimer->pxCallbackFunction( ( TimerHandle_t )pxTimer );}



展开全文
相关产品
拨打电话 微信咨询 发送询价