【FreeRTOS】详细讲解FreeRTOS的软件定时器及通过示例讲述其用法

这篇具有很好参考价值的文章主要介绍了【FreeRTOS】详细讲解FreeRTOS的软件定时器及通过示例讲述其用法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

软件定时器

  所谓定时器,也就可以类比生活中人们常用的闹钟,可以单次响铃提醒,也可以间隔固定时间响铃提醒;与FreeRTOS定时器不同的是周期不同,FreeRTOS的周期更加短,一般使用毫秒(ms)、秒(s)。
  软件定时器,是指定时器的触发方式,软件定时器一旦到达定时时间就会触发回调函数。
  回调函数,遵循快进快出原则,因此,其中一定不能存在任何的阻塞,如vTaskDelay()、while(1)或者是其他能够产生阻塞的情况。
  FreeRTOS的软件定时器在功能上支持:

  • 软件定时器单次与周期执行;
  • 裁剪:能通过宏关闭软件定时器功能;
  • 软件定时器创建;
  • 软件定时器启动;
  • 软件定时器停止;
  • 软件定时器复位;
  • 软件定时器删除;
freertos 定时器,# FreeRTOS,OS,嵌入式硬件,c语言,驱动开发,硬件架构,stm32
定时器周期性工作与单次工作时间轴简图

  在freeRTOS的配置上,如果要是用定时器就需要配置下面几个宏定义:

//打开定时器
#define configUSE_TIMERS                1
//定时器的优先级
#define configTIMER_TASK_PRIORITY       50
//定时器栈大小
#define configTIMER_TASK_STACK_DEPTH    50
//定时器队列大小
#define configTIMER_QUEUE_LENGTH        50

FreeRTOS定时器的控制块

    typedef struct tmrTimerControl                  /* The old naming convention is used to prevent breaking kernel aware debuggers. */
    {
        const char * pcTimerName;                   /*<< Text name.  This is not used by the kernel, it is included simply to make debugging easier. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
        ListItem_t xTimerListItem;                  /*<< Standard linked list item as used by all kernel features for event management. */
        TickType_t xTimerPeriodInTicks;             /*<< How quickly and often the timer expires. */
        void * pvTimerID;                           /*<< An ID to identify the timer.  This allows the timer to be identified when the same callback is used for multiple timers. */
        TimerCallbackFunction_t pxCallbackFunction; /*<< The function that will be called when the timer expires. */
        #if ( configUSE_TRACE_FACILITY == 1 )
            UBaseType_t uxTimerNumber;              /*<< An ID assigned by trace tools such as FreeRTOS+Trace */
        #endif
        uint8_t ucStatus;                           /*<< Holds bits to say if the timer was statically allocated or not, and if it is active or not. */
    } xTIMER;

  定时器控制块中一共含有7个变量,其作用解析如下:

  • const char * pcTimerName:记录定时器名字
  • ListItem_t xTimerListItem:定时器的列表项,用于插入定时器列表;
  • TickType_t xTimerPeriodInTicks:定时器的周期,单位为系统节拍周期,即tick;
  • void * pvTimerID:定时器的ID,整数形式。该ID是当一个回调函数分配给一个或多个定时器时,可以根据IP不同处理回调函数中不同程序;
  • TimerCallbackFunction_t pxCallbackFunction:定时器回调函数;
  • UBaseType_t uxTimerNumber:跟踪工具分配的ID,如FreeRTOS+Trace;
  • uint8_t ucStatus:保存计时器是否静态分配,以及它是否处于活动状态;

  在定义完成控制块后,代码中会使用typedef xTIMER Timer_t重定义控制块的变量别名,在后续代码及开发中可以使用别名完成程序开发。


相关函数解析

  在FreeRTOS的定时器相关函数中,相关的函数有很多,如:发送指定到定时器任务队列函数xTimerGenericCommand、更新定时器周期函数xTimerChangePeriod、重启定时器函数xTimerReset、创建定时器函数xTimerCreate、启动定时器函数xTimerStart等等,其中最为重要且常用的函数当属创建定时器xTimerCreate、启动定时器xTimerStart

动态创建定时器函数
函数原型:

TimerHandle_t xTimerCreate(  const char * const pcTimerName,
                             TickType_t xTimerPeriodInTicks,
                             BaseType_t xAutoReload,
                             void * pvTimerID,
                             TimerCallbackFunction_t pxCallbackFunction );

