浅析STM32 Systick查询定时的处理过程

share
《STM32 Systick 简介》

STM32 Systick 是 STM32 微控制器中的一个重要组成部分,它在 Cortex-M 内核中占据着独特的地位,发挥着关键的作用。

从所属类别专业来看,STM32 Systick 属于嵌入式系统领域。在嵌入式系统开发中,准确的时间控制和定时功能是至关重要的。STM32 Systick 正是为了满足这一需求而设计的。

Systick,即系统定时器,是 Cortex-M 内核中的一个 24 位向下递减计数器。它存在于所有的 Cortex-M 处理器中,包括 STM32 所采用的 Cortex-M 内核。在 Cortex-M 内核中,Systick 具有重要的地位。它为操作系统和其他需要时间基准的系统软件提供了一个稳定的时间基准。

Systick 的主要作用之一是提供一个简单的时间基准,用于操作系统的时间片调度。在多任务操作系统中,需要一个精确的时间基准来确定各个任务的执行时间和切换时机。Systick 可以提供一个固定的时间间隔,操作系统可以根据这个时间间隔进行任务调度,确保各个任务能够公平地获得处理器时间。

此外,Systick 还可以用于产生定时中断。通过设置 Systick 的计数器初始值和中断使能位,可以让 Systick 在计数器递减到零时产生中断请求。这个中断可以用于各种定时任务,如周期性的数据采集、定时通信等。

Systick 的另一个重要作用是作为一个软件定时器。在某些应用中,需要在特定的时间间隔后执行某个操作。可以通过设置 Systick 的计数器初始值,并在中断服务程序中检查计数器的值来实现软件定时器的功能。

在 STM32 中,Systick 的时钟源可以是内部时钟(AHB 时钟/8)或者外部时钟源。通过配置相关的寄存器,可以选择合适的时钟源,并设置计数器的初始值和中断使能位。

总的来说,STM32 Systick 在 Cortex-M 内核中具有重要的地位和作用。它为嵌入式系统提供了一个稳定的时间基准,用于操作系统的时间片调度、产生定时中断和实现软件定时器等功能。在嵌入式系统开发中,合理地使用 Systick 可以提高系统的实时性和可靠性。

Systick 寄存器介绍

在 STM32 微控制器中,Systick 是一种内置的定时器,它基于 Cortex-M 内核的 Systick 模块。Systick 定时器提供了一个高精度的系统时钟,可以用于操作系统的时钟节拍、任务调度等应用场景。Systick 定时器主要通过四个寄存器实现其功能:CTRL、LOAD、VAL 和 CALIB。

1. CTRL 寄存器(控制寄存器)
CTRL 寄存器用于控制 Systick 定时器的运行状态和配置。它包含以下关键位:
- ENABLE:使能 Systick 定时器,设置为 1 时,定时器开始计数。
- TICKINT:设置为 1 时,定时器溢出时会触发一个中断。
- CLKSOURCE:选择时钟源,可以是内部时钟或外部时钟。
- COUNTFLAG:指示定时器是否已经溢出。

2. LOAD 寄存器(加载寄存器)
LOAD 寄存器用于设置定时器的重载值,即定时器计数到该值时会产生溢出。LOAD 寄存器的值决定了定时器的计数周期。例如,如果系统时钟频率为 1MHz,LOAD 寄存器设置为 1000,则定时器的计数周期为 1ms。

3. VAL 寄存器(当前值寄存器)
VAL 寄存器存储当前定时器的计数值。当定时器开始计数时,VAL 寄存器的值会不断递减,直到计数到 0。此时,如果 ENABLE 位被设置,则定时器会产生溢出,并根据 TICKINT 位的设置,可能触发一个中断。溢出后,VAL 寄存器的值会重新加载 LOAD 寄存器的值。

4. CALIB 寄存器(校准寄存器)
CALIB 寄存器用于校准 Systick 定时器的时钟频率。它包含两个关键位:
- TENMS:表示 CALIB 寄存器中的值是以 10ms 为单位的。
- SKEW:表示校准值有误差,可能需要调整。

CALIB 寄存器的值通常由微控制器制造商在生产过程中校准并设置。用户可以通过读取 CALIB 寄存器的值来获取定时器的时钟频率,进而计算定时器的计数周期。

总之,STM32 Systick 定时器通过 CTRL、LOAD、VAL 和 CALIB 四个寄存器实现其功能。CTRL 寄存器用于配置定时器的运行状态,LOAD 寄存器设置定时器的重载值,VAL 寄存器存储当前计数值,而 CALIB 寄存器用于校准定时器的时钟频率。通过合理配置这些寄存器,可以充分利用 Systick 定时器提供高精度的系统时钟,为操作系统的时钟节拍、任务调度等应用提供支持。

《Systick 的工作过程》

