解决方案

FreeRTOS实时操作系统(十四)软件定时器

seo靠我 2023-09-26 02:58:05

系列文章目录

文章目录

系列文章目录软件定时器API函数实验测试

软件定时器

定时器的作用:经过一段指定时间,触发超时事件

在裸机开发中,应用的是芯片自带的定时器模块,精度很高,在中断服务函数中处理信息,包括实SEO靠我现PWM等功能(硬件定时器)

软件定时器是指具有定时功能的软件,可以设置定时周期,在回调函数中进行信息处理,只要内存够可以创建非常多。

软件定时器优点:

硬件定时器数量有限,而软件定时器理论上只需有足够内存SEO靠我,就可以创建多个;

使用简单、成本低;

缺点:

软件定时器相对硬件定时器来说,精度没有那么高(因为它以系统时钟为基准,系统时钟中断优先级又是最低,容易被打断)。 对于需要高精度要求的场合,不建议使用软件定时SEO靠我器。

软件定时器特点:

可裁剪:使能软件定时器,需将configUSE_TIMERS 配置项配置成 1

单次和周期:软件定时器支持设置成:单次定时器或周期定时器

软件定时器服务任务的优先级为 configTISEO靠我MER_TASK_PRIORITY = 31;

定时器的命令队列长度为 configTIMER_QUEUE_LENGTH = 5

要点:

1.软件定时器的超时回调函数是由软件定时器服务任务调用的,软件定时器SEO靠我的超时回调函数本身不是任务,因此不能在该回调函数中使用可能会导致任务阻塞的 API 函数。

2.在调用函数 vTaskStartScheduler()开启任务调度器的时候,会创建一个用于管理软件定时器的SEO靠我任务,prvTimerTask( ) ,这个任务就叫做软件定时器服务任务。

3.软件定时器的超时回调函数是在软件定时器服务任务中被调用的,服务任务不是专为某个定时器服务的,它还要处理其他定时器。回调函数SEO靠我要尽快实行,不能进入阻塞状态,即不能调用那些会阻塞任务的 API 函数,如:vTaskDelay() ,访问队列或者信号量的非零阻塞时间的 API 函数也不能调用。

工作方式:API函数通过往定时器队列SEO靠我写入消息,用户不能直接访问

软件定时器有两种状态:

休眠态:软件定时器可以通过其句柄被引用,但因为没有运行,所以其定时超时回调函数不会被执行

运行态:运行态的定时器,当指定时间到达之后,它的超时回调函数会被SEO靠我调用

新创建的软件定时器处于休眠状态 ,也就是未运行的!,只有发送命令队列后才行。

FreeRTOS提供了两种软件定时器:

单次定时器:单次定时器的一旦定时超时,只会执行一次其软件定时器超时回调函数,不会自SEO靠我动重新开启定时,不过可以被手动重新开启。

周期定时器:周期定时器的一旦启动以后就会在执行完回调函数以后自动的重新启动 ,从而周期地执行其软件定时器回调函数。

单次定时器:

周期定时器:

API函数

软件定时器句SEO靠我柄结构体成员:

typedef struct tmrTimerControl { const char * pcTimerName /* 软件定时器名字 */ SEO靠我 ListItem_t xTimerListItem /* 软件定时器列表项 */ TickType_t xTimerPeriodInTicks; /* 软件定时器的周期 */ SEO靠我 void * pvTimerID /* 软件定时器的ID */ TimerCallbackFunction_t pxCallbackFunction; /* 软件定时器的SEO靠我回调函数 */ #if ( configUSE_TRACE_FACILITY == 1 ) UBaseType_t uxTimerNumber /* 软件定时器的编号,SEO靠我调试用 */ #endif uint8_t ucStatus; /* 软件定时器的状态 */ } xTIMER;

常见的API函数:

函数描述xTimerCSEO靠我reate()动态方式创建软件定时器xTimerCreateStatic()静态方式创建软件定时器xTimerStart()开启软件定时器定时xTimerStartFromISR()在中断中开启软件定SEO靠我时器定时xTimerStop()停止软件定时器定时xTimerStopFromISR()在中断中停止软件定时器定时xTimerReset()复位软件定时器定时xTimerResetFromISR()在SEO靠我中断中复位软件定时器定时xTimerChangePeriod()更改软件定时器的定时超时时间xTimerChangePeriodFromISR()在中断中更改定时超时时间

1.创建软件定时器:

TimerSEO靠我Handle_t xTimerCreate( const char * const pcTimerName, //软件定时器名字 const TickType_t xTimerPeriSEO靠我odInTicks, //定时超时时间,单位:系统时钟节拍 const UBaseType_t uxAutoReload, //定时器模式,pdTRUE:周期定时器,pdFALSE:单SEO靠我次定时器 void * const pvTimerID, //软件定时器ID,用于多个如那件定时器公用一个回调函数 TimerCallbackFunction_t pxSEO靠我CallbackFunction ); //软件定时器超时回调函数

返回值:

NULL 创建失败

其他值:创建成功,返回其句柄

2.开启软件定时器

BaseType_t xTimerStart( TimerHaSEO靠我ndle_t xTimer,const TickType_t xTicksToWait );

形参:

xTimer:要开启的软件定时器句柄

xTickToWait:发送命令到软件定时器命令队列的最大等待时间SEO靠我

返回值:

pdPASS:开启成功

pdFAIL:开启失败

3.停止软件定时器

BaseType_t xTimerStop( TimerHandle_t xTimer,const TickType_t xTicSEO靠我ksToWait);

形参:

xTimer:软件定时器句柄

xTickToWait:发送命令到软件定时器命令队列的最大等待时间

返回值:

pdPASS:停止成功

pdFAIL:停止失败

4.复位软件定时器

BaseTSEO靠我ype_t xTimerReset( TimerHandle_t xTimer,const TickType_t xTicksToWait);

形参:

xTimer:软件定时器句柄

xTickToWait:SEO靠我发送命令到软件定时器命令队列的最大等待时间

返回值:

pdPASS:成功

pdFAIL:失败

5.更改软件定时器的超时时间

BaseType_t xTimerChangePeriod( TimerHandle_SEO靠我t xTimer, const TickType_t xNewPeriod, const TickType_t xTicksToWait);

形参:

xTimer:软件定时SEO靠我器句柄

xNewPeriod:新的定时超时时间,单位:系统时钟节拍

xTickToWait:发送命令到软件定时器命令队列的最大等待时间

返回值:

pdPASS:成功

pdFAIL:失败

实验测试

TimerHandSEO靠我le_t timer1_handle = 0; /* 单次定时器 */ TimerHandle_t timer2_handle = 0; /* 周期定时器 */ voSEO靠我id timer1_callback( TimerHandle_t pxTimer ); void timer2_callback( TimerHandle_t pxTimer ); SEO靠我 void vOtherFunction( void ) { /* 单次定时器 */ timer1_handle = xTimerCreSEO靠我ate( "timer1", 500, pdFALSE, (void *)1, timer1_callback ); SEO靠我/* 周期定时器 */ timer2_handle = xTimerCreate( "timer2", 2000, pdTRUE, (vSEO靠我oid *)2, timer2_callback ); xTaskCreate( vTaskCode, "tak1", 128, NULL, 1, &task1_haSEO靠我ndler ); vTaskStartScheduler(); } void task1( void * pvParameters ) SEO靠我 { xTimerStart(timer1_handle,portMAX_DELAY); xTimerStart(timer2_handle,portMAX_DELAYSEO靠我); while(1) { vTaskDelay(10); } } void task2( void SEO靠我* pvParameters ) { while(1) { vTaskDelay(10); } } SEO靠我 /* timer1的超时回调函数 */ void timer1_callback( TimerHandle_t pxTimer ) { sSEO靠我tatic uint32_t timer = 0; printf("timer1的运行次数:%d\r\n",++timer); } /* timer2SEO靠我的超时回调函数 */ void timer2_callback( TimerHandle_t pxTimer ) { static uint32_t tSEO靠我imer = 0; printf("timer2的运行次数:%d\r\n",++timer); }

周期性任务在不断执行,单次定时器只执行了一次。

“SEO靠我”的新闻页面文章、图片、音频、视频等稿件均为自媒体人、第三方机构发布或转载。如稿件涉及版权等问题,请与 我们联系删除或处理,客服邮箱:html5sh@163.com,稿件内容仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同 其观点或证实其内容的真实性。

网站备案号:浙ICP备17034767号-2