基本概念

  • 软件定时器的回调函数类似硬件的中断服务函数,所以,回调函数也要快进快出,而且回调函数中不能有任何阻塞任务运行的情况,例如不可以使用vTaskDelay()
  • FreeRTOS 提供的软件定时器支持单次模式和周期模式
  • FreeRTOS 通过一个 prvTimerTask 任务(也叫守护任务 Daemon)管理软定时器
  • 只有设置 FreeRTOSConfig.h 中的宏定义 **configUSE_TIMERS **设置为 1 ,将相关代码编译进来
  • 以系统节拍周期为计时单位
  • 定时器消息队列的长度由宏 configTIMER_QUEUE_LENGTH 定义,
  • FreeRTOS 是采用队列的方式发送一个消息给软件定时器任务,任务被唤醒从而执行接收到的命令
  • 软件定时器任务是在系统开始调度(vTaskStartScheduler()函数)的时候就被创建的

注意事项

  • 软件定时器的回调函数中应快进快出,绝对不允许使用任何可能引软件定时器起任务挂起或者阻塞的 API 接口,在回调函数中也绝对不允许出现死循环。
  • 软件定时器使用了系统的一个队列和一个任务资源,软件定时器任务的优先级默认为 configTIMER_TASK_PRIORITY,为了更好响应,该优先级应设置为所有任务中最高的优先级。
  • 创建单次软件定时器,该定时器超时执行完回调函数后,系统会自动删除该软件定时器,并回收资源。
  • 定时器任务的堆栈大小默认为 configTIMER_TASK_STACK_DEPTH 个字节。

控制块

typedef struct tmrTimerControl
{const char             *pcTimerName;       /*软件定时器名字 */ListItem_t              xTimerListItem;     /*软件定时器列表项 */TickType_t             xTimerPeriodInTicks;/*件 定时 器的周 期 */UBaseType_t              uxAutoReload;       /*pdFalse,那么创建的软件定时器工作模式是单次模式,否则为周期模式。*/void                  *pvTimerID;         /*软件定时器 ID*/TimerCallbackFunction_t pxCallbackFunction; /*回调函数 */#if( configUSE_TRACE_FACILITY == 1 )UBaseType_t          uxTimerNumber;      /*<< An ID assigned by trace tools such as FreeRTOS+Trace */#endif#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )uint8_t            ucStaticallyAllocated; /*标记定时器使用的内存,删除时判断是否需要释放内存 */#endif
} xTIMER;

回调函数格式

typedef void (*TimerCallbackFunction_t)( TimerHandle_t xTimer );

定时器句柄

typedef xTIMER Timer_t;

函数接口

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

TimerHandle_t xTimerCreate(  const char * const pcTimerName,//软件定时器名字const TickType_t xTimerPeriodInTicks,//软件定时器的周期const UBaseType_t uxAutoReload,//pdTRUE周期模式,pdFALSE 单次模式void * const pvTimerID,//软件定时器 IDTimerCallbackFunction_t pxCallbackFunction ) //定时器的回调函数 typedef void (*TimerCallbackFunction_t)( TimerHandle_t xTimer );

软件定时器启动函数xTimerStart()

普通版


#define xTimerStart( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) )BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, const BaseType_t xCommandID, const TickType_t xOptionalValue, BaseType_t * const pxHigherPriorityTaskWoken, const TickType_t xTicksToWait )//xCommandID 可选项
#define tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR    ( ( BaseType_t ) -2 )
#define tmrCOMMAND_EXECUTE_CALLBACK             ( ( BaseType_t ) -1 )
#define tmrCOMMAND_START_DONT_TRACE             ( ( BaseType_t ) 0 )
#define tmrCOMMAND_START                        ( ( BaseType_t ) 1 )
#define tmrCOMMAND_RESET                        ( ( BaseType_t ) 2 )
#define tmrCOMMAND_STOP                         ( ( BaseType_t ) 3 )
#define tmrCOMMAND_CHANGE_PERIOD                ( ( BaseType_t ) 4 )
#define tmrCOMMAND_DELETE                       ( ( BaseType_t ) 5 )#define tmrFIRST_FROM_ISR_COMMAND               ( ( BaseType_t ) 6 )
#define tmrCOMMAND_START_FROM_ISR               ( ( BaseType_t ) 6 )
#define tmrCOMMAND_RESET_FROM_ISR               ( ( BaseType_t ) 7 )
#define tmrCOMMAND_STOP_FROM_ISR                ( ( BaseType_t ) 8 )
#define tmrCOMMAND_CHANGE_PERIOD_FROM_ISR       ( ( BaseType_t ) 9 )
参数 说明
xTimer 待启动的定时器
xTicksToWait 户指定超时阻塞时间
返回值 如果启动命令无法成功地发送到定时器命令队列则返回 pdFAILE,成功发送则返回pdPASS。

中断版

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

软件定时器停止函数

普通版xTimerStop()

BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xBlockTime );#define xTimerStop( xTimer, xTicksToWait ) xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xTicksToWait ) )
参数 说明
xTimer 软件定时器句柄。
xBlockTime 用户指定超时时间,单位为系统节拍周期(即 tick)。如果在 FreeRTOS 调度器开启之前调用 xTimerStart(),形参将不起作用。
返回值 如果启动命令在超时时间之前无法成功地发送到定时器命令队列则返回 pdFAILE,成功发送则返回 pdPASS。

