本文主要是介绍零死角玩转stm32初级篇6-Systick(操作系统的心脏),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
本篇博文目录:
- 一.Systick相关基本概念
- 1.什么是Systick
- 2.配置Systick
- 二. SysTick 精确延时
- 三.源代码
一.Systick相关基本概念
1.什么是Systick
在STM32单片机中,Systick是一个系统定时器,也就是系统时钟的另一种计时方式。它可以让我们方便地进行时间延迟和定时操作。Systick定时器是一个24位的自由运行倒计时器,其自动重载值寄存器为0xFFFFFF,计数器到达该值后会自动重新加载。它可以通过编程配置定时器中断、延时等功能,常用于精确定时、周期定时等场合。此外,Systick还可以被用来作为操作系统的时基,如FreeRTOS。当然,作为内核定时器,它也可以用于其他的系统调度操作,比如软件看门狗等。 — 解释来源于ChartGPT
在《零死角玩转 STM32 》这本电子书上也有一些相关的概念:
- SysTick 定时器被捆绑在 NVIC 中,用于产生 SysTick 异常(异常号:15)。
- Cortex-M3 在内核部分包含了一个简单的定时器—— SysTick timer(简化移植)。
- 在 STM32 中 SysTick 以 HCLK(AHB 时钟)或 HCLK/8 作为运行时钟。
- SysTick 定时器除了能服务于操作系统之外,还能用于其它目的:如作为一个闹铃,用于测量时间等。
- SysTick 定时器采用计数方式, STK_VAL表示当前计数值寄存器;STK_LOAD表示重载寄存器,计数器开始后STK_VAL计数器的数字向下减1,直至为0,触发异常,在中断服务函数中处理定时任务;并且硬件会将STK_LOAD寄存器中保存的值重新加载到STK_VAL中,再次循环。
2.配置Systick
当然,要使 SysTick 进行定时工作必须要进行 SysTick 进行配置。它的控制配置很简单,只有三个控制位和一个标志位,都位于寄存器 STK_CTRL(SysTick control and status register ) 中,如下图所示。
- 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。
与 SysTick 控制相关的所有寄存器如下图所示,其中上面没有介绍的STK_CALIB 寄存器是用于校准的,不常用。
二. SysTick 精确延时
每1s亮一次LED。
- SysTick.h
#ifndef __SysTick_h
#define __SysTick_h
#include "stm32f10x.h"
void SysTick_Init(void);
void Delay_ms(u32);
#endif
- SysTick.c
#include "SysTick.h"
__IO u32 TimingDelay;// 初始化SysTick
void SysTick_Init(){// SystemCoreClock/1000 1ms中断一次// SystemCoreClock/100000 10us中断一次// SystemCoreClock/1000000 1us 中断一次if(SysTick_Config(SystemCoreClock/1000)){// 配置SysTick_Config用于配置SysTickwhile(1);// 如果配置不成功,就会进入死循环}// 关闭滴答定时器SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;}void Delay_ms(__IO u32 nTime){TimingDelay = nTime;// 初始化TimingDelay// 使能滴答定时器SysTick -> CTRL |= SysTick_CTRL_ENABLE_Msk;// 开启滴答计时while(TimingDelay !=0);// 判断TimingDelay是否为0}
- main.c
#include "stm32f10x.h"
#include "led.h"
#include "SysTick.h"int main(void){// 初始化LEDledInit();// 初始化定时器SysTick_Init();while(1){// 每1s亮一次LEDDelay_ms(1000);ledOnOrOff(LED_ON);Delay_ms(1000);ledOnOrOff(LED_OFF);}
}
- stm32f10x_it.c
本实验例子中,使用时钟源为 AHB 时钟,其频率被配置为 72MHz(SystemFrequency = 72000000)。当调用函数时,把 ticks 赋值为 ticks=SystemFrequency / 1000 =72000,表示72000个时钟周期中断一次;(1/f)是时钟周期的时间,此时(1/f =1/72 us ),所以根据公式T=ticks*(1/f)最终定时总时间 T=72000*(1/72),为 7200个时钟周期,正好是 1000us = 1ms。
- SystemFrequency 依据源码可得
SysTick 定时器的定时时间(配置为触发中断,即为 中断周期 ),由 ticks 参数决定,最大定时周期不能超过 2 24 个。以下是几种常用的中断周期配置,就是根据上面的公式计算出来的。(
注意时钟为AHB
)
在前面基础知识哪里说道 SysTick 的时钟是可以进行修改的,可以变成8分频,我们可以使用SysTick_CLKSourceConfig() 进行修改,也可以直接对 SysTick_Config() 函数的代码进行修改。
- SysTick_CLKSourceConfig()源码
- 进行8分频
- SysTick_Config()的源码
代码中使用到了宏 SysTick_LOAD_RELOAD_Msk ,与其它库函数类似,这个宏是用来指示寄存器的特定位置或进行位屏蔽用的。
- 寄存器位指示宏和位屏蔽宏 ( 野火给这两类宏取的两个名字而已,官网没有这个说法! )
其中的寄存器位指示宏 : SysTick_xxx_Pos ,宏展开后即为 xxx 在相应寄存器中的位置,如控制 SysTick 时钟源的 SysTick_CTRL_CLKSOURCE_Pos ,宏展开为 2 ,这个寄存器位正是在寄存器 STK_CTRL 中的 Bit2 。
而寄存器位屏蔽宏 : SysTick_xxx_Msk ,宏展开是 xxx 的位全部置 1 后,左移 SysTick_xxx_Pos 位。如控制 SysTick 时钟源的SysTick_CTRL_CLKSOURCE_Msk ,宏展开为 (1ul <<SysTick_CTRL_CLKSOURCE_Pos) ,把无符号长整型数值(ul) 1 左移 2 位,得到了一个只有 Bit2:CLKSOURCE 位被置 1,其它位为 0 的数值,这样的数值配合位操作 &(按位与)、| (按位或)可以很方便地修改寄存器的某些位。假如控制 CLKSOURCE 需要四个寄存器位(1111->8+4+2+1=f),这个宏就应该被改为(0xf ul <<SysTick_CTRL_CLKSOURCE_Pos) ,这样就会得到一个关于 CLKSOURCE 的四位被置 1 的值,这些宏的参数就是这样被确定的。
- 通过上面的解释在来看一下,下面通过修改SysTick_Config()源代码为AHB8分频的代码,就一目了然:
三.源代码
微信公众号,回复
滴答定时器源码
既可以获取本篇博文的源代码,如果有什么问题,后台留言我看见会第一时间回复你的喔。
这篇关于零死角玩转stm32初级篇6-Systick(操作系统的心脏)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!