在STM32微控制器中,Systick(系统定时器)是一个重要的内核级定时器,它为系统提供了一个简单的定时器功能,使得开发人员能够在不需要外部定时器的情况下执行周期性的任务。Systick的工作过程涉及其如何定时产生中断请求以及与NVIC(Nested Vectored Interrupt Controller,嵌套向量中断控制器)的交互,从而允许软件开发者实现精确的时间控制和任务调度。

### Systick的工作机制

Systick的工作基于一个简单的计数器,该计数器是一个递减计数器,其值从SysTick->LOAD寄存器中预设的重装载值开始递减,直到0。当计数器值递减至0时,会发生两件事情:首先,如果使能了中断(SysTick->CTRL寄存器的INTEN位被设置),则会产生一个中断请求;其次,计数器会自动重新从LOAD寄存器的值重新加载,并继续递减,形成一个循环。

### Systick与NVIC的交互

Systick产生的中断请求被发送到NVIC,这是Cortex-M内核中负责中断管理的部分。NVIC负责确定中断的优先级、屏蔽和使能中断。当Systick产生中断时,NVIC根据当前的中断优先级和屏蔽状态,决定是否将中断请求传递给处理器核心。如果中断被允许,处理器将会暂停当前的执行流程,保存当前任务的状态,并跳转到相应的中断服务程序(ISR)执行。

### Systick的中断优先级

Systick可以配置不同的中断优先级,这意味着在多任务环境下,可以对中断进行优先级排序,确保关键任务能够及时响应。在SysTick->CTRL寄存器中,可以设置SysTick的优先级,其中SysTick->CTRL寄存器的PRIO字段允许开发者配置优先级。

### Systick的时钟源

Systick的时钟源可以是系统时钟(System Clock)或者一个专门的外部参考时钟(External Reference Clock)。在大多数情况下,Systick使用系统时钟作为时钟源,因此,Systick的时钟频率与系统时钟频率相同。开发者可以通过SysTick->CTRL寄存器的CLKSOURCE位选择时钟源。

### Systick的中断使能与屏蔽

Systick的中断可以通过SysTick->CTRL寄存器的INTEN位来使能或屏蔽。当INTEN位被设置为1时,Systick在计数到0时产生中断;如果INTEN位被清零,则Systick不会产生中断,即使计数到0也不会。

### Systick的计数模式

Systick支持两种计数模式:二进制递减计数和二进制回绕计数。在二进制递减计数模式下,计数器从预设值开始递减到0,然后停止,直到下一次手动启动。在二进制回绕计数模式下,计数器在递减到0之后会自动从SysTick->LOAD寄存器中重新加载预设值,并继续递减,形成一个循环。

### Systick的实用性

Systick的实用性在于其可以被用来实现操作系统的节拍定时器(tick timer),用于调度和时间管理。此外,Systick还可以用来生成精确的时间延迟,这对于需要定时执行任务的嵌入式应用来说非常重要。

### 结论

Systick作为STM32微控制器中的一个内核级定时器,其工作过程与NVIC紧密相连,共同为系统提供了精确的时间控制功能。通过配置SysTick寄存器,开发者可以灵活地使用Systick实现各种定时和中断功能,从而满足不同应用场景的需求。了解和掌握Systick的工作原理对于进行高效的嵌入式系统开发至关重要。

### Systick 的使用方法

Systick,或称为系统定时器,是 ARM Cortex-M 系列处理器的一个关键组件,它提供了一个简单的定时器功能,用于实现操作系统的节拍定时、时间测量、延时等功能。在 STM32 微控制器中,Systick 同样扮演着重要的角色,它可以帮助开发者实现精确的时间控制,从而在各种应用场景中发挥作用。本文将详细介绍 Systick 的初始化步骤以及计数器开始计数的过程。

#### Systick 初始化步骤

Systick 的初始化过程主要包括以下几个步骤:

1. **配置 Systick 控制及状态寄存器(CTRL)**:
- 设置时钟源:Systick 可以使用的时钟源包括 AHB 时钟(HCLK)的 1/8、HCLK 本身或外部时钟。通常,我们会选择 HCLK 作为 Systick 的时钟源。
- 使能 Systick 计数器:通过设置 CTRL 寄存器的位 0(ENABLE)来启动 Systick 计数器。
- 配置中断:如果需要使用 Systick 产生中断,需要设置 CTRL 寄存器的位 1(TICKINT)。
- 设置时钟分频:通过 CTRL 寄存器的位 2(CLKSOURCE)来选择时钟源。

2. **配置重装载值寄存器(LOAD)**:
- 设置重装载值:LOAD 寄存器用于设置 Systick 计数器的重装载值,即计数器溢出前的计数值。这个值决定了 Systick 定时器的时间间隔。

3. **配置当前值寄存器(VAL)**:
- 清零 VAL 寄存器:在开始计数前,通常需要将 VAL 寄存器清零,以确保从正确的值开始计数。

