STM32中的Systick的使用
SysTick,全称System Tick Timer,是Cortex-M microcontrollers内核中提供的一个简单而有效的系统定时器,设计用来给操作系统提供时间基准,或用于生成周期性的中断。STM32系列微控制器,作为基于ARM Cortex-M内核的设备,也内置了这一功能模块。
主要特点
24位递减计数器:SysTick是一个24位自动重载的递减计数器,达到0时,计数器会自动重新装载预设的值,并且可以产生一个可选的中断。
-
灵活的时钟源选择:SysTick定时器可以选择内核时钟(processor clock)或内核时钟的1/8作为其时钟源。这给了开发者根据实际需求选择时钟速度的灵活性。
-
简单易用:对于简单的延时生成、操作系统的节拍(timer tick) 或任何需要定时的任务,SysTick提供了一个简单而有效的解决方案,而不需要复杂的定时器配置。
-
固定的中断优先级:SysTick的中断优先级是在Cortex-M内核中固定的,这意味着开发者不能改变它。这为操作系统的设计提供了一定的便利,因为SysTick通常被用作系统的心跳或时间管理。
-
无需外部硬件:与其他外部或外围定时器不同,SysTick是内核内置功能,不需要其他外部硬件,可以保持系统的精简。
实现延时
开发者经常利用SysTick实现毫秒级的延时功能,这是通过配置SysTick的重载值(LOAD寄存器),并启用SysTick定时器和它的中断来实现的。每次SysTick定时器到达零,SysTick定时器会重新装载预设的值,并且可以触发中断(如果已经启用)。在中断服务程序(ISR)中可以执行相关的周期任务或标记一个周期的结束。
使用场景
- 操作系统节拍:实时操作系统(RTOS)常用SysTick定时器作为系统的基础节拍源,用于任务调度、时间管理等。
- 程序延时:在不需要精确时间管理的应用中,SysTick可以用来实现简易的延时功能,例如等待硬件准备好或实现非阻塞延迟。
- 时间测量:SysTick也可以用于程序执行时间的测量,从而帮助开发者优化代码。
总之,SysTick是Cortex-M系列微控制器中非常实用的功能,对于需要精确时间管理或操作系统支持的应用来说尤其重要。
如何初始化systick定时器
为了初始化SysTick定时器,通常需要设置定时器的重载值,选择时钟源,并可选地使能SysTick中断。以下步骤展示了如何在裸机编程中初始化SysTick定时器,不依赖特定的硬件抽象层(HAL)或类似库
步骤1: 选择SysTick时钟源
SysTick定时器可以选择使用核心时钟或核心时钟的1/8作为其时钟源。这个设置通过SysTick控制和状态寄存器(SysTick CTRL)中的CLKSOURCE位来控制。一般情况下,我们通常使用核心时钟为SysTick定时器提供时钟,以达到更高的时间精度。
SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk;
步骤2: 设置重载值(Reload Value)
SysTick的重载值决定了定时器计数到0所需要的时钟周期数。这个值根据定时器所需的时间间隔来计算,并设置在SysTick重载值寄存器(SysTick LOAD)中。重载值计算公式如下,假设您要设置的定时时间是time_ms
毫秒。
uint32_t reloadValue = (SystemCoreClock / 1000) * time_ms - 1;
SysTick->LOAD = reloadValue;
这里SystemCoreClock
变量表示系统的核心时钟频率,它需要根据实际的系统核心时钟进行设
步骤3: 使能SysTick定时器和中断(可选)
使能SysTick定时器,选择是否使能中断。如果需要定时器到0时产生中断,还需要使能SysTick中断。
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; // 使能SysTick中断
SysTick->VAL = 0; // 清空计数器
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // 启动SysTick定时器
步骤4: 实现SysTick_Handler中断服务例程(如果使能了中断)
如果你使能了SysTick中断,你需要实现SysTick_Handler()
中断服务例程(ISR)来处理中断。这个函数在SysTick计数到0时被调用。
void SysTick_Handler(void) {// 处理中断。例如,更新定时器标志,执行定时任务等。
}
以上就是初始化SysTick定时器的基本步骤。这个过程允许你根据需要配置SysTick定时器,来实现周期性的任务调度或生成准确的延时。
如何计算SysTick定时器的重载值?
计算SysTick定时器的重载值需要知道你想要定时器溢出的时间间隔以及定时器的时钟频率。以下是计算过程:
-
确定时钟频率:
- 主时钟频率 (
SystemCoreClock
): 如果你选择的是处理器的核心时钟(通常情况下)。 - 分频后的时钟频率: 如果你选择的是分频后的时钟频率,例如核心时钟频率的1/8。
- 主时钟频率 (
-
计算时间间隔对应的时钟周期数:
根据定时器的时间间隔以及定时器的时钟频率,计算出所需的时钟周期数。如果定时器的时间间隔是T
秒,定时器的时钟频率是f_clock
赫兹,则对应的时钟周期数N
可用以下公式计算:N = T * f_clock
例如,如果你需要1毫秒的时间间隔,并且SysTick的时钟频率是
SystemCoreClock
,则N = 0.001 * SystemCoreClock
- 计算重载值:
SysTick是一个24位的递减到零计数器,计数从重载值开始,并每个时钟周期递减一直到0。因此,重载值应是计数周期数减1。如果重载值设为R
:R = N - 1
这是因为从
R
递减到0正好是R + 1
个计数周期。 - 考虑24位计数器的最大值:
由于SysTick是24位的,其最大计数值是0xFFFFFF
(即16,777,215)。所以,要确保计算得出的R
不要超出这个范围。
示例:
假设:
核心时钟频率 SystemCoreClock
= 72 MHz
需要的定时器周期 T
= 1 ms(0.001秒)
计算周期数 N
为
N = 0.001 * 72 MHz = 72,000
你可以将这个值写入SysTick加载值寄存器(LOAD)来设置定时器每1毫秒溢出一次。
代码实现将类似于:
SysTick->LOAD = (uint32_t)(N - 1);
SysTick->VAL = 0x0; // 清空计数器
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk; // 使能定时器
确保你选择对的时钟源(核心时钟,或核心时钟的1/8),因为这将直接影响上面的计算。如果你决定使用分频后的时钟源,你需要在计算时将 SystemCoreClock
替换为 SystemCoreClock / 8
。
如何使用systick实现delay功能
要使用SysTick定时器实现延时(delay)功能,你需要设置SysTick以适当的速率递减,并在递减到零时进行等待或触发中断。下面是实现delay
功能的基本步骤,不使用中断,而是使用轮询的方式。
轮询方式实现:
首先你需要正确配置SysTick定时器,包括选择时钟源,设置重载值等。
配置SysTick重载值:
计算并设置SysTick重载值,以匹配你需要的延时长度。例如,如果你的核心时钟是72MHz,你想要延时1毫秒:
uint32_t ticks = SystemCoreClock / 1000;
SysTick->LOAD = ticks - 1;
SysTick->VAL = 0; // 清除当前值及计数器
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk; // 选择核心时钟并启动
实现delay
函数:
编写一个延时函数,该函数重复地加载重载值并等待SysTick递减到零
void delay_ms(uint32_t ms) {// 计算重载值(假设已经减去1且 SysTick->LOAD 直接可以使用)uint32_t ticks = (SystemCoreClock / 1000) * ms;SysTick->LOAD = (uint32_t)(ticks - 1UL);SysTick->VAL = 0UL; // 清除计数器// 等待计时器倒数到0while ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) == 0) {// 该位在倒数到0时会设置,此处空循环直到满足该条件}
}
使用以上delay_ms()
函数可以实现毫秒延时。请注意,这里SysTick是设置了一次并等待它完成。如果延时时间长,你可以设置SysTick只延时1毫秒,然后在循环中多次调用该延时函数。
注意事项:
- 使用该轮询方法实现
delay
将阻塞CPU执行直到延时完成; - 确保在使用前SysTick 定时器尚未被操作系统或其它库使用;
- 在多任务或中断驱动的环境中,使用SysTick的方式可能会影响系统中断的响应性能;
- 上述示例假设
SystemCoreClock
已定义并且与实际的系统核心时钟同步。在实际项目中SystemCoreClock
往往是由系统初始化代码更新的全局变量,它通常在启动文件进行赋值。 - 如果需要长时间延时,确保重载值乘以延时毫秒数不会超过SysTick定时器的最大值。
对于具有实时操作系统(RTOS)的系统,最好利用操作系统提供的延时函数,因为这些函数更加精准且不会影响操作系统的性能。
相关文章:
STM32中的Systick的使用
SysTick,全称System Tick Timer,是Cortex-M microcontrollers内核中提供的一个简单而有效的系统定时器,设计用来给操作系统提供时间基准,或用于生成周期性的中断。STM32系列微控制器,作为基于ARM Cortex-M内核的设备&a…...
做一个桌面悬浮翻页时钟
毛玻璃效果翻页桌面悬浮时钟,TopMost(Topmost“True”),不在任务栏显示(ShowInTaskbar“False”),在托盘区显示图标,双击托盘区图标实现最小化和还原,右键托盘图标可选“…...

Transformers中加载预训练模型的过程剖析(一)
使用HuggingFace的Transformers库加载预训练模型来处理下游深度学习任务很是方便,然而加载预训练模型的方法多种多样且过程比较隐蔽,这在一定程度上会给人带来困惑。因此,本篇文章主要讲一下使用不同方法加载本地预训练模型的区别、加载预训练模型及其配置的过程,藉此做个记…...

数据可视化的艺术:使用Matplotlib和Seaborn揭示数据故事
引言 数据可视化是数据分析中的关键一环,它帮助我们理解数据模式、趋势和异常。在Python中,Matplotlib和Seaborn是两个流行的数据可视化库,它们提供了丰富的图表和图形选项,使数据的可视化变得简单而强大。 Matplotlibÿ…...

2024全新小狐狸AI免授权源码
源码安装说明: 下 载 地 址 : runruncode.com/php/19757.html 1. 在宝塔新建一个站点,选择 PHP 版本为 7.2、7.3 或 7.4。将压缩包上传到站点的根目录,并设置运行目录为 /public。 2. 导入数据库文件,该文件位于 …...

Python基础详解四
目录 一,Json解析 二,pyecharts模块 三,类和对象 四,类型注解 一,Json解析 字典转换为JSON: import jsondata [{"name":"袁震","age":20},{"name":"张三&…...
es6新语法和ajax和json
es6新语法 1.定义变量:let 2.定义常量:const <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"…...

Hadoop3:HDFS副本节点选择逻辑讲解
一、副本节点选择(机架感知) 说明 第一个副本,因为我们的client可能是web页,也可能是shell终端。 如果是web页,则随机选取一个节点,如果是shell终端,则选择当前shell终端所在的节点。 节点距离最…...
Java 高级面试问题及答案 更新(二)
Java 高级面试问题及答案 以下是几个常见的Java高级面试问题及其答案,这些问题覆盖了Java语言的核心概念和高级特性。 问题1: 什么是Java内存模型(JMM),它在并发编程中扮演着什么角色? 答案: Java内存模型(JMM)是一个抽象的概念…...
MacOS安装Go
下载 Go 安装包: 访问 Go 官方网站的下载页面,找到适合 macOS 系统的 Go 安装包,并下载 go1.20.2.darwin-amd64.pkg(假设你的 macOS 是 64 位系统)。 安装 Go: 打开下载的安装包 go1.20.2.darwin-amd64.pk…...

【微服务最全详解】
文章目录 微服务微服务的介绍微服务服务架构演变 微服务网关微服务的负载均衡微服务的容灾机制服务崩溃服务容灾机制微服务熔断机制微服务限流Sentinel怎么实现限流微服务限流算法1.令牌桶算法2.漏斗桶算法 服务监控日志收集 微服务 微服务的介绍 微服务是一种软件架构风格&a…...

如何在云电脑实现虚拟应用—数据分层(应用分层)技术简介
数据分层(应用分层)技术简介 近几年虚拟化市场实现了非常大的发展,桌面虚拟化在企业中应用越来越广泛,其拥有的如下优点得到大量企业的青睐: 数据安全不落地。在虚拟化环境下面数据保存在中心服务器上面,…...

【动态规划五】回文串问题
目录 leetcode题目 一、回文子串 二、最长回文子串 三、分割回文串 IV 四、分割回文串 II 五、最长回文子序列 六、让字符串成为回文串的最少插入次数 leetcode题目 一、回文子串 647. 回文子串 - 力扣(LeetCode)https://leetcode.cn/problems/…...

【C++杂货铺铺】AVL树
目录 🌈前言🌈 📁 概念 📁 节点的定义 📁 插入 📁 旋转 1 . 新节点插入较高左子树的左侧---左左:右单旋 2. 新节点插入较高右子树的右侧---右右:左单旋 3. 新节点插入较高左…...

【R语言】生存分析模型
生存分析模型是用于研究时间至某个事件发生的概率的统计模型。这个事件可以是死亡、疾病复发、治疗失败等。生存分析模型旨在解决在研究时间相关数据时的挑战,例如右侧截尾(右侧截尾表示未观察到的事件发生,例如研究结束时还未发生事件&#…...

「AIGC」Python实现tokens算法
本文主要介绍通过python实现tokens统计,避免重复调用openai等官方api,开源节流。 一、设计思路 初始化tokenizer使用tokenizer将文本转换为tokens计算token的数量二、业务场景 2.1 首次加载依赖 2.2 执行业务逻辑 三、核心代码 from transformers import AutoTokenizer imp…...
【Unity】编程感悟20240510
【背景】 这一点感悟是过去有所认识,但是最近写Unity项目,涉及UDP通信需要持续监听逻辑时更加感受深刻的。 选用合适的触发点,用明确的逻辑避免循环处理 尽量采用明确的触发点使逻辑清晰,规避一定时间刷新这类的逻辑。 比如UDP…...

C#【进阶】泛型
1、泛型 文章目录 1、泛型1、泛型是什么2、泛型分类3、泛型类和接口4、泛型方法5、泛型的作用思考 泛型方法判断类型 2、泛型约束1、什么是泛型2、各泛型约束3、约束的组合使用4、多个泛型有约束思考1 泛型实现单例模式思考2 ArrayList泛型实现增删查改 1、泛型是什么 泛型实现…...

50. UE5 RPG FGameplayEffectContext
接下来,我想实现处理完伤害时,将伤害的触发格挡或者触发暴击时的逻辑传递到数据集的PostGameplayEffectExecute里面,这样,在处理IncomingDamage时,我们可以通过释放触发格挡或者触发暴击在UI上面进行对应的效果表现。 …...
Golang 的 unmarshal 踩坑指南
文章目录 1. 写在最前面2. 字段区分出空字段还是未设置字段2.1 问题描述2.2 解决 3. 字段支持多种类型 & 按需做不同类型处理3.1 问题描述3.2 解决 4. 碎碎念5. 参考资料 1. 写在最前面 笔者最近在实现将内部通知系统的数据定义转化为产品定义的对外提供的数据结构。 举例…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...

YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...

【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...
Python Einops库:深度学习中的张量操作革命
Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...

阿里云Ubuntu 22.04 64位搭建Flask流程(亲测)
cd /home 进入home盘 安装虚拟环境: 1、安装virtualenv pip install virtualenv 2.创建新的虚拟环境: virtualenv myenv 3、激活虚拟环境(激活环境可以在当前环境下安装包) source myenv/bin/activate 此时,终端…...
面试高频问题
文章目录 🚀 消息队列核心技术揭秘:从入门到秒杀面试官1️⃣ Kafka为何能"吞云吐雾"?性能背后的秘密1.1 顺序写入与零拷贝:性能的双引擎1.2 分区并行:数据的"八车道高速公路"1.3 页缓存与批量处理…...

AD学习(3)
1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...