十九、FreeRTOS之FreeRTOS软件定时器

本文详细介绍了FreeRTOS中的软件定时器,包括其概念、状态、优缺点、FreeRTOS提供的API函数,以及实际应用中的创建、操作和实验示例。重点讲解了单次定时器和周期定时器的区别,以及如何使用API进行定时器管理。
  • 本节主要需要掌握以下内容:

1,软件定时器的简介(了解)

2,软件定时器的状态(熟悉)

3,单次定时器和周期定时器(熟悉)

4,软件定时器结构体成员介绍(熟悉)

5FreeRTOS软件定时器相关API函数(熟悉)

6FreeRTOS软件定时器实验(掌握)

7,课堂总结(掌握)

一、软件定时器的简介(了解)

  • 定时器:

从指定的时刻开始,经过一个特定事件,然后触发一个超时事件,用户可以自定义定时器的周期。(类似于闹钟,响一次还是周期响)

  • 硬件定时器:

芯片自带的定时器模块,硬件定时器一般精度很高,每次在定时时间到达之后就会自动触发一个中断,用户在中断服务函数中处理信息。

  • 软件定时器:

是指具有定时功能的软件,可设置定时周期,当指定时间到达后要调用回调函数(也称超时函数),用户在回调函数中处理信息。

1.1 软件定时器的优缺点?

  • 优点:
  1. 硬件定时器数量优先,而软件定时器理论上只需要足够内存,就可以创建多个;
  2. 使用简单、成本低
  • 缺点:
  1. 软件定时器相对硬件定时器来说,精度没有那么高(因为它以系统时钟为基准,系统时钟中断优先级又是最低,容易被打断)。对于需要高精度要求的场合,不建议使用软件定时器。

1.2 FreeRTOS软件定时器特点

可裁剪:软件定时器是可裁剪可配置的功能,如果要使能软件定时器,需要将configUSE_TIMERS配置成1

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

注意:软件定时器的超时回调函数是由软件定时器服务任务调用的(这个任务去调超时回调函数),软件定时器的超时回调函数本身不是任务,因此不能再该回调函数中使用可能会导致阻塞的API函数。

软件定时器服务任务:在调用函数vTaskStartScheduler()开启任务调度的时候,会创建两个任务(一个空闲任务),一个用于管理软件定时器的任务,这个任务就叫软件定时器任务。

软件定时器服务任务作用

  • 负责软件定时器超时的逻辑判断
  • 调用超时软件定时器的超时回调函数
  • 处理软件定时器命令队列

1.3 软件定时器的命令队列

FreeRTOS提供了许多软件定时器相关的API函数,这些API函数大多都是往定时器的队列中写入消息(发送命令),这个队列叫软件定时器命令队列,是提供给FreeRTOS中的软件定时器使用的,用户是不能直接访问的。

软件定时器的相关配置

当FreeRTOS的配置项configUSE_TIMERS设置为1,在启动任务调度器时,会自动创建软件定时器的服务/守护任务prvTimerTask();

软件定时器服务任务的优先级为:configTIMER_TASK_PRIORITY  =  31;(配置为优先级最大,这样一有软件定时器超时,就立马调用超时回调函数,保证软件定时器的实时性)

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

注意:软件定时器的超时回调函数是在软件定时器服务任务中被调用的,服务任务不是专为某个定时器服务的,它还要处理其他定时器。

所以:定时器的回调函数不要影响“他人”;

1、回调函数要尽快实行,不能进入阻塞状态,即不能调用那些会阻塞任务的API函数,如:vTaskDelay()

2、访问队列或信号量的非零阻塞时间的API函数也不能调用。

二、软件定时器的状态

软件定时器共有两种状态:

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

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

注意:新创建的软件定时器处于休眠状态,也就是未运行的!

问题:如何让软件定时器从休眠态转变为运行态?

发送命令队列,比如说发送开启软件定时器,这个时候软件定时器就开始工作了,从休眠态转变为运行态

三、单次定时器和周期定时器(熟悉)

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

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

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

下图为单次定时器和周期定时器的示意图:

Timer1:周期定时器,定时超时时间为2个单位时间,开启后,一直以2个时间单位间隔重复执行;

Timer2:单次定时器,定时超时时间为1个单位时间,开启后,则在第一个超时后就不再执行了。

