RT-Thread的时钟管理机制是怎样的?

2026-04-28 10:571阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计3254个文字,预计阅读时间需要14分钟。

RT-Thread的时钟管理机制是怎样的?

一、时钟节拍+任何操作系统都需要提供时钟节拍,以处理与时间和事件相关的任务,如线程的延时、时间片轮转调度以及定时器超时等。时钟节拍是周期性的中断,确保系统能够按特定周期执行。

一、时钟节拍

任何操作系统都需要提供一个时钟节拍,以供系统处理所有和时间有关的事件,如线程的延时、线程的时间片轮转调度以及定时器超时等。时钟节拍是特定的周期性中断,这个中断可以看做是系统心跳,中断之间的时间间隔取决于不同的应用,一般是 1ms–100ms,时钟节拍率越快,系统的实时响应越快,但是系统的额外开销就越大,从系统启动开始计数的时钟节拍数称为系统时间。

RT-Thread 中,时钟节拍的长度可以根据 RT_TICK_PER_SECOND 的定义来调整,等于 1/RT_TICK_PER_SECOND 秒。

  • 实现方式
    RT-Thread在board.c文件中实现了SysTick_Handler中断函数,在rt_hw_board_init()函数中设置了系统的时钟节拍,也就是1/RT_TICK_PER_SECOND 秒会发生一次中断。如下图所示:

    从图中可以,当中断函数发生时都会调用一次 rt_tick_increase() 对全局变量 rt_tick 进行自加,代码如下所示:

    void rt_tick_increase(void) { struct rt_thread *thread; /* 全局变量 rt_tick 自加 */ ++ rt_tick; /* 检查时间片 */ thread = rt_thread_self(); -- thread->remaining_tick; if (thread->remaining_tick == 0) { /* 重新赋初值 */ thread->remaining_tick = thread->init_tick; /* 线程挂起 */ rt_thread_yield(); } /* 检查定时器 */ rt_timer_check(); }

    可以看到全局变量 rt_tick 在每经过一个时钟节拍时,值就会加 1,rt_tick 的值表示了系统从启动开始总共经过的时钟节拍数,即系统时间。此外,每经过一个时钟节拍时,都会检查当前线程的时间片是否用完,以及是否有定时器超时。

    注意:中断中的 rt_timer_check() 用于检查系统硬件定时器链表,如果有定时器超时,将调用相应的超时函数。且所有定时器在定时超时后都会从定时器链表中被移除,而周期性定时器会在它再次启动时被加入定时器链表。

二、定时器管理

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

  1. 定时器介绍
    RT-Thread定时器提供两类定时器机制:一种是只会触发一次的定时器;另一种是周期性触发定时器。另外根据超时函数执行时所处的上下文环境,RT-Thread 的定时器可以分为 HARD_TIMER 模式与 SOFT_TIMER 模式,如下图。
  • HARD_TIMER 模式
    1)HARD_TIMER 模式是在中断过程中执行,可以在初始化 / 创建定时器时使用参数 RT_TIMER_FLAG_HARD_TIMER 来指定。
    2)在HARD_TIMER 模式中不能申请动态内存、释放动态内存等。
    3)中断是优先级最好的抢占式服务,所以不能在HARD_TIMER 模式下的超时函数中执行长时间的占用操作。

  • SOFT_TIMER 模式
    1)通过宏定义 RT_USING_TIMER_SOFT 来决定是否启用该模式
    2)SOFT_TIMER 模式的定时器超时函数在都会在 timer 线程的上下文环境中执行。
    3)初始化 / 创建定时器时使用参数 RT_TIMER_FLAG_SOFT_TIMER 来指定设置 SOFT_TIMER 模式。

  1. 定时器工作机制
    在 RT-Thread 定时器模块中维护着两个重要的全局变量:

    • 当前系统经过的 tick 时间 rt_tick(当硬件定时器中断来临时,它将加 1);
    • 定时器链表 rt_timer_list。系统新创建并激活的定时器都会按照以超时时间排序的方式插入到 rt_timer_list 链表中。

    注意:t_timer_list 链表是一个有序链表,当创建了一个新的tick值时,在链表中的添加如下图所示:

  2. 定时器跳表 (Skip List) 算法
    如下图所示,从该有序链表中搜索元素 {13, 39},需要比较的次数分别为 {3, 5},总共比较的次数为 3 + 5 = 8 次。

    使用跳表算法,把一些节点提取出来作为索引,得到如下图所示的结构。在这个结构里把 {3, 18,77} 提取出来作为一级索引,这样搜索的时候就可以减少比较次数了, 例如在搜索 39 时仅比较了 3 次(通过比较 3,18,39)。

    注意:跳表算法可以提取多级索引,在 RT-Thread 中通过宏定义 RT_TIMER_SKIP_LIST_LEVEL 来配置跳表的层数,默认为 1。

  3. 定时器控制快
    RT-Thread 在 rtdef.h 文件中定义了结构体 struct rt_timer ,如下所示:

    struct rt_timer { struct rt_object parent; rt_list_t row[RT_TIMER_SKIP_LIST_LEVEL]; /* 定时器链表节点 */ void (*timeout_func)(void *parameter); /* 定时器超时调用的函数 */ void *parameter; /* 超时函数的参数 */ rt_tick_t init_tick; /* 定时器初始超时节拍数 */ rt_tick_t timeout_tick; /* 定时器实际超时时的节拍数 */ }; typedef struct rt_timer *rt_timer_t;