4. **配置校准值寄存器(CALIB)**:
- 设置校准值:CALIB 寄存器用于调整 Systick 定时器的精度。在一些情况下,由于时钟频率的微小偏差,可能需要微调 Systick 的定时精度。

5. **启动 Systick 计数器**:
- 在完成上述配置后,可以通过设置 CTRL 寄存器的 ENABLE 位来启动 Systick 计数器。

#### 计数器开始计数的过程

一旦 Systick 计数器被启动,它将按照以下过程工作:

- **计数开始**:计数器从 VAL 寄存器的值开始递减,每收到一个时钟脉冲,VAL 寄存器的值就减少 1。
- **重装载**:当 VAL 寄存器的值减到 0 时,计数器会触发一个中断(如果启用了中断),并且自动从 LOAD 寄存器中加载新的重装载值,继续计数。
- **溢出处理**:在计数过程中,如果设置了溢出中断,每当计数器溢出时,都会产生一个中断请求,这可以用于操作系统的心跳定时或其他定时任务。

#### 总结

Systick 是一个简单但强大的定时器,它为 STM32 微控制器提供了精确的时间控制能力。通过正确地初始化 Systick 并理解其计数过程,开发者可以在各种应用中实现高效的时间管理,无论是简单的延时功能还是复杂的实时操作系统节拍定时。掌握 Systick 的使用方法,对于任何希望深入利用 STM32 微控制器的开发者来说,都是一项宝贵的技能。

### Systick 查询定时的应用

在嵌入式系统开发中,定时任务的实现是不可或缺的一部分。STM32系列微控制器中的Systick定时器因其简单易用而被广泛应用于各种计时需求场景中。与基于中断的方法相比,查询方式虽然牺牲了一定程度上的实时性,但在某些特定情况下(如资源紧张或不需要高精度定时)却能提供更加灵活简便的解决方案。本节将以LED闪烁为例,深入探讨如何利用Systick进行查询式定时处理。

#### 一、准备工作

首先,我们需要准备一块支持Systick功能的STM32开发板,并连接一个LED到GPIO口上。假设我们已经完成了GPIO的相关配置工作,接下来将专注于Systick定时器的设置以及如何通过它来控制LED的亮灭状态变化。

#### 二、Systick初始化

在使用Systick之前,需要对其进行适当的初始化设置。这通常包括以下几个步骤:

1. **加载计数周期**:设定`SYSTICK_LOAD_REG`寄存器值以确定定时器溢出所需的时间长度。
2. **启用Systick定时器**:通过写入`SYSTICK_CTRL_REG`使能Systick,并选择是否开启中断模式。
3. **启动计数**:再次访问`SYSTICK_CTRL_REG`触发计数开始。

对于查询模式而言,最关键的是正确设置了Systick的计数值和不启用中断位。这样,在每次主循环执行时,程序可以检查当前Systick计数值是否达到预设阈值,从而决定下一步动作。

#### 三、实现LED闪烁功能

现在让我们来看一个具体的例子——利用Systick实现每秒一次的LED闪烁效果。为了简化说明,这里假定我们的系统时钟频率为72MHz,且已知Systick时钟源同样为72MHz。

- 首先计算出每秒钟对应的滴答数:\(72,000,000 / 1 = 72,000,000\) ticks
- 接着将此值写入`SYSTICK_LOAD_REG`作为重载值
- 设置`SYSTICK_CTRL_REG`为非中断模式并启动计时
- 在主循环里不断检查`SYSTICK_VAL_REG`是否归零,一旦发现则反转LED状态并重启计数器

```c
// 初始化Systick
uint32_t reload_value = 72000000 - 1; // 计算得到的一秒内滴答数减一
SysTick->LOAD = reload_value; // 设置重载值
SysTick->VAL = 0; // 清空当前值
SysTick->CTRL = SysTick_CTRL_ENABLE_Msk; // 启动Systick,不启用中断

while (1) {
if ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) != 0) { // 检查是否超时
HAL_GPIO_TogglePin(LED_PORT, LED_PIN); // 切换LED状态
SysTick->VAL = 0; // 重新开始计数
}
}
```

上述代码片段展示了如何通过简单的逻辑判断来实现周期性的任务调度。需要注意的是,由于采用的是轮询机制而非中断驱动,因此CPU会在等待期间持续运行该段代码直至满足条件为止。这意味着如果在此过程中没有其他更优先级的任务被执行,则可能会导致处理器利用率不高。

#### 四、总结

通过以上介绍我们可以看出,尽管基于Systick的查询定时方法相对简单直接,但它同样能够有效地满足许多基本的应用需求。特别是对于那些对响应时间要求不是特别严格或是希望尽量减少中断使用的场合来说,这种方法无疑提供了一个不错的替代方案。然而,在实际工程项目中选择何种定时策略还需根据具体需求权衡利弊后做出决策。
share