RT-Thread 时钟 timer delay 相关

前言

  • 此处,介绍对delay 时钟 timer 这几部分之间的关联和相关的知识点;
  • 本来只是想介绍一下 delay的,但是发现说到delay 不先 提到 先验知识 晶振\时钟\时钟节拍\定时器 好像没法解释透彻,所以就变成了 晶振\时钟\时钟节拍\定时器\delay 的很简单的概括一遍;
  • 并附带上能直接运行的示例代码;

一个可以跳过的Tip -> 为了大家方便跳过,我设置成了图片,赶时间可以不点开

在这里插入图片描述


晶振 \ 时钟 \ 时钟节拍 \ 定时器 \ delay

定义

  • 晶振(Crystal Oscillator):
    晶振是硬件级别的时钟源,为微控制器(MCU)提供基准频率。它是系统所有时间相关功能的根基。晶振的频率决定了MCU的主时钟频率,通常称为HCLK(主时钟)。这个频率是非常重要的,因为它直接影响到微控制器的执行速度和整个系统的性能。
  • 时钟(Clock):
    在 RT-Thread 中,时钟通常指的是系统时钟,它是由晶振通过分频、倍频等方式产生的。系统时钟为操作系统和应用程序提供时间基准。系统时钟可以分为不同的类别,如核心时钟、外设时钟等,它们由晶振经过不同的处理得到。
  • 时钟节拍(Tick):
    时钟节拍是操作系统的基本时间单位,RT-Thread 通过硬件定时器来产生固定频率的时钟节拍。每一个时钟节拍代表操作系统中一个最小的时间片段。操作系统利用这些时钟节拍来进行任务调度、延时处理等操作。时钟节拍的频率(通常称为Tick Rate)决定了系统调度的精度和响应速度。例如,一个Tick Rate为1000Hz的系统每个时钟节拍代表1ms。
  • 定时器(Timer):
    定时器是基于时钟节拍工作的,用于执行定时任务。在 RT-Thread 中,定时器可以是一次性的或周期性的。定时器使用时钟节拍来计算时间,当达到指定的时钟节拍数时,定时器超时并执行相应的回调函数。
  • delay:
    delay 函数(在 RT-Thread 中通常为 rt_thread_delay())用于暂停当前线程执行指定的时间段。这个延时是以时钟节拍为单位的。当线程调用 rt_thread_delay() 时,它会被挂起,直到指定的时钟节拍数过去。在这段时间内,调度器会将CPU控制权转移给其他就绪状态的线程。

前面的解释可能太长了,我们再精简一点


  • 晶振(Crystal Oscillator):
    晶振提供了硬件级别的时钟源,它确定了微控制器(MCU)的主时钟频率(HCLK),这直接影响微控制器的执行速度和整个系统的性能。晶振是所有时间管理和计时功能的基础。
  • 时钟(Clock):
    系统时钟是由晶振产生的,可以通过分频、倍频等方式调整,为操作系统和应用程序提供时间基准。时钟可以有不同的类型(如核心时钟、外设时钟),它们支持系统各个部分的运作和时间管理。
  • 时钟节拍(Tick):
    时钟节拍是由系统时钟驱动的,表示操作系统的基本时间单位,用于任务调度和时间管理。时钟节拍的频率(Tick Rate)决定了系统的调度精度和响应速度,每个时钟节拍代表了系统中的一个固定时间片。
  • 定时器(Timer):
    定时器利用时钟节拍来计划和执行定时任务。它可以设置为一次性或周期性,用于在特定的时间点或经过特定时间段后执行任务。定时器的工作是基于时钟节拍的,它们使得在精确的时间执行任务成为可能。
  • delay:
    rt_thread_delay() 函数用于使当前线程暂停执行特定的时钟节拍数,从而提供延时功能。如果调用官方api,在此期间,CPU的控制权会转移给其他就绪状态的线程,实现有效的多任务处理。

一句话概括


  • 晶振为系统提供基本的时间频率,系统时钟根据晶振调整形成不同的时间基准
  • 时钟节拍根据系统时钟生成,为操作系统提供一个均匀的时间度量
  • 定时器和延时功能(delay)则是基于这些时钟节拍来安排和管理时间和任务的执行。
  • 观察 \ 运行 \ 修改 下方代码,获得更深入了解