三、定时器函数

在系统启动时,会在 rtthread_startup 函数中调用 rt_system_timer_init 函数和 rt_system_timer_thread_init 函数,如下所示:

// 初始化定时器管理系统 void rt_system_timer_init(void); // 计时器线程初始化 void rt_system_timer_thread_init(void);

定时器的相关操作如下图所示:

  1. 获取时钟节拍

    rt_tick_t rt_tick_get(void);

    • rt_tick_t:返回当前时钟节拍值 rt_tick
  2. 动态创建定时器

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

    • name:定时器的名称

    • void (timeout) (void parameter): 定时器超时函数指针(当定时器超时时,系统会调用这个函数)

    • parameter:定时器超时函数的入口参数(当定时器超时时,调用超时回调函数会把这个参数做为入口参数传递给超时函数)

    • time:定时器的超时时间,单位是时钟节拍

    • flag:定时器创建时的参数,支持的值包括单次定时、周期定时、硬件定时器、软件定时器等(可以用 “或” 关系取多个值)

    • rt_timer_t :RT_NULL:创建失败(通常会由于系统内存不够用而返回 RT_NULL)。创建成功是返回定时器的句柄

    • flag 的值在rtdef.h 中定义了相关的宏:

      #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 /* 软件定时器 */

    注意: 上面 2 组值可以以 “或” 逻辑的方式赋给 flag。

  3. 删除动态定时器

    rt_err_t rt_timer_delete(rt_timer_t timer);

    • timer:定时器句柄,指向要删除的定时器
    • rt_err_t:RT_EOK:删除成功(如果参数 timer 句柄是一个 RT_NULL,将会导致一个 ASSERT 断言)
  4. 创建静态定时器

    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);

    • timer:定时器句柄,指向要初始化的定时器控制块
    • name:定时器的名称
    • void (timeout) (void parameter):定时器超时函数指针(当定时器超时时,系统会调用这个函数)
    • parameter:定时器超时函数的入口参数(当定时器超时时,调用超时回调函数会把这个参数做为入口参数传递给超时函数)
    • time:定时器的超时时间,单位是时钟节拍
    • flag:定时器创建时的参数,支持的值包括单次定时、周期定时、硬件定时器、软件定时器(可以用 “或” 关系取多个值),详见创建定时器小节
  5. 删除静态定时器

    rt_err_t rt_timer_detach(rt_timer_t timer);

    • timer:定时器句柄,指向要脱离的定时器控制块
    • rt_err_t :RT_EOK:脱离成功
  6. 启动定时器

    rt_err_t rt_timer_start(rt_timer_t timer);

    • timer:定时器句柄,指向要启动的定时器控制块
    • rt_err_t :RT_EOK:启动成功
  7. 停止定时器

    RT-Thread的时钟管理机制是怎样的?

    rt_err_t rt_timer_stop(rt_timer_t timer);

    • timer:定时器句柄,指向要启动的定时器控制块
    • rt_err_t :RT_EOK:成功停止定时器,RT_ERROR:timer 已经处于停止状态
  8. 控制定时器

    rt_err_t rt_timer_control(rt_timer_t timer, rt_uint8_t cmd, void* arg);

    • timer:定时器句柄,指向要启动的定时器控制块
    • cmd :用于控制定时器的命令,当前支持四个命令,分别是设置定时时间,查看定时时间,设置单次触发,设置周期触发
    • arg:与 cmd 相对应的控制命令参数 比如,cmd 为设定超时时间时,就可以将超时时间参数通过 arg 进行设定
    • rt_err_t :RT_EOK:成功
    • cmd 支持的命令:

      #define RT_TIMER_CTRL_SET_TIME 0x0 /* 设置定时器超时时间 */ #define RT_TIMER_CTRL_GET_TIME 0x1 /* 获得定时器超时时间 */ #define RT_TIMER_CTRL_SET_ONESHOT 0x2 /* 设置定时器为单次定时器 */ #define RT_TIMER_CTRL_SET_PERIODIC 0x3 /* 设置定时器为周期型定时器 */

