打印
[其他ST产品]

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

[复制链接]
746|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
l63t89|  楼主 | 2023-9-25 18:16 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
Systick(系统嘀嗒定时器)学习
一、Systick 介绍
Systick 是 STM32 的一个系统定时器,又名系统嘀嗒定时器,是一个 24 位的倒计数定时器,当计数到 0 时,将从 RELOAD 寄存器中自动重装载定时初值,开始新一轮计数。

Systick 的信号来源于系统时钟,不分频为 72MHz,8 分频为 9MHz,从下图的时钟树就可以看出来。



使用特权

评论回复
沙发
l63t89|  楼主 | 2023-9-25 18:17 | 只看该作者
有4个寄存器控制SysTick定时器,分别如下:

控制及状态寄存器(CTRL)

使用特权

评论回复
板凳
l63t89|  楼主 | 2023-9-25 18:17 | 只看该作者
重装载数值寄存器(LOAD)

使用特权

评论回复
地板
l63t89|  楼主 | 2023-9-25 18:17 | 只看该作者
当前数字寄存器(VAL)

使用特权

评论回复
5
l63t89|  楼主 | 2023-9-25 18:17 | 只看该作者
校准数值寄存器(CALIB)

使用特权

评论回复
6
l63t89|  楼主 | 2023-9-25 18:18 | 只看该作者
二、Systick 延迟思路解析及实现(库函数版)
在《STM32中文参考手册_V10》中的 9.1.1 小节上有着下面这样一句话:

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

使用特权

评论回复
7
l63t89|  楼主 | 2023-9-25 18:18 | 只看该作者
由此可见,对于时延的初始化,直接让 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

使用特权

评论回复
8
l63t89|  楼主 | 2023-9-25 18:21 | 只看该作者
代码:
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;                //将定时器归零
}

使用特权

评论回复
9
l63t89|  楼主 | 2023-9-25 18:22 | 只看该作者
学习分享,一起成长!以上为小编的个人学习总结分享,若存在不当之处,请批评指正!

使用特权

评论回复
10
周半梅| | 2024-2-21 07:03 | 只看该作者

每个电容与纹波电流源的引线阻抗一样

使用特权

评论回复
11
Pulitzer| | 2024-2-21 08:06 | 只看该作者

时间片轮的设计思想

使用特权

评论回复
12
童雨竹| | 2024-2-21 10:02 | 只看该作者

大大减小与其他引线之间的容性耦合

使用特权

评论回复
13
Wordsworth| | 2024-2-21 11:05 | 只看该作者

需要在做项目的过程中经历磨难

使用特权

评论回复
14
Clyde011| | 2024-2-21 12:08 | 只看该作者

硬件设计和软件设计本来就是鱼和熊掌的关系,两者不可兼得

使用特权

评论回复
15
公羊子丹| | 2024-2-21 13:01 | 只看该作者

与电感和续流二极管相连

使用特权

评论回复
16
万图| | 2024-2-21 14:04 | 只看该作者

结构化模块化的程序设计的思想,使最基本的要求

使用特权

评论回复
17
Uriah| | 2024-2-21 15:07 | 只看该作者

确定好硬件原理图,硬件布线,最后才是软件的开发

使用特权

评论回复
18
帛灿灿| | 2024-2-21 17:03 | 只看该作者

写程序不难,但是程序怎么样才能写的好,写的快,那是需要点经验积累的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

88

主题

776

帖子

1

粉丝