FreeRTOS 是一个开源的实时操作系统,提供了丰富的时间管理和定时器功能,用于实现任务调度、延时等操作。在本文中,我们将深入探讨 FreeRTOS 的时间管理和定时器相关的内容。
时间管理
FreeRTOS 提供了以下几种与时间相关的管理功能:
1. vTaskDelay
函数
vTaskDelay
函数用于使任务进入阻塞状态,以实现延时功能。延时的时间以 FreeRTOS 的时钟节拍(tick)为单位。
1 2 3 4 5 6 7 8 9
| #include "FreeRTOS.h" #include "task.h"
void vTaskFunction(void *pvParameters) {
vTaskDelay(pdMS_TO_TICKS(1000)); }
|
2. vTaskDelayUntil
函数
vTaskDelayUntil
函数用于设置任务的周期性执行,它在指定的绝对时间执行任务,而不是相对于当前时间的相对延时。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #include "FreeRTOS.h" #include "task.h"
void vTaskFunction(void *pvParameters) { TickType_t xLastWakeTime = xTaskGetTickCount();
for (;;) {
vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(1000)); } }
|
3. 获取系统时间
xTaskGetTickCount
函数用于获取系统自启动以来的时钟节拍数,以及 xTaskGetTickCountFromISR
用于中断服务例程中获取时钟节拍数。
1 2 3 4 5 6 7 8
| #include "FreeRTOS.h" #include "task.h"
void vTaskFunction(void *pvParameters) { TickType_t currentTickCount = xTaskGetTickCount(); }
|
xTaskGetTickCountFromISR
是 FreeRTOS 提供的一个用于在中断服务例程(ISR,Interrupt Service Routine)中获取系统时钟节拍数的函数。由于在中断上下文中,一些 FreeRTOS API 是不允许使用的,因此需要使用特定的 ISR 版本的函数来执行相应的操作。
函数原型:
1
| TickType_t xTaskGetTickCountFromISR(void);
|
- 返回值: 当前的系统时钟节拍数(以
TickType_t
类型表示)。
示例代码
下面是一个简单的示例,演示了如何在中断服务例程中使用 xTaskGetTickCountFromISR
函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| #include "FreeRTOS.h" #include "task.h" #include "stdio.h"
void vISRFunction(void) { BaseType_t xHigherPriorityTaskWoken = pdFALSE;
TickType_t currentTickCount = xTaskGetTickCountFromISR();
vTaskNotifyGiveFromISR(, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken); }
void vTaskFunction(void *pvParameters) { for (;;) { ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
printf("Task is running. Current tick count: %lu\n", xTaskGetTickCount()); } }
int main(void) { xTaskCreate(vTaskFunction, "Task", 1000, NULL, 1, NULL);
for (;;) { vISRFunction();
vTaskDelay(pdMS_TO_TICKS(1000)); }
return 0; }
|
在上述示例中,vISRFunction
模拟一个中断服务例程,其中使用了 xTaskGetTickCountFromISR
函数来获取当前系统时钟节拍数。随后,通过 vTaskNotifyGiveFromISR
函数通知等待的任务发生了事件,并通过 portYIELD_FROM_ISR
判断是否需要进行任务切换。
请注意,在实际中断服务例程中,应该谨慎使用 FreeRTOS API,并根据实际情况选择是否需要任务切换。在某些情况下,可能需要在中断服务例程中延迟任务的执行,以避免破坏实时性。
定时器
FreeRTOS 提供了定时器作为一种更灵活的时间管理工具,可以用于周期性执行任务或在一段时间后触发事件。
1. 创建定时器
使用 xTimerCreate
函数创建定时器,并指定回调函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #include "FreeRTOS.h" #include "timers.h"
void vTimerCallback(TimerHandle_t xTimer) { }
void vTaskFunction(void *pvParameters) { TimerHandle_t xTimer = xTimerCreate( "MyTimer", pdMS_TO_TICKS(1000), pdTRUE, NULL, vTimerCallback);
if (xTimer != NULL) { xTimerStart(xTimer, 0); }
}
|
2. 定时器示例
下面是一个完整的示例,演示了如何使用 FreeRTOS 定时器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #include "FreeRTOS.h" #include "timers.h" #include "task.h"
void vTimerCallback(TimerHandle_t xTimer) { printf("Timer expired!\n"); }
void vTaskFunction(void *pvParameters) { TimerHandle_t xTimer = xTimerCreate( "MyTimer", pdMS_TO_TICKS(1000), pdTRUE, NULL, vTimerCallback);
if (xTimer != NULL) { xTimerStart(xTimer, 0);
for (;;) { } } }
int main(void) { xTaskCreate(vTaskFunction, "Task", 1000, NULL, 1, NULL); vTaskStartScheduler();
return 0; }
|
在这个示例中,创建了一个名为 “MyTimer” 的定时器,每隔 1000 毫秒触发一次回调函数 vTimerCallback
。回调函数中输出 “Timer expired!”。任务函数中启动了定时器,并进入一个无限循环的任务执行代码。
以上是 FreeRTOS 的时间管理和定时器相关内容的简要介绍。通过使用这些功能,可以更加灵活地管理任务的执行时间和周期性任务的触发。在实际项目中,合理利用时间管理和定时器功能将对系统的稳定性和实时性产生积极影响。
项目实例
假设我们正在开发一个嵌入式系统,这个系统负责控制智能家居中的温度和湿度监控。我们需要定期采集传感器数据,更新显示,以及根据设定的温度阈值触发相应的控制操作。在这个项目中,时钟和定时器将起到关键作用。
1. 系统初始化
首先,在系统初始化阶段,我们需要初始化 FreeRTOS 时钟节拍和创建定时器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #include "FreeRTOS.h" #include "task.h" #include "timers.h"
TaskHandle_t xTaskHandle; TimerHandle_t xTimerHandle;
void vTemperatureTask(void *pvParameters);
void vTimerCallback(TimerHandle_t xTimer);
int main(void) { xTaskCreate(vTemperatureTask, "TemperatureTask", 1000, NULL, 1, &xTaskHandle);
xTimerHandle = xTimerCreate("SensorTimer", pdMS_TO_TICKS(1000), pdTRUE, (void *)0, vTimerCallback);
if (xTimerHandle != NULL) { xTimerStart(xTimerHandle, 0); }
vTaskStartScheduler();
return 0; }
|
2. 温度任务
温度任务周期性地采集传感器数据,并更新显示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| #include "FreeRTOS.h" #include "task.h"
void vTemperatureTask(void *pvParameters) { for (;;) { float temperature = readTemperatureSensor();
updateDisplay(temperature);
vTaskDelay(pdMS_TO_TICKS(5000)); } }
|
3. 定时器回调函数
定时器回调函数用于检查温度是否超过设定的阈值,并触发相应的控制操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #include "FreeRTOS.h" #include "timers.h"
void vTimerCallback(TimerHandle_t xTimer) { float currentTemperature = readTemperatureSensor();
if (currentTemperature > TEMPERATURE_THRESHOLD) { controlTemperature(currentTemperature); } }
|
通过这个示例,我们展示了在一个智能家居温控系统中如何利用 FreeRTOS 的时钟和定时器功能。温度任务定期采集传感器数据,而定时器回调函数则用于实时监测温度并触发相应的控制操作。这种基于时钟和定时器的任务调度方式可以确保系统按照预定的周期执行任务,提高系统的实时性和可靠性。