pb 判断timer是否在执行_FreeRTOS 之 Timer

本文介绍了FreeRTOS中的软件定时器工作原理,包括xTimerCreate函数的使用,软件定时器如何与系统交互,如何判断定时器是否超时,以及处理定时器的任务如何运行。虽然软件定时器基于task实现,但可能因优先级抢占导致精度不足。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在《FreeRTOS 之任务调度》一文中提到,硬件定时器是和硬件设计相关的,不同的芯片有不同的配置方法,通过中断方式触发执行,精确度高。相对于硬件定时器,FreeRTOS 中还提供了软件定时器。本文就来聊聊软件定时器是如何实现的,以及它的精度如何呢??

首先看一个例子,如下的代码就是使用软件定时器,周期性的打印 “This is a softtimer” 信息。

3ed33f27758dbad5ab83d5e006a79fce.png

xTimerCreate() 函数用于创建一个定时器。其中, “时长” 是以 tick 为单位的,uxAutoReload 参数表示当定时器到期时,是否自动装载,等待下一次触发。

a63ea007fe5f0d26d5ee25859e1ffd16.png

从函数的定义中可以看出,其参数就是一个定时器所包括的资源:

/* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "FreeRTOS.h" #include "task.h" #include "main.h" #include "cmsis_os.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "queue.h" #include "usart.h" #include <string.h> #include "event_groups.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 */ void SendTask(void *data); void RecvTask(void *data); //软件定时器的回调函数 void timer1_callback(TimerHandle_t xtimer); void timer2_callback(TimerHandle_t xtimer); TimerHandle_t timer1_handle; TimerHandle_t timer2_handle; TaskHandle_t sendtaskhandle=NULL; TaskHandle_t recvtaskhandle=NULL; /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN Variables */ /* USER CODE END Variables */ /* Definitions for defaultTask */ osThreadId_t defaultTaskHandle; const osThreadAttr_t defaultTask_attributes = { .name = "defaultTask", .stack_size = 128 * 4, .priority = (osPriority_t) osPriorityNormal, }; /* Private function prototypes -----------------------------------------------*/ /* USER CODE BEGIN FunctionPrototypes */ /* USER CODE END FunctionPrototypes */ void StartDefaultTask(void *argument); void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */ /** * @brief FreeRTOS initialization * @param None * @retval None */ void MX_FREERTOS_Init(void) { /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* USER CODE BEGIN RTOS_MUTEX */ /* add mutexes, ... */ /* USER CODE END RTOS_MUTEX */ /* USER CODE BEGIN RTOS_SEMAPHORES */ /* add semaphores, ... */ /* USER CODE END RTOS_SEMAPHORES */ /* USER CODE BEGIN RTOS_TIMERS */ /* start timers, add new ones, ... */ /* USER CODE END RTOS_TIMERS */ /* USER CODE BEGIN RTOS_QUEUES */ /* add queues, ... */ /* USER CODE END RTOS_QUEUES */ /* Create the thread(s) */ /* creation of defaultTask */ defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes); /* USER CODE BEGIN RTOS_THREADS */ /* add threads, ... */ xTaskCreate(SendTask,"SendTask",128,NULL,2,&sendtaskhandle); xTaskCreate(RecvTask,"RecvTask",128,NULL,3,&recvtaskhandle); //创建一个定时器 timer1_handle=xTimerCreate("timer1", //定时器名字,调试用 1000, //多长时间触发 //单位tick pdTRUE, //是否重复 (void*)1, //标志位,每个定时器不能相同 timer1_callback); //回调函数 timer2_handle=xTimerCreate("timer2", 1000, pdFALSE, (void*)2, timer2_callback); /* USER CODE END RTOS_THREADS */ /* USER CODE BEGIN RTOS_EVENTS */ /* add events, ... */ /* USER CODE END RTOS_EVENTS */ } /* USER CODE BEGIN Header_StartDefaultTask */ /** * @brief Function implementing the defaultTask thread. * @param argument: Not used * @retval None */ /* USER CODE END Header_StartDefaultTask */ void StartDefaultTask(void *argument) { /* USER CODE BEGIN StartDefaultTask */ /* Infinite loop */ for(;;) { osDelay(1); } /* USER CODE END StartDefaultTask */ } /* Private application code --------------------------------------------------*/ /* USER CODE BEGIN Application */ void SendTask(void *data) { while(1) { if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_6)==0) { vTaskDelay(20); while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_6)==0); if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_6)==1) { vTaskDelay(20) ; USART_printf(&huart1,"button2 on\n"); xTimerStop(timer1_handle,portMAX_DELAY); //停止定时器 xTimerStop(timer2_handle,portMAX_DELAY); //停止定时器 USART_printf(&huart1,"timer1,timer2 stop\n"); } } } vTaskDelete( NULL ); } void RecvTask(void *data) { while(1) { if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==0) { vTaskDelay(20); while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==0); if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==1) { vTaskDelay(20) ; USART_printf(&huart1,"button1 on\n"); xTimerStart(timer1_handle,portMAX_DELAY); //启动定时器 死等 xTimerStart(timer2_handle,portMAX_DELAY); //启动定时器 USART_printf(&huart1,"timer1,timer2 start\n"); } } } vTaskDelete( NULL ); } void timer1_callback(TimerHandle_t xtimer) { USART_printf(&huart1,"hello\n"); } void timer2_callback(TimerHandle_t xtimer) { USART_printf(&huart1,"word!\n"); } 只有按下按键才会打印hello不按下就不打印,另外pb6不能用不知道为啥
最新发布
05-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值