函数说明:

  • const char * const pcTimerName:设置定时器名字;
  • TickType_t xTimerPeriodInTicks:设置定时器执行周期;
  • BaseType_t xAutoReload:设置定时器是单次或周期执行;
  • void * pvTimerID:设置定时器ID;
  • TimerCallbackFunction_t pxCallbackFunction:设置定时器回调函数;
  • 返回值:pxNewTimer ,数据类型为TimerHandle_t。一旦创建成功,则返回值不为NULL;否则,就为NULL;

函数解析:
  通过该函数可以创建一个定时器,但是该函数仅仅只是申请了一块内存空间,真正进行定时器初始化的函数为prvInitialiseNewTimer()。但是需要注意的是创建完成后处于就绪状态,需要启动后才能正常使用该定时器。

静态创建定时器函数
函数原型:

 TimerHandle_t xTimerCreateStatic(const char * const pcTimerName,
                                  TickType_t xTimerPeriodInTicks,
                                  BaseType_t xAutoReload,
                                  void * pvTimerID,
                                  TimerCallbackFunction_t pxCallbackFunction,
                                  StaticTimer_t *pxTimerBuffer );

函数参数说明:

  • const char * const pcTimerName:设置定时器名字;
  • TickType_t xTimerPeriodInTicks:设置定时器执行周期;
  • BaseType_t xAutoReload:设置定时器是单次或周期执行;
  • void * pvTimerID:设置定时器ID;
  • TimerCallbackFunction_t pxCallbackFunction:设置定时器回调函数;
  • StaticTimer_t *pxTimerBuffer:指向StaticTimer_t类型的变量,用于保存计时器的状态,就不需要动态分配内存了;
  • 返回值:pxNewTimer ,数据类型为TimerHandle_t。一旦创建成功,则返回值不为NULL;否则,就为NULL;

函数解析:
  定时器创建函数,与上面的定时器创建函数功能上一样,参数与返回值大部分相同,唯一不同的是定时器内存的分配方式,该函数无需动态分配内存,因为其已经传递一个指针用于保存定时器的相关内容。

启动定时器函数
函数原型:

BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait );

函数参数说明:

  • TimerHandle_t xTimer:创建定时器成功后返回的控制权柄,也就是其地址
  • TickType_t xTicksToWait:用户指定的超时阻塞时间,单位为系统节拍tick。在系统开始调用vTaskStartScheduler()前调用该函数,那么函数形参无作用。在定时器开始指令成功送达定时器命令队列前,定时器还是处于阻塞状态的。
  • 返回值:返回值类型为BaseType_t,如果启动命令无法成功地发送到定时器命令队列则
    返回 pdFAILE,成功发送则返回pdPASS。

函数解析:
  该函数的作用为启动定时器,一旦创建定时器后,就必须使用该函数启动,否则定时器还是处于就绪状态,没有任何实际用处
  启动定时器的函数实际上还是调用xTimerGenericCommand()函数,该函数含有五个参数、一个返回值,功能是发送命令到定时器命令队列。

在中断中启动定时器函数
函数原型:

BaseType_t xTimerStartFromISR( TimerHandle_t xTimer, 
							   BaseType_t * pxHigherPriorityTaskWoken );

函数参数说明:

  • TimerHandle_t xTimer:定时器控制句柄。
  • BaseType_t * pxHigherPriorityTaskWoken:定时器守护任务的大部分时间都在阻塞态等
    待定时器命令队列的命令。调用函数 xTimerStartFromISR()将会往定时器的命令队列发送
    一个启动命令,这很有可能会将定时器任务从阻塞态 移 除 。如果调用函数
    xTimerStartFromISR()让定时器任务脱离阻塞态,且定时器守护任务的优先级大于或者等
    于当前被中断的任务的优先级,那么 pxHigherPriorityTaskWoken 的值会在函数
    xTimerStartFromISR()内部设置为 pdTRUE,然后在中断退出之前执行一次上下文切换。
  • 返回值:返回值类型为BaseType_t,如果启动命令无法成功地发送到定时器命令队列则
    返回 pdFAILE,成功发送则返回pdPASS。

函数解析:
xTimerStartFromISR()是函数 xTimerStart()的中断版本,用于在中断中启动一个先前由函数xTimerCreate()xTimerCreateStatic()创建的软件定时器。

终止定时器函数
函数原型:

BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait );

函数参数说明:

  • TimerHandle_t xTimer:创建定时器成功后返回的控制权柄,也就是其地址;
  • TickType_t xTicksToWait:用户指定的超时阻塞时间,单位为系统节拍tick。在系统开始调用vTaskStartScheduler()前调用该函数,那么函数形参无作用。在定时器开始指令成功送达定时器命令队列前,定时器还是处于阻塞状态的。
  • 返回值:返回值类型为BaseType_t,如果启动命令无法成功地发送到定时器命令队列则
    返回 pdFAILE,成功发送则返回pdPASS。

