STM32之SysTick(系统定时器)

SysTick定时器是被捆绑在NVIC中的,用于产生SysTick异常(异常号是15)。(同样,玩过51单片机的都知道定时器的作用了)

在STM32在内核部分是包含了一个简单的定时器–SysTick timer。因为在所有的Cortex-M3芯片上都有这个定时器,所以软件在不同芯片生产厂商的Cortex-M3器件间的一只工作就得以化简。

该定时器的时钟源可以是内部时钟( FCLK, CM3 上的自由运行时钟),或者是外部时钟(CM3 处理器上的 STCLK 信号)。不过, STCLK 的具体来源则由芯片设计者决定,因此不同产品之间的时钟频率可

能会大不相同。因此,需要阅读芯片的使用手册来确定选择什么作为时钟源。

*(在 STM32 中 SysTick 以 HCLK(AHB 时钟)或 HCLK/8 作为运行时钟。)

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

SysTick timer工作分析:

SysTick 是一个 24 位的定时器,即一次最多可以计数 224 个时钟脉冲,这个脉冲计数值被保存到 当前计数值寄存器 STK_VAL (SysTick current valueregister) 中,只能向下计数,每接收到一个时钟脉冲 STK_VAL 的值就向下减1,直至 0,当 STK_VAL 的值被减至 0 时,由硬件自动把重载寄存器

STK_LOAD( SysTick reload value register) 中保存的数据加载到 STK_VAL,重新向下计数。当 STK_VAL 的值被计数至 0 时,触发异常,就可以在中断服务函数中处理定时事件了。

(要使 SysTick 进行工作必须要进行SysTick配置。它的控制配置很简单,只有三个控制位和一个标志位,都位于寄存器 STK_CTRL)

Bit0: ENABLE:

为 SysTick timer 的使能位,此位为 1 的时候使能 SysTick timer,此位为 0的时候关闭 SysTick timer。

Bit1: TICKINT:

为异常触发使能位,此位为 1 的时候并且 STK_VAL 计数至 0 时会触发SysTick 异常,此位被配置为 0 的时候不触发异常

Bit2: CLKSOURCE:

为 SysTick 的时钟选择位,此位为 1 的时候 SysTick 的时钟为 AHB 时钟,此位为 0 的时候 SysTick 时钟为 AHB/8( AHB 的八分频)。

Bit16: COUNTFLAG:

为计数为 0 标志位,若 STK_VAL 计数至 0,此标志位会被置 1。

(STK_CALIB 寄存器是用于校准的,不常用。可以在STM32数据手册中找到所有SysTick相关寄存器)

实例分析SysTick(延时流水灯)

主函数功能:

int main()

{

LED_GPIO_Config(); //LED GPIO初始化

SysTick_Init();    //配置SysTick

while(1)           //一个死循环的流水灯
{
    LED1(0);
    Delay_us(50000);
    LED1(1);

    LED2(0);
    Delay_us(50000);
    LED2(1);

    LED3(0);
    Delay_us(50000);
    LED3(1);
}

return 0;

}

SysTick_Init()分析

void SysTick_Init(void)

{

/* SystemFrequency / 1000 1ms 中断一次

SystemFrequency / 100000 10us 中断一次

SystemFrequency / 1000000 1us 中断一次 */

// if (SysTick_Config(SystemFrequency / 100000)) // ST3.0.0 库版本

if (SysTick_Config(SystemCoreClock / 100000)) // ST3.5.0 库版本

{

while (1);

}

SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;//关闭定时器

}

其实函数里面就调用了一个函数SysTick_Config(),这个函数是属于内核层的Cortex-M3的通用函数,位于Core_cm3.h中。函数工作很简单,就是若调用SysTick_Config()不成功,则进入死循环,当初始化SysTick成功后,先关闭定时器,需要用的时候再开启。(我们可以在keil环境下跟踪这个函数查看函数的定义)

