前言

时间管理是嵌入式系统的关键,而STM32单片机的SysTick定时器就是实现这一功能的核心工具。本文将介绍SysTick定时器的基本原理、配置方法及实际应用案例。

SysTick定时器简介

SysTick定时器是STM32单片机内核自带的一个系统定时器,主要用于提供系统滴答时钟,为操作系统或任务调度提供时间基准。它是一个24位的倒计数定时器,具有简单易用,高精度,应用广泛特点。在实际应用中,SysTick定时器经常用于操作系统的时间管理,任务调度,时间测量的场景。

SysTick定时器基本结构

SysTick定时器是一个24位的倒计数定时器,这意味着它从一个设定的值开始倒数,直到数到0。

它的主要组成部分包括:

计数寄存器(SYSTICK_VAL):存储当前的计数值。

重装载寄存器(SYSTICK_RELOAD):存储每次计数的起始值。

 控制寄存器(SYSTICK_CTRL):控制定时器的启动、停止、中断等功能。

SysTick定时器配置步骤:

1,设置SysTick定时器的时钟来源

2,设置SysTick定时器的重装初始值

3,清除SysTick定时器当前计数器的值

4,使能SysTick定时器

SysTick定时器代码配置

1,初始化SysTick定时器,选择时钟来源

//全局变量,用于存储微秒和毫秒的倍频系数
u8 time_us;
u16 time_ms;

void SysTick_Init(u8 SYSCLK)
{
    // 配置SysTick定时器的时钟源为HCLK的8分频
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
    
    // 计算微秒的倍频系数
    time_us = SYSCLK / 8;
    
    // 计算毫秒的倍频系数
    time_ms = time_us * 1000;
}

时钟来源为CPU时钟,即HCLK,进行8分频是为了降低SysTick定时器溢出的频率,提高系统的实时性能。将72Mhz的系统时钟进行8分频成9Mhz,此时时钟频率就变成了9Mhz,再根据周期公式:时钟周期 = 1 / 时钟频率,所以9Mhz的时钟周期就约待等于1微秒(us),再根据毫秒与微秒的互换得出1ms = 1000 us;

2,微秒级延时函数

/**
 * 微秒级延时函数
 * @param us 延时的微秒数
 */
void delay_us(u32 us)
{
    u32 temp; // 定义一个临时变量,用于读取SysTick控制寄存器的当前值

    // 设置SysTick定时器的重装载值,即定时器计数到0后自动加载的值
    SysTick->LOAD = us * time_us;

    // 清除当前计数值,让定时器从0开始计数
    SysTick->VAL = 0;

    // 启动SysTick定时器
    // SysTick_CTRL_ENABLE_Msk用于使能SysTick定时器
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;

    // 等待SysTick定时器计数到0并发生溢出
    // 这个循环会一直执行,直到SysTick定时器溢出(COUNTFLAG位被置位)
    // 同时确保SysTick定时器是使能状态(ENABLE位为1)
    do
    {
        temp = SysTick->CTRL; // 读取SysTick控制寄存器的当前值
    } while ((temp & 0x01) && !(temp & (1 << 16))); // 检查ENABLE位和COUNTFLAG位

    // 停止SysTick定时器
    // 清除SysTick控制寄存器中的使能位,停止定时器
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;

    // 清除当前计数值,为下一次使用做准备
    SysTick->VAL = 0;
}

首先来讲一下

SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;

SysTick->CTRL是读取 控制寄存器(SYSTICK_CTRL)的值,然后和SysTick_CTRL_ENABLE_Msk(它的值是0x01)进行按位或运算,将运算的结果写回控制寄存器(SYSTICK_CTRL)中,此时控制寄存器(SYSTICK_CTRL)的值为0x01,这样定时器就被成功启动了。

再来讲一下

    do
    {
        temp = SysTick->CTRL; // 读取SysTick控制寄存器的当前值
    } while ((temp & 0x01) && !(temp & (1 << 16))); 

temp = SysTick->CTRL;是访问控制寄存器(SYSTICK_CTRL)的值,并将访问的值赋给temp,(temp & 0x01)是将temp的值与0x01进行与运算,运算结果用来检查SysTick定时器是否还在运行。在!(temp & (1 << 16))中,(1 << 16)表示把1向左移16位,然后与temp的第16位进行与运算,最后将该运算结果取反,用来检查SysTick定时器标志位是否为0,标志位为0就继续运行。总结一下,

1. 读取控制寄存器:

 temp = SysTick->CTRL; 读取SysTick控制寄存器的当前值,并将其存储在临时变量 temp 中。

2. 检查定时器状态: while ((temp & 0x01) && !(temp & (1 << 16))); :在 while 循环中,检查两个条件:(temp & 0x01) :检查使能位(位0)是否为1,即SysTick定时器是否正在运行。  !(temp & (1 << 16)) :检查SysTick定时器标志位(位16)是否为0,即SysTick定时器是否尚未溢出。

最后来讲一下

 SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;

首先对SysTick_CTRL_ENABLE_Msk(0x01)按位取反,变成0xfe,再与 SysTick->CTRL ,也就是控制寄存器(SYSTICK_CTRL)当前的值进行与运算,并将结果返回控制寄存器(SYSTICK_CTRL),很显然,这时候的控制寄存器(SYSTICK_CTRL)的第0位,也就是使能位为0,即清除使能位,停止定时器。总结一下

3. 清除使能位:由于  ~SysTick_CTRL_ENABLE_Msk  的第0位是0,其他位都是1,按位与运算后, SysTick->CTRL  的第0位(ENABLE位)被清零,其他位保持不变。

4. 停止定时器:使能位被清零后,SysTick定时器停止计数。

3,毫秒级延时函数

/**
 * 毫秒级延时函数
 * @param ms 延时的毫秒数
 */
void delay_ms(u32 ms)
{
    u32 temp; // 定义一个临时变量,用于读取SysTick控制寄存器的当前值

    // 设置SysTick定时器的重装载值,即定时器计数到0后自动加载的值
    SysTick->LOAD = ms * time_ms;

    // 清除当前计数值,让定时器从0开始计数
    SysTick->VAL = 0;

    // 启动SysTick定时器
    // SysTick_CTRL_ENABLE_Msk用于使能SysTick定时器
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;

    // 等待SysTick定时器计数到0并发生溢出
    // 这个循环会一直执行,直到SysTick定时器溢出(COUNTFLAG位被置位)
    // 同时确保SysTick定时器是使能状态(ENABLE位为1)
    do
    {
        temp = SysTick->CTRL; // 读取SysTick控制寄存器的当前值
    } while ((temp & 0x01) && !(temp & (1 << 16))); // 检查ENABLE位和COUNTFLAG位

    // 停止SysTick定时器
    // 清除SysTick控制寄存器中的使能位,停止定时器
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;

    // 清除当前计数值,为下一次使用做准备
    SysTick->VAL = 0;
}

总结

SysTick定时器是STM32单片机中不可或缺的一部分,它使得时间控制变得更加容易和可靠。掌握SysTick定时器的使用,将大大提高你在嵌入式系统开发中的效率和项目的可靠性。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