函数解析:
  终止定时器函数,实际上调用xTimerGenericCommand()函数,该函数含有五个参数、一个返回值,功能是发送命令到定时器命令队列。
  终止定时器后,定时器会回归就绪态,等待下一次唤醒。

在中断中停止定时器函数
函数原型:

BaseType_t xTimerStopFromISR(    TimerHandle_t xTimer,
                                 BaseType_t *pxHigherPriorityTaskWoken );

函数参数说明:

  • TimerHandle_t xTimer:定时器控制句柄。
  • BaseType_t * pxHigherPriorityTaskWoken:定时器守护任务的大部分时间都在阻塞态等
    待定时器命令队列的命令。调用函数 xTimerStartFromISR()将会往定时器的命令队列发送
    一个启动命令,这很有可能会将定时器任务从阻塞态 移 除 。如果调用函数
    xTimerStartFromISR()让定时器任务脱离阻塞态,且定时器守护任务的优先级大于或者等
    于当前被中断的任务的优先级,那么 pxHigherPriorityTaskWoken 的值会在函数
    xTimerStartFromISR()内部设置为 pdTRUE,然后在中断退出之前执行一次上下文切换。
  • 返回值:返回值类型为BaseType_t,如果启动命令无法成功地发送到定时器命令队列则
    返回 pdFAILE,成功发送则返回pdPASS。

函数解析:
  该函数用于在中断停止定时器,使其进入就绪态。使用条件与xTimerStartFromISR()函数类似。

设置定时器执行周期函数
函数原型:

void vTimerSetReloadMode( TimerHandle_t xTimer,
                          const BaseType_t xAutoReload )

函数参数说明:

  • TimerHandle_t xTimer:定时器的控制权柄
  • const BaseType_t xAutoReload:定时器新的执行周期。若为pdFALSE则单次执行;否则为pdTRUE,就周期执行。

函数解析:
  使用该函数能够重新设置定时器的执行周期。
重启定时器函数
函数原型:

BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait );

函数参数说明:

  • TimerHandle_t xTimer:定时器的控制权柄;
  • TickType_t xTicksToWait:用户指定的超时阻塞时间,单位为系统节拍tick。

函数解析:
  重新启动一个定时器。

删除定时器函数
函数原型:

BaseType_t xTimerDelete( TimerHandle_t xTimer, TickType_t xTicksToWait );

函数参数说明:

  • TimerHandle_t xTimer:定时器控制权柄;
  • TickType_t xTicksToWait:用户指定的超时阻塞时间,单位为系统节拍tick。

函数解析:
  删除定时器函数,调用该函数能够删除对应定时器工作。

示例

创建两个定时器任务
  通过创建链各个定时器任务,完成定时器任务1实现——LED1间隔循环1s闪烁与定时器任务2实现——LED3单次闪烁。

void timeCallBackTask(void);
void timeCallBackTask2(void);

int main(void)
{
	TimerHandle_t xTimeHandle[2];
	xTimeHandle[0] = xTimerCreate(
								(const char *)"task1",// 定时器名字
								(TickType_t)1000,// 定时器的周期
								pdTRUE,// 定时器是单次执行还是周期执行, pdTRUE为周期执行,pdFALSE为周期执行
								(void*)1,// 给定时器分配的唯一ID
								(TimerCallbackFunction_t)timeCallBackTask// 定时器的回调函数
								);
	xTimeHandle[1] = xTimerCreate(
								(const char *)"task2",// 定时器名字
								(TickType_t)2000,// 定时器的周期
								pdFALSE,// 定时器是单次执行还是周期执行, pdTRUE为周期执行,pdFALSE为周期执行
								(void*)2,// 给定时器分配的唯一ID
								(TimerCallbackFunction_t)timeCallBackTask2// 定时器的回调函数
								);
	if(xTimeHandle[0] && xTimeHandle[1])
	{
		xTimerStart(xTimeHandle[0],0); //开启定时器
		xTimerStart(xTimeHandle[1],0); //开启定时器
	}
	else
		//定时器任务创建失败 打开LED8
		changeLedStateByLocation(LED8,ON);
	//打开任务调度器
	vTaskStartScheduler();
}

/*****************************************
* 函数功能:定时器任务
* 函数参数:无
* 函数返回值:无
*****************************************/
void timeCallBackTask(void)
{
	//闪烁LED1
	rollbackLedByLocation(LED1);
}