/*

* @brief Initialize and start the SysTick counter and its interrupt.

*

* @param ticks number of ticks between two interrupts

* @return 1 = failed, 0 = successful

*

* Initialise the system tick timer and its interrupt and start the

* system tick timer / counter in free running mode to generate

* periodical interrupts.

*/

static __INLINE uint32_t SysTick_Config(uint32_t ticks)

{

/* Reload value impossible */

if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); //

/* set reload register */

SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;

/* set Priority for Cortex-M0 System Interrupts */

NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);

/* Load the SysTick Counter Value */

SysTick->VAL = 0;

SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |

SysTick_CTRL_TICKINT_Msk |

SysTick_CTRL_ENABLE_Msk; /* Enab

le SysTick IRQ and SysTick Timer */

return (0); /* Func

tion successful */

}

这个函数的主要功能:启动了SysTimer,并且把它配置为计数至0引起中断,输入的参数ticks为两次中断之间的脉冲数(既相隔ticks个时钟周期会引起一次中断),配置SysTick成功时返回0,出错返回1

以下为详细分析:

if (ticks > SysTick_LOAD_RELOAD_Msk) return (1);

因为ticks这个参数是脉冲计数值,要被保存到重载寄存器 STK_LOAD 寄存器中,再由硬件把STK_LOAD值加载到当前计数值寄存器STK_VAL使用的,因为STK_LOAD和STK_VAL都是24位,所以在输入ticks大于可存储的最大值时,由这行代码检查出错误返回。

SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1;

当ticks的值没有错误后,就把ticks-1赋值到STK_LOAD寄存器中(注意是减1),当STK_VAL从ticks-1向下计数到0,则就经过了ticks个脉冲。

(这里面用到的SysTick_LOAD_RELOAD_Msk宏(在keil环境下跟踪查看定义),这个宏是用来指示寄存器的“特定位置”或者是用来“位屏蔽”,所以叫位指示宏或位屏蔽宏,这个在操作寄存器代码中经常用到,通常都是用作控制寄存器某些位(“或”和“与”操作))

NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);

调用了NVIC_SetPriority()函数配置了SysTick中断,所以我们就不需要再去手动配置。配置完后把STK_VAL寄存器重新赋值为0。

SysTick->CTRL配置

向STK_CTRL写入SysTick timer的控制参数,配置为时钟,使能为计数至0引起中断,使能SysTick,接着SysTick就开始运行,做脉冲计数。

(如果想使用AHB/8作为时钟,可以调用库函数SysTick_CLKSourceConfig()或者修改SysTick->CTRL的使能配置)

最后在调用完SysTick_Config()后,SysTick定时器被打开了,但是我们并不是需要这样,所以在调用完之后关闭定时器

// 使能定时器

SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;

// 关闭定时器

SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;

(这里又用到位屏蔽宏,可见用的是十分广泛)

定时时间的计算:

再调用完SysTick_Config()时,输入ticks为SystemCoreClock / 100000 SystemCoreClock 为定义了系统时钟(SYSCLK)频率的宏,即等于AHB的时钟频率,历程用到AHB都是72MHz,所以SystemCoreClock这个宏展开就是7200 0000.

根据前面对 SysTick_Config()函数的介绍,它的输入参数为SysTick将要计的脉冲数,经过 ticks 个脉冲(经过 ticks 个时钟周期)后将触发中断,触发中断后又重新开始计数。

由此我们可以算出定时的时间,下面为计算公式:

T=ticks*(1/f)

T 为要定时的总时间。

ticks 为 SysTick_Config()的输入参数。

1/ f 即为 SysTick timer 使用的时钟源的时钟周期,f为该时钟源的时钟频率,当时钟源确定后为常数。

例如本实例使用时钟源为 AHB 时钟,其频率被配置为 72MHz。调用函数时,把ticks赋值为 ticks=SystemFrequency / 10000 =720,表示720个时钟周期中断一次;( 1/f)是时钟周期的时间,此时(1/f =1/72us ),所以最终定时总时间 T=720*(1/72),为 720 个时钟周期,正好是 10us。