四、应用实例 动态定时器使用

#include "stm32f10x.h" #include "drv_gpio.h" #include "drv_usart.h" #include <rtthread.h> /* 定时器的控制块 */ static rt_timer_t timer1; static rt_timer_t timer2; static int cnt = 0; /* 定时器 1 超时函数 */ static void timeout1(void *parameter) { rt_kprintf("periodic timer is timeout %d\n", cnt); /* 运行第 10 次,停止周期定时器 */ if (cnt++>= 9) { rt_timer_stop(timer1); rt_kprintf("periodic timer was stopped! \n"); } } /* 定时器 2 超时函数 */ static void timeout2(void *parameter) { rt_kprintf("one shot timer is timeout\n"); } int timer_sample(void) { /* 创建定时器 1 周期定时器 */ timer1 = rt_timer_create("timer1", timeout1, RT_NULL, 10, RT_TIMER_FLAG_PERIODIC); /* 启动定时器 1 */ if (timer1 != RT_NULL) rt_timer_start(timer1); /* 创建定时器 2 单次定时器 */ timer2 = rt_timer_create("timer2", timeout2, RT_NULL, 30, RT_TIMER_FLAG_ONE_SHOT); /* 启动定时器 2 */ if (timer2 != RT_NULL) rt_timer_start(timer2); return 0; } int main(void) { rt_kprintf("RT-Thread Start...... \n"); timer_sample(); while (1) { GPIO_ResetBits(GPIOB,GPIO_Pin_12); rt_thread_delay(1000); // 延时1000 ms GPIO_SetBits(GPIOB, GPIO_Pin_12 ); rt_thread_delay(1000); // 延时1000 ms } }

运行结果如下:

静态定时器使用

#include "stm32f10x.h" #include "drv_gpio.h" #include "drv_usart.h" #include <rtthread.h> /* 定时器的控制块 */ static struct rt_timer timer1; static struct rt_timer timer2; static int cnt = 0; /* 定时器 1 超时函数 */ static void timeout1(void* parameter) { rt_kprintf("periodic timer is timeout\n"); /* 运行 10 次 */ if (cnt++>= 9) { rt_timer_stop(&timer1); } } /* 定时器 2 超时函数 */ static void timeout2(void* parameter) { rt_kprintf("one shot timer is timeout\n"); } int timer_static_sample(void) { /* 初始化定时器 */ rt_timer_init(&timer1, "timer1", /* 定时器名字是 timer1 */ timeout1, /* 超时时回调的处理函数 */ RT_NULL, /* 超时函数的入口参数 */ 10, /* 定时长度,以 OS Tick 为单位,即 10 个 OS Tick */ RT_TIMER_FLAG_PERIODIC); /* 周期性定时器 */ rt_timer_init(&timer2, "timer2", /* 定时器名字是 timer2 */ timeout2, /* 超时时回调的处理函数 */ RT_NULL, /* 超时函数的入口参数 */ 30, /* 定时长度为 30 个 OS Tick */ RT_TIMER_FLAG_ONE_SHOT); /* 单次定时器 */ /* 启动定时器 */ rt_timer_start(&timer1); rt_timer_start(&timer2); return 0; } int main(void) { rt_kprintf("RT-Thread Start...... \n"); timer_static_sample(); while (1) { GPIO_ResetBits(GPIOB,GPIO_Pin_12); rt_thread_delay(1000); // 延时1000 ms GPIO_SetBits(GPIOB, GPIO_Pin_12 ); rt_thread_delay(1000); // 延时1000 ms } }

运行结果如下:

参考文献

RT-Thread文档中心:www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/README

如本博客的内容侵犯了你的权益,请与以下地址联系,本人获知后,马上删除。同时本人深表歉意,并致以崇高的谢意! computer_wx@foxmail.com