/*****************************************
* 函数功能:定时器任务2
* 函数参数:无
* 函数返回值:无
*****************************************/
void timeCallBackTask2(void)
{
	//闪烁LED3
	rollbackLedByLocation(LED3);
}

创建一个系统任务来管理两个定时器任务
  创建一个系统任务来开启与关闭定时器任务。由于创建完成定时器任务后,任务仍然处于就绪状态,需要开启函数xTimerStart才能够完成启动,而碰到关闭函数 xTimerStop定时器任务又会处于就绪状态。
  通过不断地开启与关闭,可以实现定时器任务timeCallBackTask与timeCallBackTask2不断地切换,实际上也实现就是LED1与LED2轮流闪烁。

void timeTask1(void);
void timeCallBackTask(void);
void timeCallBackTask2(void);

//任务控制权柄
TaskHandle_t xHandleTsak[4];
// 定时器控制权柄
TimerHandle_t xTimeHandle[2];
int main(void)
{

	BaseType_t xReturn[2];
	xTimeHandle[0] = xTimerCreate(
								(const char *)"task1",// 定时器名字
								(TickType_t)1000,// 定时器的周期
								pdTRUE,// 定时器是单次执行还是周期执行, pdTRUE为周期执行,pdFALSE为周期执行
								(void*)1,// 给定时器分配的唯一ID
								(TimerCallbackFunction_t)timeCallBackTask// 定时器的回调函数
								);
	xTimeHandle[1] = xTimerCreate(
								(const char *)"task2",// 定时器名字
								(TickType_t)2000,// 定时器的周期
								pdTRUE,// 定时器是单次执行还是周期执行, pdTRUE为周期执行,pdFALSE为周期执行
								(void*)2,// 给定时器分配的唯一ID
								(TimerCallbackFunction_t)timeCallBackTask2// 定时器的回调函数
								);
	xReturn[0] = xTaskCreate(
				(TaskFunction_t )timeTask1,//任务入口函数
				(const char *)"timeTask1",//任务名字
				(uint16_t)512,//任务栈大小
				(void*)NULL,//任务入口参数
				1,//任务优先级  优先级越高,任务优先选越高
				&xHandleTsak[2]//任务控制块
				);
	if(xReturn[0] == pdFALSE)
		changeLedStateByLocation(LED7,ON);
	//打开任务调度器
	vTaskStartScheduler();
}

/*****************************************
* 函数功能:定时器管理任务1
* 函数参数:无
* 函数返回值:无
*****************************************/
void timeTask1(void)
{
	uint32_t count = 0;
	const volatile TickType_t xDelay500ms = pdMS_TO_TICKS( 500UL );
	while(1)
	{
		//LED3闪烁
		if(++count % 2)
			rollbackLedByLocation(LED3);
		//开启定时器任务1  关闭定时器任务2
		if(count % 50 == 0)
		{
			xTimerStart(xTimeHandle[0],0);
			xTimerStop(xTimeHandle[1],0);
		}
		//开启定时器任务2  关闭定时器任务1
		if(count % 50 == 25)
		{
			xTimerStart(xTimeHandle[1],0);
			xTimerStop(xTimeHandle[0],0);
		}
		//非阻塞延时1s
		vTaskDelay( xDelay500ms );
	}
}

/*****************************************
* 函数功能:定时器任务
* 函数参数:无
* 函数返回值:无
*****************************************/
void timeCallBackTask(void)
{
	rollbackLedByLocation(LED1);
}

/*****************************************
* 函数功能:定时器任务2
* 函数参数:无
* 函数返回值:无
*****************************************/
void timeCallBackTask2(void)
{
	rollbackLedByLocation(LED2);
}

  本文是基于Cortex-M4核心板实现的,若需要移植FreeRTOS到Cortex-M4上可以参考文章【FreeRTOS】在Cortex-M4开发板上移植FreeRTOS并且实现LED灯闪烁(保姆级教程)
  小编这里还有一篇关于定时器的文章,也欢迎各位点击观看😉😉😉【FreeRTOS】详细讲解FreeRTOS中任务管理并通过示例讲述其用法

  最后 ,也欢迎大家留言或私信交流,大家共同进步!😁😁😁文章来源地址https://www.toymoban.com/news/detail-788945.html