软件定时器的状态转换图:

 首先创建一个定时器,创建完之后是休眠态的,通过发送命令队列(开启、复位、更改超时时间),都可以让其转换成运行态,调用停止命令就可以从运行态转换为休眠态,或者单次一旦超时(调用超时回调函数),就会转换为休眠态。

周期定时器状态转换图:

 周期定时器 超时之后只要调用超时回调函数,就会自动计时,时间到了超时,又自动计时。

四、软件定时器结构体成员介绍(熟悉)

五、FreeRTOS软件定时器相关API函数(熟悉)

函数

描述

xTimerCreate()

动态方式创建软件定时器

xTimerCreateStatic()

静态方式创建软件定时器

xTimerStart()

开启软件定时器定时

xTimerStartFromISR()

在中断中开启软件定时器定时

xTimerStop()

停止软件定时器定时

xTimerStopFromISR()

在中断中停止软件定时器定时

xTimerReset()

复位软件定时器定时

xTimerResetFromISR()

在中断中复位软件定时器定时

xTimerChangePeriod()

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

xTimerChangePeriodFromISR()

在中断中更改定时超时时间

 5.1,创建软件定时器API函数

形参

描述

pcTimerName

软件定时器名

xTimerPeriodInTicks

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

uxAutoReload

定时器模式, pdTRUE:周期定时器, pdFALSE:单次定时器

pvTimerID

软件定时器 ID,用于多个软件定时器公用一个超时回调函数

pxCallbackFunction

软件定时器超时回调函数

返回值

描述

NULL

软件定时器创建失败

其他值

软件定时器创建成功,返回其句柄

5.2,开启软件定时器API函数

形参

描述

xTimer

待开启的软件定时器的句柄

xTickToWait

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

返回值

描述

pdPASS

软件定时器开启成功

pdFAIL

软件定时器开启失败

5.3,停止软件定时器API函数

形参

描述

xTimer

待停止的软件定时器的句柄

xTickToWait

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

返回值

描述

pdPASS

软件定时器停止成功

pdFAIL

软件定时器停止失败

5.4,复位软件定时器API函数

 该功能将使软件定时器的重新开启定时,复位后的软件定时器以复位时的时刻作为开启时刻重新定时

形参

描述

xTimer

待复位的软件定时器的句柄

xTickToWait

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

返回值

描述

pdPASS

软件定时器复位成功

pdFAIL

软件定时器复位失败

 

5.5,更改软件定时器超时时间API函数

形参

描述

xTimer

待更新的软件定时器的句柄

xNewPeriod

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

xTickToWait

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

返回值

描述

pdPASS

软件定时器定时超时时间更改成功

pdFAIL

软件定时器定时超时时间更改失败

 FreeRTOS软件定时器实验(掌握)

6.1、实验目的:

学习 FreeRTOS 的软件定时器相关API函数的使用。

6.2、实验设计:

将设计三个任务:start_task、task1

三个任务的功能如下:

  • start_task:用来创建task1任务,并创建两个定时器(单次和周期)

        (发现全文把好多单次  打成了 单词,如有单词,则指单次)

  • task1:用于按键扫描,并对软件定时器进行开启、停止操作

6.3 实验代码

 ****************************************************************************************************
 */

#include "freertos_demo.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "./SYSTEM/delay/delay.h"
#include "./MALLOC/malloc.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"
#include "event_groups.h"
/******************************************************************************************************/
/*FreeRTOS配置*/

/* START_TASK 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define START_TASK_PRIO         1
#define START_TASK_STACK_SIZE   128
TaskHandle_t    start_task_handler;
void start_task( void * pvParameters );

/* TASK1 任务 配置
 * 包括: 任务句柄 任务优先级 堆栈大小 创建任务
 */
#define TASK1_PRIO         2
#define TASK1_STACK_SIZE   128
TaskHandle_t    task1_handler;
void task1( void * pvParameters );

void timer1_callback( TimerHandle_t pxTimer );
void timer2_callback( TimerHandle_t pxTimer );
/******************************************************************************************************/

/**
 * @brief       FreeRTOS例程入口函数
 * @param       无
 * @retval      无
 */
