刚刚学会用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;