到了这里,关于【FreeRTOS】详细讲解FreeRTOS的软件定时器及通过示例讲述其用法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【STM32】FreeRTOS软件定时器学习

      软件定时器 FreeRTOS提供了现成的软件定时器功能,可以一定程度上替代硬件定时器,但精度不高。 实验:创建一个任务,两个定时器,按键开启定时器,一个500ms打印一次,一个1000ms打印一次。 实现:在【STM32】FreeRTOS事件组学习基础上修改。 上面的代码是CubeMX封装好的。

    2024年02月12日
    浏览(38)
  • 【STM32/FreeRTOS】SysTick定时器及FreeRTOS系统节拍

    目录 一、SysTick定时器 1、SysTick寄存器介绍 (1)控制及状态寄存器 (2)重装载数值寄存器 (3)当前数值寄存器 2、SysTick寄存器配置函数 二、FreeRTOS中的SysTick定时器 1、SysTick配置函数及分析 2、SysTick中断函数 三、其他操作配置FreeRTOS的SysTick 1、找到头文件 FreeRTOSConfig.h 有如

    2024年01月24日
    浏览(47)
  • STC15W104 定时器实现灯的闪烁(定时器原理讲解)

    STC15W104单片机共有2个定时器,分别为定时器0、定时器2。 定时器是单片机中的一种常用外设,用于在一定时间间隔内产生中断。 定时器通常用于计时、测量时间间隔、生成PWM信号等应用中。 在STC15W104单片机中,定时器可以被配置为定时器/计数器模式。 在定时器模式下,定

    2024年02月13日
    浏览(44)
  • 51单片机——定时器中断实验,小白讲解,相互学习

    定时器介绍 1,CPU时序的有关知识 震荡周期:为单片机提供定时信号的震荡源的周期(晶振周期或外加震荡周期)。 状态周期:2个震荡周期为1个状态周期,用S表示。震荡周期又称S周期或时钟周期。 机器周期:1个机器周期含6个状态周期,12个震荡周期 指令周期:完成1条指

    2024年02月03日
    浏览(48)
  • STM32软件定时器

    目录 什么是定时器? 软件定时器优缺点 软件定时器原理 软件定时器相关配置 单次定时器和周期定时器 软件定时器相关 API 函数 1. 创建软件定时器 2. 开启软件定时器 3. 停止软件定时器 4. 复位软件定时器 5. 更改软件定时器定时时间 实操 cubeMX配置 代码实现  简单可以理解为

    2024年02月11日
    浏览(39)
  • 江西省电子专题大赛考点讲解七:NE555定时器

    【芯片引脚图】 图NE555-1 NE555芯片引脚图 1脚(GND):外接电源负端VSS或接地,一般情况下接地。 2脚(TRIG):低触发端TR。 3脚(OUT):输出端Vo 4脚(RESET):是直接清零端。当此端接低电平,则时基电路不工作,此时不论TR、TH处于何电平,时基电路输出为“0”,该端不用时应接高电平

    2024年02月08日
    浏览(54)
  • 【STM32H7 开发笔记】| 02 - 通过定时器级联方式同步启动多个定时器并输出 PWM 波形

    (STM32H723xE/G) 所有定时器包括 两个高级控制定时器、十二个通用定时器、两个基本定时器、五个低功耗定时器、两个看门狗定时器和一个SysTick定时器 。所有计时器计数器都可以在Debug模式下冻结。 本次实验主频配置的是500MHz 高级控制定时器(TIM1,TIM8)可以看作是在6通道

    2024年02月14日
    浏览(44)
  • RK3399平台开发系列讲解(基础篇)Linux 传统间隔定时器

    🚀返回专栏总目录 沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将详细 介绍 Linux 传统间隔定时器。 Linux 的传统间隔定时器设置接口是 setitimer,它可以设定在未来某个时

    2023年04月11日
    浏览(42)
  • 【杰理AC696X】软件定时器介绍

    测试SDK版本:《ac696n_soundbox_sdk_v1.6.0》 SDK给出了软件定时器的相关接口,主要有 sys_hi_timer_add、sys_s_hi_timer_add、sys_timer_add等。 列出AC696X系列软件定时器的相关知识点,再结合代码调试和工具测试,总结出使用案例。 上面的低功耗指的是 power down,不是soft poweroff。 usr_timer的强

    2024年02月10日
    浏览(41)
  • 9.物联网操作系统之软件定时器

    一。软件定时器概念及应用 1.软件定时器定义         就是软件实现定时器。 2.FreeRTOS软件定时器介绍         如上图所示,Times的左边为设置定时器时间,设置方式可以为任务设置或者中断设置;Times的右边为定时器的定时响应,使用CallBack响应。  3.FreeRTOS软件定时器工作

    2024年02月14日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包