当前位置: 首页 > news >正文

学习RT-thread(RT-thread定时器)

1. 时钟节拍

对于RT-Thread来说,它和其他系统都一样,都需要一个时钟节拍,以提供系统处理所有和时间有关的事件,如线程的延时,线程的时间片轮转调度以及定时器超时等。

时钟节拍是特定的周期性中断,这个中断被描述为系统的心跳。而中断的事件间隔取决于系统配置,时钟节拍越快,系统的实时响应越快,但会使系统的开销变大。

以STM32为例,通过SysTick提供了这个时钟节拍,SysTick每次中断的到来,都会调用一次 rt_tick_increase函数,通知操作系统已经过去一个系统时钟。

void SysTick_Handler(void){/* 进入中断 */rt_interrupt_enter();……rt_tick_increase();/* 退出中断 */rt_interrupt_leave();}

2. 定时器

2.1 什么是定时器

定时器,是指从指定的时刻开始,经过一定的指定时间后触发一个事件,例如定个时间提醒第二天能够按时起床。定时器有硬件定时器和软件定时器之分:

2.1.1 硬件定时器:

硬件定时器:定时器超时函数在中断上下文环境中执行,可以在初始化 / 创建定时器时使用参数 RT_TIMER_FLAG_HARD_TIMER 来指定。注意:在中断上下文环境中执行时,对于超时函数的要求 与中断服务例程的要求相同:执行时间应该尽量短,执行时不应导致当前上下文挂起、等待。例如 在中断上下文中执行的超时函数它不应该试图去申请动态内存、释放动态内存等。

2.1.2 软件定时器:

软件定时器:系统会在初始化时创建一个 timer 线程,然后 SOFT_TIMER 模式的定时器超时函数在 都会在 timer 线程的上下文环境中执行。可以在初始化 / 创建定时器时使用参数 RT_TIMER_FLAG_SOFT_TIMER 来指定设置 SOFT_TIMER 模式。

注意:RT-Thread 操作系统提供软件实现的定时器,以时钟节拍(OS Tick)的时间长度为单位,即定时 数值必须是 OS Tick 的整数倍,例如一个 OS Tick 是 10ms,那么上层软件定时器只能是 10ms, 20ms,100ms 等,而不能定时为 15ms。RT-Thread 的定时器也基于系统的节拍,提供了基于节拍整数 倍的定时能力。

2.2 定时器工作原理

1. 当前系统经过的 tick 时间 rt_tick(当硬件定时器中断来临时,它将加 1)

2. 定时器链表 rt_timer_list。系统新创建并激活的定时器都会按照以超时时间排序的方式插入到 rt_timer_list 链表中

如下图所示,系统当前 tick 值为 20,在当前系统中已经创建并启动了三个定时器,分别是定时时间为 50 个 tick 的 Timer1、100 个 tick 的 Timer2 和 500 个 tick 的 Timer3,这三个定时器分别加上系统当 前时间 rt_tick=20,从小到大排序链接在 rt_timer_list 链表中,形成如图所示的定时器链表结构。

而 rt_tick 随着硬件定时器的触发一直在增长(每一次硬件定时器中断来临,rt_tick 变量会加 1),50 个 tick 以后,rt_tick 从 20 增长到 70,与 Timer1 的 timeout 值相等,这时会触发与 Timer1 定时器相关联 的超时函数,同时将 Timer1 从 rt_timer_list 链表上删除。同理,100 个 tick 和 500 个 tick 过去后,与 Timer2 和 Timer3 定时器相关联的超时函数会被触发,接着将 Timer2 和 Timer3 定时器从 rt_timer_list 链表中删除。

如果系统当前定时器状态在 10 个 tick 以后(rt_tick=30)有一个任务新创建了一个 tick 值为 300 的 Timer4 定时器,由于 Timer4 定时器的 timeout=rt_tick+300=330, 因此它将被插入到 Timer2 和 Timer3 定时器中间,形成如下图所示链表结构:

3. 定时器相关函数

3.1 启动和停止函数

