STM32入门:Systick(嘀嗒定时器)学习

Systick(系统嘀嗒定时器)学习

这里特别声明一下,本文仅适用于 STM32F103 系列主频运行在 72MHz 下的 MCU 芯片,其他系列及主频的 MCU 芯片可做参考。
更新时间:2024-06-26

一、Systick 介绍

Systick 是 STM32 的一个系统定时器,又名系统嘀嗒定时器,是一个 24 位的倒计数定时器,当计数到 0 时,将从 RELOAD 寄存器中自动重装载定时初值,开始新一轮计数。

Systick 的信号来源于系统时钟,不分频为 72MHz,8 分频为 9MHz,从下图的时钟树就可以看出来。
时钟树
有4个寄存器控制SysTick定时器,分别如下:

  1. 控制及状态寄存器(CTRL)
    在这里插入图片描述
  2. 重装载数值寄存器(LOAD)
    在这里插入图片描述
  3. 当前数字寄存器(VAL)
    在这里插入图片描述
  4. 校准数值寄存器(CALIB)
    在这里插入图片描述

二、Systick 延迟思路解析及实现(库函数版)

在《STM32中文参考手册_V10》中的 9.1.1 小节上有着下面这样一句话:

系统嘀嗒校准值固定为 9000,当系统嘀嗒时钟设定为 9MHz ( HCLK/8 的最大值),产生 1ms 时间基准。

由此可见,对于时延的初始化,直接让 Systick 使用系统时钟的 8 分频,使其达到 9MHz 的频率,产生 1ms 1s 时间基准。

在这里更正一下之前的理解,对于频率与时间之间的转换公式为 f = 1 / T,STM32F103芯片的系统频率为72MHz,即 1 / 72000000 秒产生一个周期的振动,1 / 72000000 秒即 1 / 72 微秒,应该是为了时间更精确些,所以 SysTick 模块对时钟进行了 8 分频操作(为什么采用 8 分频操作,我也没搞明白,这里只是一个猜测),8分频操作后的时钟只有9M了,此时的 SysTick 模块每隔 1 / 9000000 秒即 1 / 9 微秒记一次数,需要计 9 次数,才能产生 1 us 的时钟,所以下方的 fac_us 的值为 72000000 / 8000000 = 9,这里的计算大致是这样的,很简单,不过我也是最近才搞明白,这里重新说明一下,感谢观看!
更新时间:2023-03-08

废话不多说,直接上代码:

static u32 fac_us;	//定义 1 个微秒的值
static u32 fac_ms;	//定义 1 个毫秒的值

/**
 * 初始化系统的嘀嗒定时器
 */
void delay_init(){
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);	//选择外部时钟,将 72MHz 的频率 8 分频,把系统嘀嗒定时器的变化定位在 1s
	fac_us = SystemCoreClock / 8000000;			//将 fac_us 设置为系统时钟的 1 / 8000000,SystemCoreClock = 72MHz,9MHz <=> 1s
	fac_ms = fac_us * 1000;						//将 fac_ms 设置为 fac_us 的 1000 倍
}
/**
 * 微秒延迟计数
 * temp & 0x01 && !(temp & (1 << 16)) 详解:
 * temp & 0x01 通过定时器状态值的最小位(1位)判断定时器是否处于使能状态
 * !(temp & (1 << 16)) 通过定时器状态值的最大位(16位)判断定时器是否处于归零状态
 */
void delay_us(u32 nus){
	u32 temp;
	SysTick -> LOAD = nus * fac_us;		//设置重装载值
	SysTick -> VAL |= 0x00;		//将定时器归零
	SysTick -> CTRL |= SysTick_CTRL_ENABLE_Msk;		//开启定时器
	//这里通过循环判断定时器的状态位值来确认定时器是否已归零
	do{
		temp = SysTick -> CTRL;	//获取定时器的状态值
	}while(temp & 0x01 && !(temp & (1 << 16)));
	SysTick -> CTRL &= ~SysTick_CTRL_ENABLE_Msk;	//关闭定时器
	SysTick -> VAL |= 0x00;		//将定时器归零
}
/**
 * 毫秒延时计数
 */
void delay_ms(u32 nms){
	u32 temp;
	SysTick -> LOAD = nms * fac_ms;		//设置重装载值
	SysTick -> VAL |= 0x00;		//将定时器归零
	SysTick -> CTRL |= SysTick_CTRL_ENABLE_Msk;		//开启定时器
	//这里通过循环判断定时器的状态位值来确认定时器是否已归零
	do{
		temp = SysTick -> CTRL;	//获取定时器的状态值
	}while(temp & 0x01 && !(temp & (1 << 16)));
	SysTick -> CTRL &= ~SysTick_CTRL_ENABLE_Msk;	//关闭定时器
	SysTick -> VAL |= 0x00;		//将定时器归零
}

学习分享,一起成长!以上为小编的个人学习总结分享,若存在不当之处,请批评指正!

  • 32
    点赞
  • 178
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 26
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是混子我怕谁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值