SysTick 定时器的定时时间(配置为触发中断,即为中断周期),由ticks参数决定,最大定时周期不能超过 224个。以下是几种常用的中断周期配置,就是根据上面的公式计算出来的。

SystemFrequency / 1000 1ms 中断一次
SystemFrequency / 100000 10us 中断一次
SystemFrequency / 1000000 1us 中断一次

中断服务函数:

在main中,我们让LED工作在无限循环中,在开关之间调用了Delay_us(),一旦调用了之后,SysTick就会被开启,按照设定好的定时周期递减计数,当SysTick的计数值减到0时,就进入到中断,中断执行完后又重新计数

void Delay_us(__IO u32 nTime)

{

TimingDelay = nTime;

SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; //使能定时器
while(TimingDelay != 0);

}

使能了SysTick之后,就使用 while(TimingDelay != 0)语句等待TimingDelay变量变为 0,这个变量是在中断服务函数中被修改的。

/*

* @brief This function handles SysTick Handler.

* @param None

* @retval : None

*/

void SysTick_Handler(void)

{

if (TimingDelay != 0x00)

{

TimingDelay–;

}

}

SysTick中断属于系统异常向量,在stm32f10x_it.c文件中已经默认有了它的中断服务函数SysTick_Handler(),但内容为空。所以我们要自己编写。

每次进入 SysTick 中断就把全局变量TimingDelay自减一次。用户函数 Delay_us ()在TimingDelay被减至等于 0 时,才退出延时循环,即我们对 TimingDelay 赋的值为要中断的次数。

所以总的延时时间 T延时= T 中断周期 * TimingDelay 。

ps:

定时器我们还可以用作计算程序执行时间:

当我们开启 SysTick 定时器后,定时器开始工作,我们可以定义一个变量a来对中断次数进行记录,在定时器进入中断时,这个变量就a++,当我们关闭定时器后,将变量的数值乘与定时器的中断周期 就等于测量时间。特别是涉及到算法的程序,这对于优化算法是有非常大的帮助。假如你的算法的是 us 级别的,那么 SysTick 就应该设定为us 级中断,如果是 ms 级别的,就将 SysTick 设定为 ms 级中断。

时间: 2024-10-28 11:27:36

STM32之SysTick(系统定时器)的相关文章

SysTick—系统定时器

本章参考资料<ARM Cortex?-M4F 技术参考手册> -4.5 章节 SysTick Timer(STK), 和4.48 章节 SHPRx,其中 STK 这个章节有 SysTick 的简介和寄存器的详细描述.因为SysTick 是属于 CM4 内核的外设,有关寄存器的定义和部分库函数都在 core_cm4.h 这个头文件中实现.所以学习 SysTick 的时候可以参考这两个资料,一个是文档,一个是源码. SysTick 简介SysTick-系统定时器是属于 CM4 内核中的一个外设,内

SysTick系统定时器(功能框图和优先级配置)

SysTick-系统定时器是属于 CM3 内核中的一个外设,内嵌在 NVIC 中.系统定时器是一个 24bit (2^24)的向下递减的计数器,计数器每计数一次的时间为 1/SYSCLK,一般我们设置系统时钟 SYSCLK 等于 72M.当重装载数值寄存器的值递减到 0 的时候,系统定时器就产生一次中断,以此循环往复. 因为 SysTick 是属于 CM3 内核的外设,所以所有基于 CM3 内核的单片机都具有这个系统定时器,使得软件在 CM3 单片机中可以很容易的移植.系统定时器一般用于操作系统

第18章 SysTick—系统定时器

本章参考资料<Cortex?-M7内核编程手册>-4.4 章节SysTick Timer(STK),和4.38章节SHPRx,其中STK这个章节有SysTick的简介和寄存器的详细描述.因为SysTick是属于CM7内核的外设,有关寄存器的定义和部分库函数都在core_cm7.h这个头文件中实现.所以学习SysTick的时候可以参考这两个资料,一个是文档,一个是源码. 18.1  SysTick简介 SysTick-系统定时器是属于CM7内核中的一个外设,内嵌在NVIC中.系统定时器是一个24

