STM32中的Systick的使用

devtools/2024/10/18 16:46:19/

SysTick,全称System Tick Timer,是Cortex-M microcontrollers内核中提供的一个简单而有效的系统定时器,设计用来给操作系统提供时间基准,或用于生成周期性的中断。STM32系列微控制器,作为基于ARM Cortex-M内核的设备,也内置了这一功能模块。

主要特点

24位递减计数器:SysTick是一个24位自动重载的递减计数器,达到0时,计数器会自动重新装载预设的值,并且可以产生一个可选的中断

  1. 灵活的时钟源选择:SysTick定时器可以选择内核时钟(processor clock)或内核时钟的1/8作为其时钟源。这给了开发者根据实际需求选择时钟速度的灵活性。

  2. 简单易用:对于简单的延时生成、操作系统的节拍(timer tick) 或任何需要定时的任务,SysTick提供了一个简单而有效的解决方案,而不需要复杂的定时器配置。

  3. 固定的中断优先级:SysTick的中断优先级是在Cortex-M内核中固定的,这意味着开发者不能改变它。这为操作系统的设计提供了一定的便利,因为SysTick通常被用作系统的心跳或时间管理。

  4. 无需外部硬件:与其他外部或外围定时器不同,SysTick是内核内置功能,不需要其他外部硬件,可以保持系统的精简。

实现延时

开发者经常利用SysTick实现毫秒级的延时功能,这是通过配置SysTick的重载值(LOAD寄存器),并启用SysTick定时器和它的中断来实现的。每次SysTick定时器到达零,SysTick定时器会重新装载预设的值,并且可以触发中断(如果已经启用)。在中断服务程序(ISR)中可以执行相关的周期任务或标记一个周期的结束。

使用场景

  • 操作系统节拍:实时操作系统(RTOS)常用SysTick定时器作为系统的基础节拍源,用于任务调度、时间管理等。
  • 程序延时:在不需要精确时间管理的应用中,SysTick可以用来实现简易的延时功能,例如等待硬件准备好或实现非阻塞延迟。
  • 时间测量:SysTick也可以用于程序执行时间的测量,从而帮助开发者优化代码。

总之,SysTick是Cortex-M系列微控制器中非常实用的功能,对于需要精确时间管理或操作系统支持的应用来说尤其重要。

如何初始化systick定时器

为了初始化SysTick定时器,通常需要设置定时器的重载值,选择时钟源,并可选地使能SysTick中断。以下步骤展示了如何在裸机编程中初始化SysTick定时器,不依赖特定的硬件抽象层(HAL)或类似库

systick时钟源">步骤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变量表示系统的核心时钟频率,它需要根据实际的系统核心时钟进行设

systick定时器中断(可选)">步骤3: 使能SysTick定时器中断(可选)

使能SysTick定时器,选择是否使能中断。如果需要定时器到0时产生中断,还需要使能SysTick中断

SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; // 使能SysTick中断
SysTick->VAL = 0; // 清空计数器
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // 启动SysTick定时器

systick_handler中断服务例程(如果使能了中断)">步骤4: 实现SysTick_Handler中断服务例程(如果使能了中断

如果你使能了SysTick中断,你需要实现SysTick_Handler()中断服务例程(ISR)来处理中断。这个函数在SysTick计数到0时被调用。

void SysTick_Handler(void) {// 处理中断。例如,更新定时器标志,执行定时任务等。
}

以上就是初始化SysTick定时器的基本步骤。这个过程允许你根据需要配置SysTick定时器,来实现周期性的任务调度或生成准确的延时。

如何计算SysTick定时器的重载值?

