1. 程式人生 > >使用FREERTOS軟體定時器組

使用FREERTOS軟體定時器組

    剛剛學會用FREERTOS,剛好稱公司專案需要,就學習著用,有幾個定時需求,本來想使用硬體中斷定時器,再用軟體做個分組定時,剛好看到FREERTOS有軟體定時器組,就想用用試試看效果;

    使用的是FREERTOSV10.0.1,MCU用的是STM32F205RET6,定時需要都是10S,2S,3S,最小單位為ms級;

FREERTOS預設定時為1MS,即#define configTICK_RATE_HZ( ( TickType_t ) 1000 )

減小此值,定時精度更準,但開銷更大,增大此值,精度變低;

1、移植好FREERTOS並編譯好後,需要在freertosconfig.h增加軟體定時器巨集定義,如下

/* set soft timers para. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY  2
#define configTIMER_QUEUE_LENGTH   3
#define configTIMER_TASK_STACK_DEPTH    512

/*end of set soft timer para */

configUSE_TIMERS  即使能,軟體定時器實際上也是一種queue形式任務,故需要設定優先順序,長度與深度;

2、建立任務

void UserTimerCreate (void)
{
uint8_t i;
for(i = 0;i< TIMER_MAX; i++)
{
xTimersName[i] = xTimerCreate("Timer",  
timer_len[i],  
pdTRUE,
(void *) timer_id[i],   
  vTimerCallback);
if(xTimersName[i] == NULL)
{
printf("timer cread is error, timer id is:%d",timer_id[i]); 
}
else
{
  printf("timer cread is ok, timer id is:%d\n\r",timer_id[i]); 
  if(xTimerStart(xTimersName[i], 100) != pdPASS)
  {
  printf("timer is start timer id is:%d\n\r",timer_id[i]); 
  }
}
}
}

其中

timer_len[i],即每個定時成員定時長度,值=1即為1ms,

timer_id[i]即返回的控制代碼,用於判別是哪個定時到達;

xTimerStart()用於啟動定時器任務;

vTimerCallback(),回撥函式,用於處理定時到達任務,一個回撥函式可以多個定時任務,通過控制代碼判別定時ID;

2、處理定時

void vTimerCallback(TimerHandle_t xTimer)
{
uint8_t i;
float temp;
User_Timers_Id ulTimerID;
ulTimerID = (User_Timers_Id)pvTimerGetTimerID(xTimer);
if(ulTimerID == timer_id[TIMER_BUTTON_CHECK])
{
Button_check();
if(xTimerStart(xTimersName[TIMER_BUTTON_CHECK], 10) != pdPASS)
{
printf("restart timer id:%d\n\r",timer_id[TIMER_BUTTON_CHECK]); 
}

}

}

其中

(1)、pvTimerGetTimerID即獲取定時ID,定時到達即可作相應定時處理;

(2)、定時處理完畢後,重新啟動;

3、變更定時時長

void xTimerChPeriod( TimerHandle_t xTimer ,const BaseType_t new_Period)
{
BaseType_t wait_time;
wait_time = 300;
     // 修改定時器週期
     if(pre_Period == new_Period)
 {
 }
else
{
if(xTimerStopFromISR(xTimersName,&wait_time) == pdPASS)
{
    if( xTimerChangePeriodFromISR( xTimer, 
           /*修改定時週期*/
           new_Period, 
       /*允許阻塞最大時間 1s*/
       &wait_time ) != pdPASS )
    {
        // update fail
        // 阻塞 100 tick 仍然無法傳送命令
        // 刪除定時器 釋放對應記憶體!
        //xTimerDelete( xTimer );
 //PRINTF("change timer period is error ,stop timer\r\n");
    }
    else 
    {
//PRINTF("change timer period is succes ,then start ,new period is:%d s\r\n",new_Period);
if(xTimerStartFromISR(xTimersName, &wait_time) != pdPASS)
{
//PRINTF("timer is restart\r\n"); 
}
    }
}
}

}

其中:

1、xTimerStopFromISR,停止定時器,用於中斷函式中,非中斷函式用xTimerStop;

2、xTimerChangePeriodFromISR,也是用於中斷,非中斷用xTimerChangePeriod;