上图展示了单次定时器和周期定时器之间的差异,图中的垂直虚线的间隔时间为一个单位 时间,可以理解为一个系统时钟节拍。其中 Timer1 为周期定时器,定时超时时间为 2 个单位时 间,Timer2 为单次定时器,定时超时时间为 1 个单位时间。可以看到,Timer1 在开启后,一直 以 2 个时间单位的时间间隔重复执行,为 Timer2 则在第一个超时后就不在执行了。
复位软件定时器
除了开启和停止软件定时器的定时,还可以对软件定时器进行复位。复位软件定时器会使 软件定时器的重新开启定时,复位后的软件定时器以复位时的时刻作为开启时刻重新定时,软 件定时器的复位示意图如下图所示:
上图展示了软件定时器的复位过程,图中在 t0 时刻创建并启动了一个超时时间为 5 个单位 时间的软件定时器,接着在 t3 时刻对软件定时器进行了复位,复位后软件定时器的超时时刻以 复位时刻为开启时刻重新计算,在 t7 时刻又再次对软件定时器进行了复位,最终计算出软件定 时器的超时时刻为最后一次复位的时刻(t7)加上软件定时器的超时时间(5 个单位时间),于 是该软件定时器在 t12 时刻超时,并执行其超时回调函数。
FreeRTOS 软件定时器相关配置
开启软件定时器定时
FreeRTOS 提供了两个用于开启软件定时器定时的 API 函数,这个两个函数分别用于在任 务和在中断中开启软件定时器定时。 在任务中开启软件定时器定时 API 函数的函数原型如下所示:
函数 xTimerStart()的形参描述,如下表所示:
复位软件定时器定时
FreeRTOS 提供了两个用于复位软件定时器定时的 API 函数,这个两个函数分别用于在任 务和在中断中复位软件定时器定时。 在任务中复位软件定时器定时 API 函数的函数原型如下所示:
函数 xTimerReset()的形参描述,如下表所示:
更改软件定时器的定时超时时间
FreeRTOS 提供了两个分别用于任务和中断的更改软件定时器的定时超时时间的 API 函数。 在任务中更改软件定时器的定时超时时间 API 函数的函数原型如下所示:
函数 xTimerChangePeriod()的形参描述,如下表所示:
删除软件定时器
FreeRTOS 提供了用于删除软件定时器的 API 函数,函数原型如下所示:
函数 xTimerDelete()的形参描述,如下表所示:
FreeRTOS 软件定时器操作实验
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY (3)
#define configTIMER_QUEUE_LENGTH 10
#define configTIMER_TASK_STACK_DEPTH 256
然后是定时器1和定时器2任务的定义:
这里特别注意关于ID号的定义和设置。
TimerHandle_t Timer1Timer_Handler;
TimerHandle_t Timer2Timer_Handler;
unsigned char timer1_id = 1;
unsigned char timer2_id[] = "ID02";
void start_task(void *pvParameters)
{
taskENTER_CRITICAL();
Timer1Timer_Handler = xTimerCreate(
(const char*)"Timer1",
(TickType_t) 1000,
(UBaseType_t)pdTRUE,
(void *) &timer1_id,
(TimerCallbackFunction_t)Timer1Callback);
Timer2Timer_Handler = xTimerCreate(
(const char*)"Timer2",
(TickType_t) 1000,
(UBaseType_t)pdFALSE,
(void *) timer2_id,
(TimerCallbackFunction_t)Timer2Callback);
xTaskCreate((TaskFunction_t )task_1_task,
(const char* )"task_1_task",
(uint16_t )TASK_1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK_1_PRIO,
(TaskHandle_t* )&Task_1_Task_Handler);
vTaskDelete(StartTask_Handler);
taskEXIT_CRITICAL();
}
然后是定时器1和定时器2回调函数的定义:
这里也需要特别注意关于ID号的处理操作。
void Timer1Callback(TimerHandle_t xTimer)
{
unsigned char *id;
printf("定时器名称:%s.\r\n", pcTimerGetName(Timer1Timer_Handler));
id = (unsigned char *)pvTimerGetTimerID(Timer1Timer_Handler);
printf("定时器ID号:%d.\r\n", *id);
timer1_run_counter++;
printf("定时器运行次数:%d.\r\n", timer1_run_counter);
}
void Timer2Callback(TimerHandle_t xTimer)
{
unsigned char *id;
printf("定时器名称:%s.\r\n", pcTimerGetName(Timer2Timer_Handler));
id = (unsigned char *)pvTimerGetTimerID(Timer2Timer_Handler);
printf("定时器ID号:%s.\r\n", id);
timer2_run_counter++;
printf("定时器运行次数:%d.\r\n", timer2_run_counter);
}
最后是定时器1和定时器2开启和关闭逻辑函数:
void task_1_task(void *pvParameters)
{
if(Timer1Timer_Handler != NULL)
{
printf("定时器1创建成功!\r\n");
xTimerStart((TimerHandle_t)Timer1Timer_Handler, (TickType_t)portMAX_DELAY);
printf("定时器1开启成功!\r\n");
}
if(Timer2Timer_Handler != NULL)
{
printf("定时器2创建成功!\r\n");
xTimerStart((TimerHandle_t)Timer2Timer_Handler, (TickType_t)portMAX_DELAY);
printf("定时器2开启成功!\r\n");
}
while(1)
{
if(timer1_run_counter >= 10)
{
xTimerStop((TimerHandle_t)Timer1Timer_Handler, (TickType_t)portMAX_DELAY);
printf("定时器1关闭成功!\r\n");
printf("任务删除");
vTaskDelete(Task_1_Task_Handler);
}
vTaskDelay(500);
}
}
下载验证