0

0

0

修罗

站点介绍

只有了解事实才能获得真正的自由

SysTick系统定时器

修罗 2025-10-14 38 0条评论 stm32

首页 / 正文

1. 系统定时器简介

​ 系统定时器(SysTick系统)是属于Cortex-M3 (CM3)内核,内嵌在NVIC中。

​ 系统定时器是一个24bit的向下递减的计数器, SYSCLK 每震荡一次计数器减 1,计数器每计数一次的时间为1 / SYSCLK,一般我们设置系统时钟SYSCLK(与AHB相同)等于72M。当重装载数值寄存器的值递减到0的时候,系统定时器就产生一次中断,以此循环往复。

​ SysTick定时器能产生中断,CM3为它专门开出一个异常类型,并且在向量表中有它的一席之地。它使操作系统和其它系统软件在CM3器件间的移植变得简单多了,因为在所有CM3产品间SysTick的处理方式都是相同的。

​ 系统定时器一般用于操作系统,用于产生时基,维持操作系统的心跳。SysTick定时器除了能服务于操作系统之外,还能用于其它目的:如作为一个闹铃,用于测量时间等。

2. 与SysTick相关的寄存器

2.1 CTRL

SysTick控制和状态寄存器

image-20251014194312678.png

说明: 关于CLKSOURCE位, 当0时,时钟频率是AHB/8, 当1时,时钟频率是AHB

2.2 LOAD

SysTick重装载寄存器

image-20251014194451270.png

2.3 VAL

SysTick当前数值寄存器。计数到了哪里可以读取该值;

image-20251014194611438.png

2.4 CALIB

SysTick 校准数值寄存器。很少用到

3. 定时器使用案例(寄存器)

我们希望每隔1s 执行一次代码,直接让1s产生一次中断,重装载值可能比较大,所以采用1ms产生一次中断,因此先算出1ms执行多少次:

  • 1/72000000秒执行一次,1/72us执行一次,1us执行72次,1ms执行72000次
void Driver_SysTick_Init(void)
{
    /* 1. 配置时钟源  1=AHB(72MHz) 0=AHB/8 */
    SysTick->CTRL |= SysTick_CTRL_CLKSOURCE;
    /* 2. 使能中断 */
    SysTick->CTRL |= SysTick_CTRL_TICKINT;
    /* 3. 定时器 1ms 产生一次中断 */
    SysTick->LOAD = 72000 - 1; // -1是因为寄存器减到0不会马上产生中断,要在下一个时钟周期,所以减一
    /* 4. 使能定时器 */
    SysTick->CTRL |= SysTick_CTRL_ENABLE;

}

// 每1ms产生一次中断
uint16_t count = 0;
void SysTick_Handler(void)
{
    count++;
    if (count == 1000)
    {
        count = 0;
        
        // 需要定时执行的代码
        
    }
}

为什么不用开启NVIC: 因为 SysTick 是 Cortex-M 内核的一部分,其中断通道在 NVIC 中是默认开启且不可屏蔽的,所以无需额外配置 NVIC.

4. HAL库实现

  1. 选择时基

image-20251014200931481.png

  1. 选择时钟源

image-20251014201025138.png

  1. 时钟配置

image-20251014201136303.png

  1. 生成代码使用
void HAL_IncTick(void)
{
    uwTick += uwTickFreq;
    if (uwTick % 1000 == 0)
    { 
        // 产生了1s的计时
        // 需要定时执行的代码
    }
}

5. 工具类

delay.h

#ifndef __delay_h
#define __delay_h
#include "stm32f10x.h"                  // Device header

void Delay_us(uint16_t us);
void Delay_ms(uint16_t ms);
void Delay_s(uint16_t s);

#endif

delay.c

#include "delay.h" // Device header

void Delay_us(uint16_t us)
{
    /* 设计定时器重装值 */
    SysTick->LOAD = 72 * us;
    /* 清除当前计数值 */
    SysTick->VAL = 0;
    /*设置内部时钟源(2位->1),不需要中断(1位->0),并启动定时器(0位->1)*/
    SysTick->CTRL = 0x5;
    /*等待计数到0, 如果计数到0则16位会置为1*/
    while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG));
    /* 关闭定时器 */
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE; 
}

void Delay_ms(uint16_t ms)
{
    while (ms--)
    {
        Delay_us(1000);
    }
}

void Delay_s(uint16_t s)
{
    while (s--)
    {
        Delay_ms(1000);
    }
}

评论(0)


最新评论

  • 1

    1

  • 1

    1

  • -1' OR 2+158-158-1=0+0+0+1 or 'TKCTZnRa'='

    1

  • 1

    1

  • 1

    1

  • 1

    1

  • 1

    1

  • @@5Qa2D

    1

  • 1

    1

  • 1

    1

日历

2025年11月

      1
2345678
9101112131415
16171819202122
23242526272829
30      

文章目录

推荐关键字: Linux webpack js 算法 MongoDB laravel JAVA jquery javase redis