3.1.1 启动定时器函数:

rt_err_t rt_timer_start(rt_timer_t timer);

3.1.2 停止定时器函数

rt_err_t rt_timer_stop(rt_timer_t timer);

3.2 创建/删除函数

3.2.1 创建定时器函数:

void rt_timer_init(rt_timer_t timer,const char* name,void (*timeout)(void* parameter),void* parameter,rt_tick_t time, rt_uint8_t flag);

flag定义:

#define RT_TIMER_FLAG_ONE_SHOT        0X0        /*单次定时*/
#define RT_TIMER_FLAG_PERIODIC        0X2        /*周期定时*/
#define RT_TIMER_FLAG_HARD_TIMER      0X0        /*硬件定时器*/
#define RT_TIMER_FLAG_SOFT_TIMER      0X4        /*软件定时器*/

3.2.2 删除定时器函数:

rt_err_t rt_timer_detach(rt_timer_t timer);

4. 定时器实操

实验要求:

场景:分别通过创建两个定时器:

1. 定时器1周期性执行,控制灯的闪烁;

2. 定时器2周期性执行,打印一条打印。

CubeMX配置

我们要控制LED灯闪烁根据原理图将PA12设为GPIO_OutPut

代码实现

/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
#include <rtthread.h>
/* USER CODE BEGIN Includes *//* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
static struct rt_timer time1_handle;static struct rt_timer time2_handle;/* 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);void timer1(void* parameter)
{HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_12);
}void timer2(void* parameter)
{rt_kprintf("timer2\n");
}
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* 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 */rt_timer_init(&time1_handle,"time1",timer1,NULL,1000,RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER);rt_timer_init(&time2_handle,"time2",timer2,NULL,1000,RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER);rt_timer_start(&time1_handle);rt_timer_start(&time2_handle);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE */rt_thread_delay(100);/* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}

实验现象:

1.打开串口终端观察实验现象

timer2 1s 打印一次

2.LED1 1s闪烁一次

http://www.dtcms.com/a/561077.html

相关文章:

  • 基于整数MCU的FOC电机控制深度解析:从浮点到定点的工程实践
  • 在整数MCU上实现快速除法计算:原理、方法与优化
  • 南昌外贸网站建设网站建设faq
  • 杭州网站建设官方蓝韵网络网站开发授权书
  • 机器学习周报二十
  • 在 Jest 结合 Vue Test Utils 进行组件测试时,`shallowMount` 是一个常用的方法,用于创建组件的**浅渲染实例**
  • 深入理解 NAT、代理服务与内网穿透:解决网络通信的关键技术
  • Redisson 与 Spring Boot 3.4 整合指南
  • 建设房地产公司网站的费用程序员网站开发框架
  • wordpress 新闻类网站什么网站可以免费做护师题
  • C++笔记-14-结构体
  • .NET周刊【10月第3期 2025-10-19】
  • 视频时间基 (time_base) 详解:时间的“刻度单位”
  • 网站开发最佳实践wordpress连接公众号
  • 数据库-基础命令
  • 蚌埠做企业网站wordpress外网访问不了
  • Linux网络接口配置:静态IP与动态IP设置(附代码示例)
  • 做同城特价的网站qwins是哪个网站做的
  • 基础算法精讲 03 | 滑动窗口|ASCII表如如何使用|substr函数
  • 中国建设银行官网首页 网站首页网站文件目录结构
  • GitHub Actions for AI:构建企业级模型CI/CD流水线
  • DevOps——CI/CD持续集成与持续交付/部署的理解与部署
  • 建立网站的公司平台七牛云存储 wordpress连接失败
  • 利用DeepSeek辅助修改luadbi-duckdb读取DuckDB decimal数据类型
  • 深圳网站设计网站制作深圳网站建设推进
  • 电力电子技术 第十三章——PWM逆变器
  • 网站建设方案应该怎么写wordpress用户评论图片
  • xtuoj 2021
  • 数据科学每日总结--Day8--数据挖掘
  • 达梦DEM监控工具部署