示例代码

  • 通过这个示例,可以展示 RT-Thread 如何处理线程延时和定时器回调,以及如何利用系统的时钟节拍来进行时间管理和任务调度。
  • 在这个示例中,我们首先创建了一个线程 my_thread,它在一个循环中每隔一秒打印一次计数器 count 的值,并通过 rt_thread_delay() 函数实现延时。RT_TICK_PER_SECOND 定义了一秒内的时钟节拍数,因此 rt_thread_delay(RT_TICK_PER_SECOND) 将使线程延时一秒。
  • 接下来,我们创建了一个周期性定时器 my_timer,它每秒触发一次,并在每次触发时打印出 “Timer tick”。定时器使用 RT_TICK_PER_SECOND 作为超时时间,设置为周期性定时器 RT_TIMER_FLAG_PERIODIC,这意味着它会每隔一秒自动重启并触发回调函数 timer_callback。
#include <rtthread.h>

#define THREAD_PRIORITY 25
#define THREAD_STACK_SIZE 512
#define THREAD_TIMESLICE 5

/* 定义线程控制块 */
static struct rt_thread my_thread;
/* 定义线程栈 */
ALIGN(RT_ALIGN_SIZE)
static rt_uint8_t my_thread_stack[THREAD_STACK_SIZE];

/* 线程入口函数 */
static void my_thread_entry(void *parameter)
{
    rt_uint32_t count = 0;

    /* 线程主循环 */
    while (1)
    {
        /* 打印信息并延时一秒 */
        rt_kprintf("Thread count: %d\n", count++);
        rt_thread_delay(RT_TICK_PER_SECOND); // 延时1秒,RT_TICK_PER_SECOND是系统时钟节拍数,代表一秒
    }
}

/* 定时器回调函数 */
static void timer_callback(void *parameter)
{
    rt_kprintf("Timer tick\n");
}

/* 应用程序入口 */
int main(void)
{
    rt_timer_t my_timer;
    rt_err_t result;

    /* 初始化线程 */
    result = rt_thread_init(&my_thread,
                            "mythread",
                            my_thread_entry,
                            RT_NULL,
                            &my_thread_stack[0],
                            sizeof(my_thread_stack),
                            THREAD_PRIORITY,
                            THREAD_TIMESLICE);
    if (result == RT_EOK)
    {
        rt_thread_startup(&my_thread);
    }

    /* 创建定时器 */
    my_timer = rt_timer_create("mytimer",          // 定时器名称
                               timer_callback,     // 定时器到期时回调的函数
                               RT_NULL,            // 调用回调函数时传递的参数
                               RT_TICK_PER_SECOND, // 定时时间,这里设置为1秒
                               RT_TIMER_FLAG_PERIODIC); // 定时器模式,周期性执行

    /* 启动定时器 */
    if (my_timer != RT_NULL)
    {
        rt_timer_start(my_timer);
    }

    return 0;
}


  • 写到这里了,其实对 delay 定时器 基本的了解已经搭建起来了,其实对于开发而言,差不多够用了
  • 感兴趣的话,可以继续往下翻,我们看一下更深入的准确的定义

在这里插入图片描述


定义

  • delay 和 sleep 是两种差不多的操作在不同平台上的叫法
  • 一般不需要太过关注如何区分,在这里我们看作是一样的
  • delay 我们这里提到两种实现方式,一种是通过估计计算耗时来实现延时;另一种是 Timer定时器实现;通过估计计算耗时的方式我们没什么好说的,我们关注的是 相对智能的\高效的 基于 时钟(timer)实现的
  • 在介绍之前,我们需要一起提到 晶振\时钟\时钟节拍\定时器\delay 之间的关系
  • 在 RT-Thread 实时操作系统中,delay 函数(如 rt_thread_delay())用于挂起当前线程一定的时间。在这段时间内,CPU 将不会执行当前线程,而是转而执行其他的就绪状态线程。如果没有其他线程处于就绪状态,则可能执行空闲线程(idle thread),该线程通常用于执行低优先级的后台任务,如内存清理和系统监视。

  • RT-Thread 的 rt_thread_delay() 函数是专门设计用于多任务环境的,不同于 MicroPython 的 time.sleep(),RT-Thread 的延时操作是为多线程设计的,确实会将 CPU 时间让给其他的线程。这是因为 RT-Thread 是一个完整的实时操作系统,支持多线程和任务调度,所以它可以在一个线程暂停执行时调度其他线程运行。

  • 在 RT-Thread 中,当你调用 rt_thread_delay() 时,你实际上是将当前线程放入睡眠状态直到指定的延时时间过去。这个功能使得 CPU 资源可以被有效地分配给其他需要执行的线程,从而提高系统的总体效率和响应性。

  • 总结来说,RT-Thread 中的 delay 类操作(如 rt_thread_delay())确实会导致当前线程挂起,并允许其他线程使用 CPU。这与 MicroPython 中的 time.sleep() 在操作系统层面上有相似的效果,尽管底层的实现机制和支持的功能可能不同,因为 RT-Thread 是一个多线程的实时操作系统,而 MicroPython 通常运行在单线程环境中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/405676.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构】链式队列

