使用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;