void freertos_demo(void)
{    
    xTaskCreate((TaskFunction_t         )   start_task,
                (char *                 )   "start_task",
                (configSTACK_DEPTH_TYPE )   START_TASK_STACK_SIZE,
                (void *                 )   NULL,
                (UBaseType_t            )   START_TASK_PRIO,
                (TaskHandle_t *         )   &start_task_handler );
    vTaskStartScheduler();
}

TimerHandle_t timer1_handle = 0;    /* 单次定时器 */
TimerHandle_t timer2_handle = 0;    /* 周期定时器 */

void start_task( void * pvParameters )
{
    taskENTER_CRITICAL();               /* 进入临界区 */
    
    /* 单次定时器 */
    timer1_handle = xTimerCreate( "timer1", 
                                    500,
                                    pdFALSE,
                                    (void *)1,
                                    timer1_callback );
                            
    /* 周期定时器 */
    timer2_handle = xTimerCreate( "timer2", 
                                    2000,
                                    pdTRUE,
                                    (void *)2,
                                    timer2_callback );
                                    
    xTaskCreate((TaskFunction_t         )   task1,
                (char *                 )   "task1",
                (configSTACK_DEPTH_TYPE )   TASK1_STACK_SIZE,
                (void *                 )   NULL,
                (UBaseType_t            )   TASK1_PRIO,
                (TaskHandle_t *         )   &task1_handler );
                                             
    vTaskDelete(NULL);
    taskEXIT_CRITICAL();                /* 退出临界区 */
}

/* 任务一,按键扫描并控制软件定时器 */
void task1( void * pvParameters )
{
    uint8_t key = 0;
    while(1) 
    {
        key = key_scan(0);
        if(key == KEY0_PRES)
        {
            xTimerStart(timer1_handle,portMAX_DELAY);
            xTimerStart(timer2_handle,portMAX_DELAY);
        }else if(key == KEY1_PRES)
        {
            xTimerStop(timer1_handle,portMAX_DELAY);
            xTimerStop(timer2_handle,portMAX_DELAY);
        }
        vTaskDelay(10);
    }
}


/* timer1的超时回调函数 */
void timer1_callback( TimerHandle_t pxTimer )
{
    static uint32_t timer = 0;       /*  不加static 每次打印都是1 不然每次进来都会把timer清零 */
    printf("timer1的运行次数:%d\r\n",++timer);
}

/* timer2的超时回调函数 */
void timer2_callback( TimerHandle_t pxTimer )
{
    static uint32_t timer = 0;		/*  不加static 每次打印都是1 不然每次进来都会把timer清零 */
    printf("timer2的运行次数:%d\r\n",++timer);
}

,课堂总结(掌握)

这份毕业设计期末大作业源码为 Web 网页设计与制作领域提供了一个全面且实用的示例。它涵盖了从前端页面布局到后端交互功能的一系列关键技术,旨在帮助学生展示其在网页开发方面的综合能力和专业知识。在前端设计上,源码运用了 HTML5 和 CSS3 的最新特性,构建出精美的页面结构和视觉效果。通过合理的布局规划,包括导航栏、轮播图、内容区域、侧边栏和页脚等常见元素的安排,使得网页具有清晰的信息架构和良好的用户体验。同时,CSS 动画和过渡效果的巧妙运用,为页面增添了生动性和交互性,如按钮的悬停效果、菜单的展开与收起等,让用户在浏览过程中感受到流畅与舒适。从功能实现角度看,该源码结合 JavaScript 和 jQuery 库,实现了丰富的交互功能。例如,表单验证确保用户输入的信息符合要求,提高数据的准确性和完整性;图片的懒加载技术优化了页面加载速度,提升用户等待的耐心;响应式设计使网页能够自适应不同屏幕尺寸的设备,无论是电脑、平板还是手机,都能呈现出完美的布局和效果,满足了当今多终端浏览的需求。此外,源码的结构清晰,注释详尽,易于理解和二次开发。对于即将毕业的学生而言,这是一个宝贵的学习资源,不仅可以作为毕业设计的基础框架,通过进一步的修改和完善,还能够打造出具有个人特色和专业水准的完整网页项目,为未来的职业发展打下坚实的基础,同时也为网页设计制作领域的初学者提供了一个优秀的参考范例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

I am Supreme

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值