链式队列实现&#xff1a; 1.创建一个空队列 2.尾插法入队 3.头删法出队 4.遍历队列 一、main函数 #include <stdio.h> #include "./3.linkqueue.h" int main(int…

备考2025年AMC8数学竞赛:2000-2024年AMC8真题练一练

我们今天来随机看五道AMC8的真题和解析&#xff0c;对于想了解或者加AMC8美国数学竞赛的孩子来说&#xff0c;吃透AMC8历年真题是备考最科学、最有效的方法之一。 为帮助孩子们更高效地备考&#xff0c;我整理了2000-2004年的全部AMC8真题&#xff0c;并且独家制作了多种在线练…

Rust通用代码生成器莲花发布红莲尝鲜版二十一发布介绍视频,前端代码生成物大翻新

Rust通用代码生成器莲花发布红莲尝鲜版二十一发布介绍视频&#xff0c;前端代码生成物大翻新 Rust通用代码生成器发布了红莲尝鲜版二十一的最新介绍视频&#xff0c;前端代码生成物大翻新。视频请见&#xff1a; Rust通用代码生成器&#xff1a;莲花&#xff0c;红莲尝鲜版二…

构建生物医学知识图谱from zero to hero (3):生物医学命名实体识别和链接

生物医学实体链接 🤓现在是激动人心的部分。对于NLP和命名实体识别和链接的新手,让我们从一些基础知识开始。命名实体识别技术用于检测文本中的相关实体或概念。例如,在生物医学领域,我们希望在文本中识别各种基因、药物、疾病和其他概念。 生物医学概念提取 在这个例子中…

爬虫知识--03

数据存mysql import requests from bs4 import BeautifulSoup import pymysql# 链接数据库pymysql conn pymysql.connect(userroot,password"JIAJIA",host127.0.0.1,databasecnblogs,port3306, ) cursor conn.cursor() cursor conn.cursor()# 爬数据 res request…

Linux之ACL访问控制列表

一、ACL权限的介绍 1.1 什么是ACL 访问控制列表&#xff08;ACL&#xff09;是一种网络安全技术&#xff0c;它通过在网络设备&#xff08;如路由器、交换机和防火墙&#xff09;上定义一系列规则&#xff0c;对进出接口的数据包进行控制。这些规则可以包含“允许”&…

计算机网络面经_体系结构一文说清

编辑&#xff1a;平平无奇的羊 目录 基础 1. 计算机网络结构体系 三种模型之间的区别&#xff1a; 如何背诵&#xff1a; 进阶 OSI七层模型&#xff1a; TCP/IP四层模型&#xff1a; TCP/IP五层模型 总结 字节实习生为大家带来的是计算机网络面经系列博文&#xff0c;由浅…

线性代数:向量、张量、矩阵和标量

线性代数&#xff1a;向量、张量、矩阵和标量 背景 在线性代数中&#xff0c;向量、张量、矩阵和标量都属于基础概念&#xff0c;特别是最近AI的爆火&#xff0c;向量和张量的概念也越来越普及&#xff0c;本文将介绍下这些基本概念。 1. 标量&#xff08;Scalar&#xff0…

【Java网络编程06】HTTPS原理

1. HTTPS基本概念 HTTPS&#xff1a;HTTPS也是一个应用层协议&#xff0c;它在HTTP协议的基础上引入了一个加密层——SSL协议&#xff0c;区别就在于HTTP协议是基于明文传输的&#xff08;不安全&#xff09;&#xff0c;使用HTTPS加密就能在一定程度上防止数据在传输过程中被…

