ReeRTOS中加入了软件定时器这个功能组件,是一个可选的、不属于freeRTOS内核的功能,由定时器服务(其实就是一个定时器任务)来提供。
软件定时器是当设定一个定时时间,当达到设定的时间之后就会执行指定的功能函数,而这个功能函数就叫做回调函数。
也就是说回调函数的两次执行间隔叫做定时器的定时周期。
回调函数:回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。
软件定时器在被创建之后,当经过设定的时钟计数值后会触发用户定义的回调函数。 定时精度与系统时钟的周期有关。一般系统利用 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 秒中系统进入时钟中断的次数也就越多。
7.3 注意要点
软件定时器的回调函数中应快进快出,绝对不允许使用任何可能引软件定时器起任务挂起或者阻塞的 API 接口,在回调函数中也绝对不允许出现死循环。
软件定时器使用了系统的一个队列和一个任务资源,软件定时器任务的优先级默
认为 configTIMER_TASK_PRIORITY,为了更好响应,该优先级应设置为所有任务中最高的优先级。
创建单次软件定时器,该定时器超时执行完回调函数后,系统会自动删除该软件定时器,并回收资源。
定时器任务的堆栈大小默认为 configTIMER_TASK_STACK_DEPTH 个字节。
1.RCC和时钟树的配置
2.时基设置
3.FreeTROS的设置
开启FreeRTOS,v1与v2版本不同,一般选用v1即可
在 Config parameters 进行具体参数配置。
这里一般默认就好了
然后打开软件定时器使能
Timer Name: 定时器名称
Callback: 回调函数名称
Type: 定时器类型,osTimerPeriodic周期定时器,osTimerOnce单次定时器
Code Generation Option: 代码生成选项
Parameter: 回调函数形参,不用的时候配置为0或NULL即可
Allocation: 分配方式:Dynamic 动态内存创建
Conrol Block Name: 控制块名称
TimerHandle_t xTimerCreate
(
const char * const pcTimerName, /* 定时器名字 */
const TickType_t xTimerPeriod, /* 定时器周期 */
const UBaseType_t uxAutoReload, /* 选择单次模式或者周期模式 */
void * const pvTimerID, /* 定时器 ID */
TimerCallbackFunction_t pxCallbackFunction ); /* 定时器回调函数 */
函数描述:函数 xTimerCreate 用于创建软件定时器。
参数:
1)第 1 个参数:定时器名字,一般用于调试,方便识别不同的定时器。
2)第 2 个参数:定时器周期,单位是系统时钟节拍。
3)第 3 个参数:选择定时器是周期模式还是单次模式。若参数为 pdTRUE,则表示选择周期模式,若参数为
pdFALSE,则表示选择单次模式。
4)第 4 个参数:定时器的 ID。当创建多个不同的定时器,但又使用同一个回调函数时,在回调函数中就可以通过不同的
ID 号来区分不同的定时器。
5)第 5 个参数:定时器的回调函数。
返回值:创建成功返回定时器的句柄,失败会返回 NULL。
示例如下:创建一个单次触发的软件定时器
TimerHandle_t singalTIMERS; //单次定时器
void singalTimersFunc(TimerHandle_t xTimers); //单次定时器回调函数
/*创建单次定时器*/
singalTIMERS = xTimerCreate(
"singalTIMERS", //软件定时器的名字
1000, //定时周期,单位是时钟节拍数
pdFALSE, //定时器模式,pdTRUE为周期定时器,pdFALSE为单次定时器
(void*)1, //定时器的ID号
singalTimersFunc //定时器回调函数
);//
1)在任务中启动
BaseType_t xTimerStart( TimerHandle_t xTimer, /* 定时器句柄 */
TickType_t xBlockTime ); /* 成功启动定时器前的最大等待时间设置,单位系统时钟节拍 */
函数描述:函数 xTimerStart 用于启动软件定时器。
参数:
1> 第 1 个参数是定时器句柄。
2> 第 2 个参数是成功启动定时器前的最大等待时间设置,单位系统时钟节拍。这是定时器组的大部分 API函数不是直接运行的,而是通过消息队列给定时器任务发消息来实现的,此参数设置的等待时间就是当消息队列已经满的情况下,等待消息队列有空间时的最大等待时间。
返回值:返回 pdFAIL 表示此函数向消息队列发送消息失败,返回 pdPASS 表示此函数向消息队列发送消息成功。
注意:定时器任务实际执行消息队列发来的命令依赖于定时器任务的优先级,如果定时器任务是高优先级会及时得到执行,如果是低优先级,就要等待其余高优先级任务释放 CPU 权才可以得到执行。
BaseType_t xTimerStartFromISR(TimerHandle_t xTimer
BaseType_t* pxHigherPriorityTaskWoken);
函数描述:在中断中启动定时器
参数:
XTimer:软件定时器的句柄
pxHigherPriorityTaskWoken:退出此函数时是否要进行任务切换
返回值: pdPASS:软件定时器开启成功。pdFAIL:软件定时器开启失败。
1)函数描述:在任务中停止软件定时器
BaseType_t xTimerStop(TimerHandle_t xTime,
TickType_t xTicksToWait)
参数:
xTimer:软件定时器的句柄。
xTicksToWait:阻塞时间,即停止定时器最大的等待时间。
返回值:pdPASS:软件定时器停止成功pdFAIL:软件定时器停止失败
2)在中断中停止软件定时器
xTimerStopFormISR(TimerHandle_t xTimer,
BaseType_t pxHigherPriorityTaskWoken);
函数描述:
参数:
xTimer:软件定时器句柄
pxHigherPriorityTaskWoken:退出此函数时是否要进行任务切换
返回值:pdPASS:软件定时器开启成功。 pdFAIL:软件定时器开启失败。
函数描述:在任务中复位
BaseType_t xTimerReset(TimerHandle_t xTimer,
TickType_t xTicksToWait)
参数:
xTimer:软件定时器的句柄。
xTicksToWait:阻塞时间,即停止定时器最大的等待时间。
返回值:pdPASS:软件定时器复位成功 pdFAIL:软件定时器复位失败
函数描述:在中断中复位
BaseType_t xTimerResetFromISR(TimerHandle_t xTimer,
BaseType_t *pxHigherPriorityTaskWoken);
参数:
xTimer:软件定时器句柄
pxHigherPriorityTaskWoken:退出此函数时是否要进行任务切换
返回值:pdPASS:软件定时器复位成功。pdFAIL:软件定时器复位失败。
BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer )
函数描述:查询定时器以查看它是活动的还是休眠的。
参数:xTimer 定时器句柄
返回值: pdFALSE,没有运行。其他值,运行。
如果出现以下情况,计时器将处于休眠状态:
已创建但未启动。
已过期的计时器尚未重新启动。
osTimerId osTimerCreate (const osTimerDef_t *timer_def, os_timer_type type, void *argument)
函数描述:创建一个软件定时器,并返回一个定时器ID。
参数:
timer_def: 引用由osTimerDef定义的定时器
type: 设置为 osTimerPeriodic,那么软件定时器的工作模式就是周期模式, 一直会以用户指定的 xTimerPeriod 周期去执行回调函数。如果设置为 osTimerOnce,那么软件定时器就在用户指定的 xTimerPeriod 周期下运行一次后就进入休眠态
argument: 回调函数传入形参
返回值:成功返回定时器ID,失败返回0
osStatus osTimerStart (osTimerId timer_id, uint32_t millisec)
函数描述:启动软件定时器。该函数可以在中断中使用。
参数:
timer_id: 定时器ID
millisec: 用户指定的超时时间,单位为系统节拍周期(即 tick),如果在 FreeRTOS 调度器开启之前调用 osTimerStart(),该形参将不起作用
返回值:错误码
osStatus osTimerStop (osTimerId timer_id)
函数描述:停止一个软件定时器,让其进入休眠态。该函数可以在中断中使用。
参数:timer_id: 定时器ID
返回值:错误码
osStatus osTimerDelete (osTimerId timer_id)
函数描述:用于删除一个已经被创建成功的软件定时器,删除之后就无法使用该定时器,并且定时器相应的资源也会被系统回收释放。
参数:timer_id: 定时器ID
返回值:错误码
在FreeRTOS初始化这里打开软件定时器
/* USER CODE BEGIN RTOS_THREADS */
osTimerStart(myTimer1Handle,500);
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
在定时器回调函数添加代码:
void CallbackTimer1(void const * argument)
{
/* USER CODE BEGIN CallbackTimer1 */
HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
/* USER CODE END CallbackTimer1 */
}