6.SysTick系统时钟滴答实验(stm32中断入门)

系统时钟滴答实验很不难,我就在面简单说下,但其中涉及到了STM32最复杂也是以后用途最广的外设-NVIC,如果说RCC是实时性所必须考虑的部分,那么NVIC就是stm32功能性实现的基础,NVIC的难度并不高,但是理解起来还是比较复杂的,我会在本文中从实际应用出发去说明,当然最好去仔细研读宋岩翻译的<Cortex-M3权威指南>第八章,注意这不是一本教你如何编写STM32代码的工具书,而是阐述Cortex-M3内核原理的参考书,十分值得阅读. SysTick系统时钟的核心有两个,外设初始化和S

《零死角玩转STM32》-18-SysTick系统滴答定时器

参考资料:<STM32F4XX内核参考手册>:4.4.8-SHPRX(System Handler Priority Register)与4.5- System Tick Timer. 1. 简介 SysTick是一个24Bit的系统定时器,属于CM4内核的外设,相关寄存器与部分库函数中core_cm4.h中定义.SysTick一般用于操作系统,用于产生时基,维持OS的心跳. 如下所示:当计数器被使能(STC_CTRL: Bit0-ENABLE)并且计数器到0时,STK_LOAD中的预设值会被

stm32之Systick(系统时钟)

Systick的两大作用: 1.可以产生精确延时: 2.可以提供给操作系统一个单独的心跳(时钟)节拍: 通常实现Delay(N)函数的方法为: for(i=0;i<x;i++) ; 对于STM32系统微处理器来说,执行一条指令只有几十ns(纳秒),进入for循环,要实现N毫秒的x值非常大:而由于系统频率的宽广,很难计算出延时N毫秒的精确值:针对STM32微处理器,需要重新设计一个新的方法去实现该功能,以实现在程序中使用Delay(N): cortex的内核中包含一个SysTick时钟,SysTi

STM32F103ZET6系统定时器SysTick

1.系统定时器SysTick的简介 系统定时器SysTick属于内核外设,内嵌在NVIC中.SysTick是一个24位的向下递减的计数器,计数器根据SysTick的时钟源计数,当SysTick的计数器计数到0的时候,SysTick就产生一次中断,并且SysTick的重装载寄存器会给计数器重新赋值,以此循环往复. SysTick一般用于带操作系统的应用,用来产生时基,维持操作系统的心跳. 2.SysTick的寄存器 SysTick有4个寄存器: 控制及状态寄存器CTRL: 重装载数值寄存器LOAD

使用系统定时器SysTick实现精确延时微秒和毫秒函数

SysTick定时器简介 SysTick定时器是存在于系统内核的一个滴答定时器,只要是ARM Cortex-M0/M3/M4/M7内核的MCU都包含这个定时器,它是一个24位的递减定时器,当计数到 0 时,将从RELOAD 寄存器中自动重装载定时初值,开始新一轮计数.使用内核的SysTick定时器来实现延时,可以不占用系统定时器,由于和MCU外设无关,所以代码的移植,在不同厂家的Cortex-M内核MCU之间,可以很方便的实现.而东芝的这款TT_M3HQ开发板使用的TMPM3HQFDFG芯片,正

stm32的systick原理与应用

/* SysTick滴答定时器 一.功能 SysTick定时器是一个简单的定时器,CM3\CM4内核芯片都具备此定时器.SysTick定时器常用来做延时,采用实时系统时则用来做系统时钟.无论用作延时还是用作系统心跳时钟,不需要太复杂的功能,SysTick即可胜任. 二.实现原理 SysTick定时器是一个24位的倒计数,当倒计数为0时,将从RELOAD寄存器中取值作为定时器的初始值,同时可以选择在这个时候产生中断(异常号:15). 例如从RELOAD的值为999,那么当倒计数为0时,就会从复位为