本文共计3254个文字,预计阅读时间需要14分钟。

RT-Thread的时钟管理机制是怎样的?

一、时钟节拍+任何操作系统都需要提供时钟节拍,以处理与时间和事件相关的任务,如线程的延时、时间片轮转调度以及定时器超时等。时钟节拍是周期性的中断,确保系统能够按特定周期执行。

一、时钟节拍

任何操作系统都需要提供一个时钟节拍,以供系统处理所有和时间有关的事件,如线程的延时、线程的时间片轮转调度以及定时器超时等。时钟节拍是特定的周期性中断,这个中断可以看做是系统心跳,中断之间的时间间隔取决于不同的应用,一般是 1ms–100ms,时钟节拍率越快,系统的实时响应越快,但是系统的额外开销就越大,从系统启动开始计数的时钟节拍数称为系统时间。

RT-Thread 中,时钟节拍的长度可以根据 RT_TICK_PER_SECOND 的定义来调整,等于 1/RT_TICK_PER_SECOND 秒。

  • 实现方式
    RT-Thread在board.c文件中实现了SysTick_Handler中断函数,在rt_hw_board_init()函数中设置了系统的时钟节拍,也就是1/RT_TICK_PER_SECOND 秒会发生一次中断。如下图所示:

    从图中可以,当中断函数发生时都会调用一次 rt_tick_increase() 对全局变量 rt_tick 进行自加,代码如下所示:

    void rt_tick_increase(void) { struct rt_thread *thread; /* 全局变量 rt_tick 自加 */ ++ rt_tick; /* 检查时间片 */ thread = rt_thread_self(); -- thread->remaining_tick; if (thread->remaining_tick == 0) { /* 重新赋初值 */ thread->remaining_tick = thread->init_tick; /* 线程挂起 */ rt_thread_yield(); } /* 检查定时器 */ rt_timer_check(); }

    可以看到全局变量 rt_tick 在每经过一个时钟节拍时,值就会加 1,rt_tick 的值表示了系统从启动开始总共经过的时钟节拍数,即系统时间。此外,每经过一个时钟节拍时,都会检查当前线程的时间片是否用完,以及是否有定时器超时。

    注意:中断中的 rt_timer_check() 用于检查系统硬件定时器链表,如果有定时器超时,将调用相应的超时函数。且所有定时器在定时超时后都会从定时器链表中被移除,而周期性定时器会在它再次启动时被加入定时器链表。

二、定时器管理

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

  1. 定时器介绍
    RT-Thread定时器提供两类定时器机制:一种是只会触发一次的定时器;另一种是周期性触发定时器。另外根据超时函数执行时所处的上下文环境,RT-Thread 的定时器可以分为 HARD_TIMER 模式与 SOFT_TIMER 模式,如下图。
  • HARD_TIMER 模式
    1)HARD_TIMER 模式是在中断过程中执行,可以在初始化 / 创建定时器时使用参数 RT_TIMER_FLAG_HARD_TIMER 来指定。
    2)在HARD_TIMER 模式中不能申请动态内存、释放动态内存等。
    3)中断是优先级最好的抢占式服务,所以不能在HARD_TIMER 模式下的超时函数中执行长时间的占用操作。

  • SOFT_TIMER 模式
    1)通过宏定义 RT_USING_TIMER_SOFT 来决定是否启用该模式
    2)SOFT_TIMER 模式的定时器超时函数在都会在 timer 线程的上下文环境中执行。
    3)初始化 / 创建定时器时使用参数 RT_TIMER_FLAG_SOFT_TIMER 来指定设置 SOFT_TIMER 模式。

  1. 定时器工作机制
    在 RT-Thread 定时器模块中维护着两个重要的全局变量:

    • 当前系统经过的 tick 时间 rt_tick(当硬件定时器中断来临时,它将加 1);
    • 定时器链表 rt_timer_list。系统新创建并激活的定时器都会按照以超时时间排序的方式插入到 rt_timer_list 链表中。

    注意:t_timer_list 链表是一个有序链表,当创建了一个新的tick值时,在链表中的添加如下图所示:

  2. 定时器跳表 (Skip List) 算法
    如下图所示,从该有序链表中搜索元素 {13, 39},需要比较的次数分别为 {3, 5},总共比较的次数为 3 + 5 = 8 次。

    使用跳表算法,把一些节点提取出来作为索引,得到如下图所示的结构。在这个结构里把 {3, 18,77} 提取出来作为一级索引,这样搜索的时候就可以减少比较次数了, 例如在搜索 39 时仅比较了 3 次(通过比较 3,18,39)。

    注意:跳表算法可以提取多级索引,在 RT-Thread 中通过宏定义 RT_TIMER_SKIP_LIST_LEVEL 来配置跳表的层数,默认为 1。

  3. 定时器控制快
    RT-Thread 在 rtdef.h 文件中定义了结构体 struct rt_timer ,如下所示:

    struct rt_timer { struct rt_object parent; rt_list_t row[RT_TIMER_SKIP_LIST_LEVEL]; /* 定时器链表节点 */ void (*timeout_func)(void *parameter); /* 定时器超时调用的函数 */ void *parameter; /* 超时函数的参数 */ rt_tick_t init_tick; /* 定时器初始超时节拍数 */ rt_tick_t timeout_tick; /* 定时器实际超时时的节拍数 */ }; typedef struct rt_timer *rt_timer_t;

