SIEMENS山东省济宁市 西门子代理商——西门子华北一级总代理
| 更新时间 2024-11-26 07:00:00 价格 请来电询价 西门子总代理 PLC 西门子一级代 驱动 西门子代理商 伺服电机 联系电话 15903418770 联系手机 15915421161 联系人 张经理 立即询价 |
详细介绍
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;} 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;} /* 处理超时的定时器 */static void prvProcessExpiredTimer( const TickType_t xNextExpireTime, const TickType_t xTimeNow ){ BaseType_t xResult; /* 获取Zui近的超时定时器 */ Timer_t *const pxTimer = ( Timer_t * )listGET_OWNER_OF_HEAD_ENTRY( pxCurrentTimerList ); /* 将Zui近的超时定时器从活跃列表中移除 */ (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 );}
/*判断节拍计数器是否溢出过*/ if( xTimeNow < xLastTime ) { /*发生溢出,处理当前链表上所有定时器并切换管理链表*/ prvSwitchTimerLists(); *pxTimerListsWereSwitched = pdTRUE; } else { *pxTimerListsWereSwitched = pdFALSE; } /*更新时间记录*/ xLastTime = xTimeNow;
return xTimeNow;}
可以看到, 该函数每次调用都会记录当前系统节拍时间(TickCount), 下一次调用,通过比较相邻两次调用的值判断节拍计数器是否溢出。当系统节拍计数器溢出, 必须切换计时器列表。如果当前计时器列表中仍然引用任何计时器,那么它们一定已经过期,应该在切换列表之前进行处理。
切换列表的具体内容如下:
/* 列表非空,循环处理,直至将该列表处理完 */ 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 处理超时的定时器相关产品