计算SysTick定时器的重载值需要知道你想要定时器溢出的时间间隔以及定时器的时钟频率。以下是计算过程:

  1. 确定时钟频率

    • 主时钟频率 (SystemCoreClock): 如果你选择的是处理器的核心时钟(通常情况下)。
    • 分频后的时钟频率: 如果你选择的是分频后的时钟频率,例如核心时钟频率的1/8。
  2. 计算时间间隔对应的时钟周期数
    根据定时器的时间间隔以及定时器的时钟频率,计算出所需的时钟周期数。如果定时器的时间间隔是T秒,定时器的时钟频率是f_clock赫兹,则对应的时钟周期数N可用以下公式计算:

       N = T * f_clock

    例如,如果你需要1毫秒的时间间隔,并且SysTick的时钟频率是SystemCoreClock,则

       N = 0.001 * SystemCoreClock
  3. 计算重载值
    SysTick是一个24位的递减到零计数器,计数从重载值开始,并每个时钟周期递减一直到0。因此,重载值应是计数周期数减1。如果重载值设为R
       R = N - 1

    这是因为从R递减到0正好是R + 1个计数周期。

  4. 考虑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)的系统,最好利用操作系统提供的延时函数,因为这些函数更加精准且不会影响操作系统的性能。


http://www.ppmy.cn/devtools/38212.html

相关文章

Java | Leetcode Java题解之第66题加一

题目&#xff1a; 题解&#xff1a; class Solution {public int[] plusOne(int[] digits) {int n digits.length;for (int i n - 1; i > 0; --i) {if (digits[i] ! 9) {digits[i];for (int j i 1; j < n; j) {digits[j] 0;}return digits;}}// digits 中所有的元素…

Docker 中快速构建 Redis Cluster 集群

Docker 中快速构建 Redis Cluster 集群 目录 前言环境准备 所需软件配置网络 构建 Redis Cluster 镜像 创建自定义 Dockerfile构建镜像 启动 Redis 节点容器 启动命令 配置 Redis Cluster 集群 创建 Redis 集群验证集群状态 总结 前言 Redis 是一个高性能的键值对数据库&am…

顺序栈的操作

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd;既然选择了远方&#xff0c;当不负青春…

力扣数据库题库学习(5.4日)--1667. 修复表中的名字

1667. 修复表中的名字 问题链接 解题思路 使用 SUBSTRING() 函数获取每个名字的第一个字符和剩余字符。 使用 UPPER() 函数将第一个字符转换为大写。 使用 LOWER() 函数将剩余字符转换为小写。 使用 CONCAT() 函数将第一个字符和剩余字符组合成名字。 最后按照 user_id 对结…

【C++语言】继承

继承&#xff08;Inheritance&#xff09;是面向对象编程&#xff08;Object-Oriented Programming, OOP&#xff09;中的一个重要概念&#xff0c;它允许一个类&#xff08;称为子类或派生类&#xff09;基于另一个类&#xff08;称为父类或基类&#xff09;来构建。在C语言中…

WiFine通信与Wi-sun通信对比

调制速率 WiFine通信&#xff1a;(G)FSK 50Kbps~500Kbps &#xff1b;LoRa 5Kbps~37.5Kbps Wi-Sun通信&#xff1a;(G)FSK 50Kbps~300Kbps &#xff1b;QPSK/OFDM 计划中… 2、协议简介 WiFine通信&#xff1a;为低成本、低功耗、移动设备倾力打造 的轻量级、分布式无线移动…

使用Simulink Test进行单元测试

本文摘要&#xff1a;主要介绍如何利用Simulink Test工具箱&#xff0c;对模型进行单元测试。内容包括&#xff0c;如何创建Test Harness模型&#xff0c;如何自动生成excel格式的测试用例模板来创建测试用例&#xff0c;如何手动填写excel格式的测试用例模板来手动创建测试用例…

俄罗斯国际消费类电子电器展ICEE:人潮如织,盛况空前

近日&#xff0c;备受全球瞩目的俄罗斯国际消费类电子电器展ICEE在莫斯科盛大落幕。本次展会为期四天&#xff0c;真的攒足了眼球&#xff0c;不仅俄罗斯这边的很多媒体和自媒体有报道&#xff0c;展会第一天&#xff0c;很多参展商通过短视频平台将展会的盛况传到了国内&#…