三、定时器函数

在系统启动时,会在 rtthread_startup 函数中调用 rt_system_timer_init 函数和 rt_system_timer_thread_init 函数,如下所示:

// 初始化定时器管理系统 void rt_system_timer_init(void); // 计时器线程初始化 void rt_system_timer_thread_init(void);

定时器的相关操作如下图所示:

  1. 获取时钟节拍

    rt_tick_t rt_tick_get(void);

    • rt_tick_t:返回当前时钟节拍值 rt_tick
  2. 动态创建定时器

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

    • name:定时器的名称

    • void (timeout) (void parameter): 定时器超时函数指针(当定时器超时时,系统会调用这个函数)

    • parameter:定时器超时函数的入口参数(当定时器超时时,调用超时回调函数会把这个参数做为入口参数传递给超时函数)

    • time:定时器的超时时间,单位是时钟节拍

    • flag:定时器创建时的参数,支持的值包括单次定时、周期定时、硬件定时器、软件定时器等(可以用 “或” 关系取多个值)

    • rt_timer_t :RT_NULL:创建失败(通常会由于系统内存不够用而返回 RT_NULL)。创建成功是返回定时器的句柄

    • flag 的值在rtdef.h 中定义了相关的宏:

      #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 /* 软件定时器 */

    注意: 上面 2 组值可以以 “或” 逻辑的方式赋给 flag。

  3. 删除动态定时器

    rt_err_t rt_timer_delete(rt_timer_t timer);

    • timer:定时器句柄,指向要删除的定时器
    • rt_err_t:RT_EOK:删除成功(如果参数 timer 句柄是一个 RT_NULL,将会导致一个 ASSERT 断言)
  4. 创建静态定时器

    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);

    • timer:定时器句柄,指向要初始化的定时器控制块
    • name:定时器的名称
    • void (timeout) (void parameter):定时器超时函数指针(当定时器超时时,系统会调用这个函数)
    • parameter:定时器超时函数的入口参数(当定时器超时时,调用超时回调函数会把这个参数做为入口参数传递给超时函数)
    • time:定时器的超时时间,单位是时钟节拍
    • flag:定时器创建时的参数,支持的值包括单次定时、周期定时、硬件定时器、软件定时器(可以用 “或” 关系取多个值),详见创建定时器小节
  5. 删除静态定时器

    rt_err_t rt_timer_detach(rt_timer_t timer);

    • timer:定时器句柄,指向要脱离的定时器控制块
    • rt_err_t :RT_EOK:脱离成功
  6. 启动定时器

    rt_err_t rt_timer_start(rt_timer_t timer);

    • timer:定时器句柄,指向要启动的定时器控制块
    • rt_err_t :RT_EOK:启动成功
  7. 停止定时器

    RT-Thread的时钟管理机制是怎样的?

    rt_err_t rt_timer_stop(rt_timer_t timer);

    • timer:定时器句柄,指向要启动的定时器控制块
    • rt_err_t :RT_EOK:成功停止定时器,RT_ERROR:timer 已经处于停止状态
  8. 控制定时器

    rt_err_t rt_timer_control(rt_timer_t timer, rt_uint8_t cmd, void* arg);

    • timer:定时器句柄,指向要启动的定时器控制块
    • cmd :用于控制定时器的命令,当前支持四个命令,分别是设置定时时间,查看定时时间,设置单次触发,设置周期触发
    • arg:与 cmd 相对应的控制命令参数 比如,cmd 为设定超时时间时,就可以将超时时间参数通过 arg 进行设定
    • rt_err_t :RT_EOK:成功
    • cmd 支持的命令:

      #define RT_TIMER_CTRL_SET_TIME 0x0 /* 设置定时器超时时间 */ #define RT_TIMER_CTRL_GET_TIME 0x1 /* 获得定时器超时时间 */ #define RT_TIMER_CTRL_SET_ONESHOT 0x2 /* 设置定时器为单次定时器 */ #define RT_TIMER_CTRL_SET_PERIODIC 0x3 /* 设置定时器为周期型定时器 */

