当前位置: 代码迷 >> 综合 >> 从0到1学习FreeRTOS:FreeRTOS 内核应用开发:(二十一)软件定时器 NO.2 函数接口讲解
  详细解决方案

从0到1学习FreeRTOS:FreeRTOS 内核应用开发:(二十一)软件定时器 NO.2 函数接口讲解

热度:49   发布时间:2023-12-16 14:09:27.0

从0到1学习FreeRTOS:FreeRTOS 内核应用开发:(二十一)软件定时器 NO.2 函数接口讲解

目录

一、软件定时器创建函数 xTimerCreate()

二、软件定时器启动函数:

三、软件定时器停止函数:

四、软件定时器任务:

五、软件定时器删除函数 xTimerDelete()


一、软件定时器创建函数 xTimerCreate()

        xTimerCreate()用于创建一个软件定时器,并返回一个句柄。 要想使用该函数函数必须在头文件FreeRTOSConfig.h中把宏configUSE_TIMERS 和configSUPPORT_DYNAMIC_ALLOCATION 均定义为 1(configSUPPORT_DYNAMIC_ALLOCATION 在 FreeRTOS.h 中默认定义为 1) , 并且需要把 FreeRTOS/source/times.c 这个 C 文件添加到工程中。

        软件定时器在创建成功后是处于休眠状态, 可以使用 xTimerStart()、 xTimerReset()、xTimerStartFromISR() 、 xTimerResetFromISR() 、 xTimerChangePeriod() 和xTimerChangePeriodFromISR()这些函数将其状态转换为活跃态

static TimerHandle_t Swtmr1_Handle =NULL; /* 软件定时器句柄 */
static TimerHandle_t Swtmr2_Handle =NULL; /* 软件定时器句柄 */
/* 周期模式的软件定时器 1,定时器周期 1000(tick)*/
Swtmr1_Handle=xTimerCreate((const char*)"AutoReloadTimer",
(TickType_t)1000,/* 定时器周期 1000(tick) */
(UBaseType_t)pdTRUE,/* 周期模式 */
(void* )1,/* 为每个计时器分配一个索引的唯一 ID */
(TimerCallbackFunction_t)Swtmr1_Callback); /* 回调函数 */
if (Swtmr1_Handle != NULL)
{
/********************************************************************
* xTicksToWait:如果在调用 xTimerStart()时队列已满,则以 tick 为单位指定调用任务应保持
* 在 Blocked(阻塞)状态以等待 start 命令成功发送到 timer 命令队列的时间。
* 如果在启动调度程序之前调用 xTimerStart(),则忽略 xTicksToWait。在这里设置等待时间为 0.
**********************************************************************/
xTimerStart(Swtmr1_Handle,0); //开启周期定时器
}
/* 单次模式的软件定时器 2,定时器周期 5000(tick)*/
Swtmr2_Handle=xTimerCreate((const char* )"OneShotTimer",
(TickType_t)5000,/* 定时器周期 5000(tick) */
(UBaseType_t )pdFALSE,/* 单次模式 */
(void*)2,/* 为每个计时器分配一个索引的唯一 ID */
(TimerCallbackFunction_t)Swtmr2_Callback);
if (Swtmr2_Handle != NULL)
{
xTimerStart(Swtmr2_Handle,0); //开启单次定时器
}
static void Swtmr1_Callback(void* parameter)
{
/* 软件定时器的回调函数,用户自己实现 */
}
static void Swtmr2_Callback(void* parameter)
{
/* 软件定时器的回调函数,用户自己实现 */
}

二、软件定时器启动函数:

1、xTimerStart()
本质:通过“定时器命令队列”向定时器任务发送一个启动命令

#define   xTimerStart( xTimer, xTicksToWait )   xTimerGenericCommand( ( xTimer ),

                                  tmrCOMMAND_START,  

                                  ( xTaskGetTickCount() ),

                                   NULL, ( xTicksToWait ) )

2、xTimerStartFromISR()

       当然除在任务启动软件定时器之外 , 还有在中断中启动软件定时器的函数xTimerStartFromISR()。 xTimerStartFromISR()是函数 xTimerStart()的中断版本, 用于启动一个先前由函数 xTimerCreate() / xTimerCreateStatic()创建的软件定时器。

/* 这个方案假定软件定时器 xBacklightTimer 已经创建,
定时周期为 5s,执行次数为一次,即定时时间到了之后
就进入休眠态。
程序说明:当按键按下,打开液晶背光,启动软件定时器,
5s 时间到,关掉液晶背光*/
/* 软件定时器回调函数 */
void vBacklightTimerCallback( TimerHandle_t pxTimer )
{
/* 关掉液晶背光 */
vSetBacklightState( BACKLIGHT_OFF );
}
/* 按键中断服务程序 */
void vKeyPressEventInterruptHandler( void )
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
/* 确保液晶背光已经打开 */
vSetBacklightState( BACKLIGHT_ON );
/* 启动软件定时器 */
if ( xTimerStartFromISR( xBacklightTimer,
&xHigherPriorityTaskWoken ) != pdPASS ) {
/* 软件定时器开启命令没有成功执行 */
}
/* ...执行其他的按键相关的功能代码 */
if ( xHigherPriorityTaskWoken != pdFALSE ) {
/* 执行上下文切换 */
}
}

三、软件定时器停止函数:

1、xTimerStop()
       xTimerStop() 用于停止一个已经启动的软件定时器, 该函数的实现也是通过“定时器命令队列”发送一个停止命令给软件定时器任务,从而唤醒软件定时器任务去将定时器停止。 要想使函数 xTimerStop()必须在头文件 FreeRTOSConfig.h 中把宏 configUSE_TIMERS定义为 1。 

static TimerHandle_t Swtmr1_Handle =NULL; /* 软件定时器句柄 */
/* 周期模式的软件定时器 1,定时器周期 1000(tick)*/
Swtmr1_Handle=xTimerCreate((const char* )"AutoReloadTimer",
(TickType_t )1000,/* 定时器周期 1000(tick) */
(UBaseType_t )pdTRUE,/* 周期模式 */
(void*)1,/* 为每个计时器分配一个索引的唯一 ID */
(TimerCallbackFunction_t)Swtmr1_Callback); /* 回调函数 */
if (Swtmr1_Handle != NULL)
{
/********************************************************************
* xTicksToWait:如果在调用 xTimerStart()时队列已满,则以 tick 为单位指定调用任务应保持
* 在 Blocked(阻塞)状态以等待 start 命令成功发送到 timer 命令队列的时间。
* 如果在启动调度程序之前调用 xTimerStart(),则忽略 xTicksToWait。在这里设置等待时间为 0.
*******************************************************************/
xTimerStart(Swtmr1_Handle,0); //开启周期定时器
}
static void test_task(void* parameter)
{
while (1) {
/* 用户自己实现任务代码 */
xTimerStop(Swtmr1_Handle,0); //停止定时器
}
}

2、xTimerStopFromISR()
        xTimerStopFromISR()是函数 xTimerStop()的中断版本, 用于停止一个正在运行的软件定时器, 让其进入休眠态, 实现过程也是通过“定时器命令队列”向软件定时器任务发送停止命令。

/* 这个方案假定软件定时器 xTimer 已经创建且启动。
当中断发生时,停止软件定时器 */
/* 停止软件定时器的中断服务函数*/
void vAnExampleInterruptServiceRoutine( void )
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (xTimerStopFromISR(xTimer,&xHigherPriorityTaskWoken)!=pdPASS ) {
/* 软件定时器停止命令没有成功执行 */
}
if ( xHigherPriorityTaskWoken != pdFALSE ) {
/* 执行上下文切换 */
}
}

四、软件定时器任务:

       软件定时器任务是在系统开始调度( vTaskStartScheduler()函数) 的时候就被创建的,前提是将宏定义 configUSE_TIMERS 开启, 在xTimerCreateTimerTask()函数里面就是创建了一个软件定时器任务,就跟我们创建任务一样,支持动态与静态创建,我们暂时看动态创建的即可。
       软件定时器任务的处理很简单,如果当前有软件定时器在运行,那么它大部分的时间都在等待定时器到期时间的到来,或者在等待对软件定时器操作的命令,而如果没有软件定时器在运行,那定时器任务的绝大部分时间都在阻塞中等待定时器的操作命令

       软件定时器是一个任务,在下一个定时器到了之前的这段时间,系统要把任务状态转移为阻塞态,让其他的任务能正常运行,这样子就使得系统的资源能充分利用。
       其实处理这些软件定时器命令是很简单的, 当任务获取到命令消息的时候,会先移除对应的定时器,无论是什么原因,然后就根据命令去处理对应定时器的操作即可。

五、软件定时器删除函数 xTimerDelete()

       xTimerDelete()用于删除一个已经被创建成功的软件定时器, 删除之后就无法使用该定时器, 并且定时器相应的资源也会被系统回收释放。 要想使函数 xTimerStop()必须在头文件 FreeRTOSConfig.h 中把宏 configUSE_TIMERS 定义为 1。

       从软件定时器删除函数 xTimerDelete()的原型可以看出, 删除一个软件定时器也是在软件定时器任务中删除调用 xTimerDelete()将删除软件定时器的命令发送给软件定时器任务,软件定时器任务在接收到删除的命令之后就进行删除操作,

static TimerHandle_t Swtmr1_Handle =NULL; /* 软件定时器句柄 */
/* 周期模式的软件定时器 1,定时器周期 1000(tick)*/
Swtmr1_Handle=xTimerCreate((const char* )"AutoReloadTimer",
(TickType_t )1000,/* 定时器周期 1000(tick) */
(UBaseType_t)pdTRUE,/* 周期模式 */
(void* )1,/* 为每个计时器分配一个索引的唯一 ID */
(TimerCallbackFunction_t)Swtmr1_Callback); /* 回调函数 */
if (Swtmr1_Handle != NULL)
{
/****************************************************************
* xTicksToWait:如果在调用 xTimerStart()时队列已满,则以 tick 为单位指定调用任务应保持
* 在 Blocked(阻塞)状态以等待 start 命令成功发送到 timer 命令队列的时间。
* 如果在启动调度程序之前调用 xTimerStart(),则忽略 xTicksToWait。在这里设置等待时间为 0.
*****************************************************************/
xTimerStart(Swtmr1_Handle,0); //开启周期定时器
}
static void test_task(void* parameter)
{
while (1) {
/* 用户自己实现任务代码 */
xTimerDelete(Swtmr1_Handle,0); //删除软件定时器
}
}

 

  相关解决方案