c# 类的介绍及延伸

类介绍 类的定义是以关键字 class 开始&#xff0c;后跟类的名称。 类属于引用类型&#xff0c;只能通过new方式创建。 如果类定义中没有指定基类&#xff0c;那其基类为system.object // <访问修饰符> class class类名 <access specifier> class class_name { //…

华为配置WDS手拉手业务示例

配置WDS手拉手业务示例 组网图形 图1 配置WDS手拉手业务示例组网图 业务需求组网需求数据规划配置思路配置注意事项操作步骤配置文件 业务需求 企业用户通过WLAN接入网络&#xff0c;以满足移动办公的最基本需求。但企业考虑到AP通过有线部署的成本较高&#xff0c;所以通过建立…

golang 监听ip数据包(golang纯享版)

golang 监听ip数据包(golang纯享版) 【注】本机编译运行平台为linux&#xff0c;如需测试代码请移至linux平台进行代码测试 本文以ip4 作为案例进行包抓取示范&#xff0c;ip6抓取与ip4方式异曲同工&#xff0c;可自行举一反三得出 第一步&#xff0c;通过wireshark抓包拿到…

第四十二回 假李逵翦径劫单身 黑旋风沂岭杀四虎-python读写csv和json数据

李逵答应了宋江三件事&#xff1a;不可吃酒&#xff0c;独自前行&#xff0c;不带板斧。李逵痛快答应了&#xff0c;挎一口腰刀&#xff0c;提着朴刀&#xff0c;带了一锭大银子&#xff0c;三五个小银子就下山去了。 宋江放心不下&#xff0c;于是请同乡朱贵也回家一趟&#…

spring boot3登录开发-3(账密登录逻辑实现)

⛰️个人主页: 蒾酒 &#x1f525;系列专栏&#xff1a;《spring boot实战》 &#x1f30a;山高路远&#xff0c;行路漫漫&#xff0c;终有归途。 目录 前置条件 内容简介 用户登录逻辑实现 创建交互对象 1.创建用户登录DTO 2.创建用户登录VO 创建自定义登录业务异…

Vue模板引用之ref特殊属性

1. 使用实例 <template><input ref"input" name"我是input的name" /><br /><ul><li v-for"arr in array" :key"arr" id"111" ref"itemRefs">{{arr}}</li></ul> </…

windows11本地深度学习环境搭建Anacond,keras,tensorflow,pytorch, jupyter notebook

前言 工欲善其事&#xff0c;必先利其器。 第一步 安装Anaconda 下载地址&#xff1a; https://www.anaconda.com/download 路径默认 这里都勾选上 然后会卡在这里&#xff0c;卡很久&#xff0c;不用管&#xff0c;等着就行 第二步 配置环境 conda env list 列出所有…

css复习

盒模型相关&#xff1a; border&#xff1a;1px solid red (没有顺序) 单元格的border会发生重叠&#xff0c;如果不想要重叠设置 border-collapse:collapse (表示相邻边框合并在一起) padding padding影响盒子大小的好处使用 margin应用&#xff1a; 行内或行内块元素水…

XFF伪造 [MRCTF2020]PYWebsite1

打开题目 直接查看源码 看到一个./flag.php 访问一下 购买者的ip已经被记录&#xff0c;本地可以看到flag&#xff0c;那么使用xff或者client-ip伪造一下ip试试 bp抓包 加一个X-Forwarded-For头 得到flag

GPT-SoVITS 快速声音克隆使用案例:webui、api接口

参考: https://github.com/RVC-Boss/GPT-SoVITS 环境: Python 3.10 PyTorch 2.1.2, CUDA 12.0 安装包: 1、使用: 1)下载项目 git clone https://github.com/RVC-Boss/GPT-SoVITS.git2)下载预训练模型 https://huggingface.co/lj1995/GPT-SoVITS 下载模型文件放到GPT…

高刷电竞显示器 - HKC VG253KM

今天给大家分享一款高刷电竞显示器 - HKC VG253KM。 高刷电竞显示器 - HKC VG253KM源于雄鹰展翅翱翔的设计灵感&#xff0c;严格遵循黄金分割比例的蓝色点晴线条&#xff0c;加上雾面工艺及高低起伏错落有致的线条处理&#xff0c;在VG253KM的背部勾勒出宛若大鹏展翅的鹰翼图腾…
最新文章