四、应用实例 动态定时器使用

#include "stm32f10x.h" #include "drv_gpio.h" #include "drv_usart.h" #include <rtthread.h> /* 定时器的控制块 */ static rt_timer_t timer1; static rt_timer_t timer2; static int cnt = 0; /* 定时器 1 超时函数 */ static void timeout1(void *parameter) { rt_kprintf("periodic timer is timeout %d\n", cnt); /* 运行第 10 次,停止周期定时器 */ if (cnt++>= 9) { rt_timer_stop(timer1); rt_kprintf("periodic timer was stopped! \n"); } } /* 定时器 2 超时函数 */ static void timeout2(void *parameter) { rt_kprintf("one shot timer is timeout\n"); } int timer_sample(void) { /* 创建定时器 1 周期定时器 */ timer1 = rt_timer_create("timer1", timeout1, RT_NULL, 10, RT_TIMER_FLAG_PERIODIC); /* 启动定时器 1 */ if (timer1 != RT_NULL) rt_timer_start(timer1); /* 创建定时器 2 单次定时器 */ timer2 = rt_timer_create("timer2", timeout2, RT_NULL, 30, RT_TIMER_FLAG_ONE_SHOT); /* 启动定时器 2 */ if (timer2 != RT_NULL) rt_timer_start(timer2); return 0; } int main(void) { rt_kprintf("RT-Thread Start...... \n"); timer_sample(); while (1) { GPIO_ResetBits(GPIOB,GPIO_Pin_12); rt_thread_delay(1000); // 延时1000 ms GPIO_SetBits(GPIOB, GPIO_Pin_12 ); rt_thread_delay(1000); // 延时1000 ms } }

运行结果如下:

静态定时器使用

#include "stm32f10x.h" #include "drv_gpio.h" #include "drv_usart.h" #include <rtthread.h> /* 定时器的控制块 */ static struct rt_timer timer1; static struct rt_timer timer2; static int cnt = 0; /* 定时器 1 超时函数 */ static void timeout1(void* parameter) { rt_kprintf("periodic timer is timeout\n"); /* 运行 10 次 */ if (cnt++>= 9) { rt_timer_stop(&timer1); } } /* 定时器 2 超时函数 */ static void timeout2(void* parameter) { rt_kprintf("one shot timer is timeout\n"); } int timer_static_sample(void) { /* 初始化定时器 */ rt_timer_init(&timer1, "timer1", /* 定时器名字是 timer1 */ timeout1, /* 超时时回调的处理函数 */ RT_NULL, /* 超时函数的入口参数 */ 10, /* 定时长度,以 OS Tick 为单位,即 10 个 OS Tick */ RT_TIMER_FLAG_PERIODIC); /* 周期性定时器 */ rt_timer_init(&timer2, "timer2", /* 定时器名字是 timer2 */ timeout2, /* 超时时回调的处理函数 */ RT_NULL, /* 超时函数的入口参数 */ 30, /* 定时长度为 30 个 OS Tick */ RT_TIMER_FLAG_ONE_SHOT); /* 单次定时器 */ /* 启动定时器 */ rt_timer_start(&timer1); rt_timer_start(&timer2); return 0; } int main(void) { rt_kprintf("RT-Thread Start...... \n"); timer_static_sample(); while (1) { GPIO_ResetBits(GPIOB,GPIO_Pin_12); rt_thread_delay(1000); // 延时1000 ms GPIO_SetBits(GPIOB, GPIO_Pin_12 ); rt_thread_delay(1000); // 延时1000 ms } }

运行结果如下:

参考文献

RT-Thread文档中心:www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/README

如本博客的内容侵犯了你的权益,请与以下地址联系,本人获知后,马上删除。同时本人深表歉意,并致以崇高的谢意! computer_wx@foxmail.com