中断版

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

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

#define xTimerDelete( xTimer, xTicksToWait ) \xTimerGenericCommand( ( xTimer ), \tmrCOMMAND_DELETE, \0U, NULL, ( xTicksToWait ) )
参数 说明
xTimer 软件定时器句柄。
xBlockTime 用户指定的超时时间,单位为系统节拍周期(即 tick),如果在 FreeRTOS调度器开启之前调用 xTimerStart(),该形参将不起作用。
返回值 如果删除命令在超时时间之前无法成功地发送到定时器命令队列则返回 pdFAILE,成功发送则返回 pdPASS。

示例

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "FreeRTOS.h"
#include "task.h"
#include<bsp_key.h>
#include "semphr.h"
#include <stdio.h>#include<timers.h>
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
//任务句柄
static TaskHandle_t send_Task_Handle = NULL;
static TaskHandle_t recv_Task_Handle = NULL;
//信号量句柄
static SemaphoreHandle_t xsem=NULL;
//互斥量句柄
static SemaphoreHandle_t xlock=NULL;
//软件定时器句柄
static TimerHandle_t timer=NULL;//接收信号任务
static void recv_Task(void * param)
{uint32_t data1;while (1){//接收信号if(pdTRUE==xSemaphoreTake(xsem,portMAX_DELAY)){//串口临界资源加锁xSemaphoreTake(xlock,portMAX_DELAY );printf("take sem\r\n");//串口临界资源解锁xSemaphoreGive(xlock);HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);}}}//发送信号任务
static void send_Task(void * param)
{uint32_t data1=10;while (1){//键盘扫描if(Key_Scan(KEY1_GPIO_Port,KEY1_Pin)==KEY_ON){//发送信号xSemaphoreGive(xsem);//串口临界资源加锁xSemaphoreTake(xlock,portMAX_DELAY );printf("give sem\r\n");//串口临界资源解锁xSemaphoreGive(xlock);}vTaskDelay(100);}}static void TimerCallbackLed( TimerHandle_t xTimer )
{HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
}/* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */printf("hello FreeRTOS\r\n");int timer_id;//xqueue =  xQueueCreate(10, 4);//创建二值信号量xsem = xSemaphoreCreateBinary();//创建互斥锁xlock = xSemaphoreCreateMutex();//创建周期定时器timer = xTimerCreate("ledtimeer",100,pdTRUE,&timer_id,TimerCallbackLed);//启动定时器xTimerStart(timer, 100);if(xsem==NULL){printf("create queue fail\r\n");}BaseType_t        xReturn;//创建接收信号任务xReturn           = xTaskCreate((TaskFunction_t) recv_Task, /* 任务入口函数 */(const char *) "recv_Task",                    /* 任务名字 */(uint16_t) 512,                               /* 任务栈大小 */(void *) NULL,                                   /* 任务入口函数参数 */(UBaseType_t) 2,                              /* 任务的优先级 */(TaskHandle_t *) &recv_Task_Handle);            /* 任务控制块指针 *///创建发送信号任务xReturn          = xTaskCreate((TaskFunction_t) send_Task, /* 任务入口函数 */(const char *) "send_Task",                    /* 任务名字 */(uint16_t) 512,                               /* 任务栈大小 */(void *) NULL,                                   /* 任务入口函数参数 */(UBaseType_t) 2,                              /* 任务的优先级 */(TaskHandle_t *) &send_Task_Handle);            /* 任务控制块指针 *///启动调度器,调度器是不会返回的if (pdPASS == xReturn)vTaskStartScheduler(); /* 启动任务,开启调度 *//* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);HAL_Delay(50);}/* USER CODE END 3 */
}

8.FreeRTOS学习笔记-软件定时器相关推荐

  1. freeRtos学习笔记 (6)软件定时器

    freeRtos学习笔记 freeRtos软件定时器 软件定时器需要注意事项 软件定时器的精度基于时钟节拍,例如系统时钟节拍为10ms, 软件定时器定时时间必须是10ms的整数倍,因此软件定时器一般用 ...

  2. FreeRTOS学习笔记(7)——软件定时器

    一.头文件 #include "FreeRTOS.h" #include "timers.h" 二.软件定时器 2.1 基本概念 软件定时器在被创建之后,当经过 ...

  3. freeRtos学习笔记 (5)事件组

    freeRtos学习笔记 freeRtos事件组 为什么要用事件组? 多任务环境下, 任务.中断之间往往需要同步操作,一个事件发生会告知等待中的任 务,即形成一个任务与任务.中断与任务间的同步.事件可 ...

  4. FreeRTOS学习笔记

    FreeRTOS学习笔记 (这是我自己学习FreeRTOS整理的笔记,仅供参考) 第一部分:实现FreeRTOS内核 变量名: 定义变量时往往会把变量的类型当作前缀加在变量上 变量类型 前缀 char ...

  5. 1、野火freertos学习笔记

    野火freertos学习笔记 1.任务 1.1 栈 1.2 任务的切换 taskYIELD(); 1.3 临界段 2.空闲任务 3.任务优先级 4.任务延时的表现 5.时间片 5.1抢占式.协做式 6 ...

  6. 【ESP32+freeRTOS学习笔记-开篇前言】

    目录 前言的前言 RTOS的选择 开发与实践环境 参考资料 笔记的形式 专题文章的链接(持续更新中......) 前言的前言 单片机的开发,也有两年多了,之前一直是做一些简单应用,因此以裸机开发的方式 ...

  7. freeRtos学习笔记 (9) 移植和CPU利用率统计

    freeRtos学习笔记 (9) 移植和CPU利用率统计 使用官方固件移植 首先准备一个能跑的裸机工程 注意,freertos需要使用systick定时器,而stm32HAL库默认使用systick作 ...

  8. FreeRtos学习笔记(11)查找就绪任务中优先级最高任务原理刨析

    FreeRtos学习笔记(11)查找就绪任务中优先级最高任务原理刨析 怎么查找就绪任务中优先级最高的? tasks.c中声明了一个全局变量 uxTopReadyPriority,任务从其他状态进入就绪 ...

  9. freeRtos学习笔记 (8) 任务通知

    freeRtos学习笔记 freeRtos任务通知 任务通知的优缺点 freeRtos任务控制块中包含两个32位的变量,用于任务通知,在一些情况下,任务通知可以替代信号量和事件组,并且比信号量和事件组 ...

最新文章

  1. codeviz安装使用全记录
  2. 【MySQL】Dockerfile书写简单示例
  3. linux 同步 多终端,Linux系统如何实现不同终端间的同步
  4. 专家:大数据等新技术助力信息融合
  5. 教你理清SpringBoot与SpringMVC的关系
  6. Vue 凭什么成为 2020 年的一匹黑马
  7. java 线程类注入失败_如何在多线程中注入bean?!
  8. dcp9030cdn定影_兄弟DCP-9030CDN打印驱动下载|兄弟Brother DCP-9030CDN一体打印机驱动官方下载 - 维维软件园...
  9. linux常用命令(入门)
  10. Java中的正则表达式
  11. 16个精美的 HTML5 作品集网站设计案例
  12. ASO关键词优化如何提升APP榜单排名,aso 关键词优化工具
  13. 修改移动硬盘盘符(G盘--E盘)
  14. @Resource详解
  15. linux里面ping地址停不下来解决方法
  16. 类与对象的基本语法+练习题
  17. 波特率(baud)与比特率(bit/s)的差别
  18. 关于华为HS8145V 进入华为界面后 再刷回电信界面
  19. 刷脸支付到来用户连密码都不需要
  20. Unity基础系列(五)——每秒帧率(测试性能)

热门文章

  1. equalwith java_java中==与equal()方法的区别
  2. python基础课程第12章_流畅的python学习笔记-第12章
  3. 红宝书电子版_N2红蓝宝书电子版PDF(蓝宝书)
  4. java 高德地图 车型比价计算_高德地图的高速公路过路费计算功能是如何实现的?有相应开放的API吗?...
  5. Java 并发编程之线程池 ScheduledThreadPool
  6. html背景无法载入gif图像,background-image:url(XXXX.gif)为何不显示背景图片_html/css_WEB-ITnose...
  7. django添加字典格式的数据
  8. python123测试_【测码学院】python自动化测试学习-自动化测试模型
  9. android sdk 64 linux下载,64位Linux机器上的Android SDK
  10. flutter 动画展开菜单_Flutter ExpansionPanel 超级实用展开控件