软件定时器在被创建之后,当经过设定的时钟计数值后会触发用户定义的回调函数。 定时精度与系统时钟的周期有关。一般系统利用 SysTick 作为软件定时器的基础时钟,软件定时器的回调函数类似硬件的中断服务函数,所以,回调函数也要快进快出,而且回调函数中不能有任何阻塞任务运行的情况,比如 vTaskDelay() 以及其它能阻塞任务运行的函数,两次触发回调函数的时间间隔 xTimerPeriodInTicks 叫定时器的定时周期。
FreeRTOS 提供的软件定时器支持单次模式和周期模式,单次模式和周期模式的定时时间到之后都会调用软件定时器的回调函数,用户可以在回调函数中加入要执行的工程代码。
单次模式:当用户创建了定时器并启动了定时器后,定时时间到了,只执行一次回调函数之后就将该定时器删除,不再重新执行。
周期模式:这个定时器会按照设置的定时时间循环执行回调函数,直到用户将定时器删除。
FreeRTOS 通过一个 prvTimerTask 任务(也叫守护任务 Daemon)管理软定时器,它是在启动调度器时自动创建的,为了满足用户定时需求。prvTimerTask 任务会在其执行期间检查用户启动的时间周期溢出的定时器,并调用其回调函数。只有设置 FreeRTOSConfig.h
中的宏定义configUSE_TIMERS
设置为 1 ,将相关代码编译进来,才能正常使用软件定时器相关功能。
在操作系统中,通常软件定时器以系统节拍周期为计时单位。系统节拍是系统的心跳节拍,表示系统时钟的频率,就类似人的心跳,1s 能跳动多少下,系统节拍配置为configTICK_RATE_HZ
,该宏在 FreeRTOSConfig.h
中有定义,默认是1000。那么系统的时钟节拍周期就为1ms(1s 跳动1000 下,每一下就为1ms)。软件定时器的所定时数值必须是这个节拍周期的整数倍,例如节拍周期是 10ms,那么上层软件定时器定时数值只能是10ms,20ms,100ms 等,而不能取值为 15ms。由于节拍定义了系统中定时器能够分辨的精确度,系统可以根据实际系统 CPU 的处理能力和实时性需求设置合适的数值,系统节拍周期的值越小,精度越高,但是系统开销也将越大,因为这代表在 1 秒中系统进入时钟中断的次数也就越多。
configTIMER_TASK_PRIORITY
,为了更好响应,该优先级应设置为所有任务中最高的优先级。configTIMER_TASK_STACK_DEPTH
个字节。用于删除一个已经被创建成功的软件定时器,删除之后就无法使用该定时器,并且定时器相应的资源也会被系统回收释放。
停止一个软件定时器,让其进入休眠态。该函数可以在中断中使用。
获取滴答定时器的计数值,返回类型为TickType_t
创建一个软件定时器,定时为1000Tick(1000ms)
要想使用软件定时器必须在 Config parameters
中把 USE_TIMERS
选择 Enabled
来使能。
void MX_FREERTOS_Init(void) {
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
/* USER CODE END RTOS_MUTEX */
/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */
/* Create the timer(s) */
/* definition and creation of MyTimer_1 */
osTimerDef(MyTimer_1, MyTimer1_Callback);
MyTimer_1Handle = osTimerCreate(osTimer(MyTimer_1), osTimerPeriodic, NULL);
/* USER CODE BEGIN RTOS_TIMERS */
osTimerStart(MyTimer_1Handle, 1000); // 开启定时器,计数1000个Tick
//...
}
/* 在回调函数里编写实现任务*/
void MyTimer1_Callback(void const * argument)
{
/* USER CODE BEGIN MyTimer1_Callback */
HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);
/* USER CODE END MyTimer1_Callback */
}
STM32CubeMX学习笔记(33)——FreeRTOS实时操作系统使用(软件定时器)