STM32 的系统滴答定时器( Systick) 彻底研究解读
作者:王健
前言
SysTick 比起那些 TIM 定时器可以说简单多啦~~~~~哥的心情也好了不少, 嘎嘎!!
ARM Cortex-M3 内核的处理器内部包含了一个 SysTick 定时器,它是一个24 位的倒计数定时器,注意,是倒计数!
当计到 0 时它就会从 LOAD 寄存器中自动重装载定时初值。只要不把 CTRL 寄存器中的 ENABLE 为清 0,它就永不停息!
遗憾的是,SysTick 定时器在《STM32 参考手册》里一个屁都没放,只有在《ARM Cortex-M3 技术参考手册》和《ARM Cortex-M3 权威指南》才找到相关寄存器的介绍。
一、SysTick 的时钟来源
我们先来看看 STM32 的时钟树
The RCC feeds the Cortex System Timer (SysTick) external clock with the AHB clock(HCLK) divided by 8.
The SysTick can work either with this clock or with the Cortex clock(HCLK), configurable in the SysTick Control and Status Register.
上面这段话的意思是,SysTick的时钟来源可以是HCLK的8分频或就是HCLK,
具体是哪种可通过配置"控制和状态寄存器(CTRL)"来选择。
二、SysTick的寄存器简介
SysTick的寄存器一共有4个。
控制和状态寄存器CTRL(复位值0x00000000)
|
位段 |
名称 |
类型 |
描述 |
|
16 |
COUNTFLAG |
只读 |
计数到0时置1;读取该位将清0 |
|
2 |
CLKSOURCE |
可读可写 |
时钟来源 0=HCLK/8;1=HCLK |
|
1 |
TICKINT |
可读可写 |
1=计数到0时产生SysTick异常请求 |
|
0 |
ENABLE |
可读可写 |
使能位,即定时器的开关,1有效 |
重装值寄存器LOAD(复位值不可预测)
|
位段 |
名称 |
类型 |
描述 |
|
23:0 |
RELOAD |
可读可写 |
当计数到0时将被重装载的值 |

当前值寄存器VAL(复位值不可预测)
另外还有一个校准值寄存器CALIB,暂时用不到,先不刁它!
三、SysTick的库函数
1、寄存器定义在哪里?答:在core_cm3.h中!
typedef struct
{
__IO uint32_t CTRL;
__IO uint32_t LOAD;
__IO uint32_t VAL;
__I uint32_t CALIB;
} SysTick_Type;
…
#define SysTick ((SysTick_Type *) SysTick_BASE)
2、函数在哪里?
在V3.3的函数库中关于SysTick的函数只有两个。一个是在misc.C文件中的
SysTick_CLKSourceConfig函数,它是一个时钟源配置函数;另一个是在
core_cm3.h文件中的SysTick_Config函数,它的输入参数只有一个,传给了重装值寄存器LOAD,
另外还将VAL寄存器清0了,此外还将CTRL寄存器中的[2:0] 三位都设为了1,分别是使用HCLK时钟,允许异常请求,开启计数器。
在 misc.C 文件最后有下面一个函数
/**
- @功能: 配置 SysTick 时钟源
- @输入参数: SysTick_CLKSource: 指定SysTick 时钟源.
- 该参数可以是以下其中一个值:
- @ SysTick_CLKSource_HCLK_Div8: AHB 时钟 8 分频作为 SysTick 时钟源
- @ SysTick_CLKSource_HCLK: AHB 时钟作为 SysTick 时钟源.
*/
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
{
/* 参 数 检 查 */ assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource)); if (SysTick_CLKSource == SysTick_CLKSource_HCLK)
{
SysTick->CTRL |= SysTick_CLKSource_HCLK;
}
else
{
SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;
}
}
在 core_cm3.h 中有一个 SysTick_Config 函数
/* ############### SysTick 函数 ################### */
#if (!defined (__Vendor_SysTickConfig)) || (__Vendor_SysTickConfig == 0)
/**
- @功能 初始化并开启 SysTick计数器及其中断
- @输入参数 ticks 两次中断间的 ticks 数值
- @返回值 1 = 失败, 0 =成功
- 初始化系统滴答定时器及其中断并开启系统滴答定时器在自由运行模式下以产生周期中
断
*/
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* 重装值超过了 24 位,是不可
能的。返回失败值 0 */
SysTick->LOAD = ; /* 设置重装载寄存器 */
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* 设置优先级 for Cortex-M0 系统中断 */
SysTick->VAL = ; /* 装载计数器值(当前计数值清 0) */ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk| SysTick_CTRL_ENABLE_Msk; /*
使能 SysTick 中断请求和 Systick 定时*/
return (0); /* 成功,返回 0 */
}
#endif
3、编写一个精确延时函数!
鉴于SysTick的寄存器比较少,库函数也没写出啥玩意。所以完全有信心用寄存器的方法写出一个SysTick精确延时函数。偷学了网上的一点程序,写出了如下的函数,比网上的还精简了几行,哈哈!
/* 微秒级精确延时函数 */
void Delay_us(uint32_t n) ////////延时多少微秒,n 就输入多少!
{
SysTick->LOAD=*n; //装载计数值,因为时钟 72M,72 次在 1μs SysTick->CTRL=0x00000005;//时钟来源设为为 HCLK(72M),打开定时器while(!(SysTick->CTRL&0x00010000)); //等待计数到 0
SysTick->CTRL=0x00000004;//关闭定时器
}
编写一个点亮LED的函数测试一下。
int main(void)
{
GPIO_Configuration(); while(1)
{
GPIO_SetBits(GPIOD, GPIO_Pin_3); //输出高电平
Delay_us(10); //精确延时 10μs
GPIO_ResetBits(GPIOD, GPIO_Pin_3); //输出低电平
Delay_us(10); //精确延时 10μs
}
}
经示波器测试,发现确实很准,嘎嘎~~~△X=10.5μs,那0.5μs的误差来自哪里呢?因为要调用GPIO和Delay_us函数,包括Dealy_us函数中的几条设置语句,所以说还是相当准的!嘎嘎 ~~~~~~~~~~

STM32 的系统滴答定时器( Systick) 彻底研究解读的更多相关文章
- STM32之系统滴答定时器
一.SysTick(系统滴答定时器)概述 操作系统需要一个滴答定时器周期性产生中断,以产生系统运行的节拍.在中断服务程序里,基于优先级调度的操作系统会根据进程优先级切换任务,基于时间片轮转系统会根据时 ...
- 系统滴答定时器(SysTick)中断配置
系统滴答定时器(SysTick)中断配置 在STM32标准库中是通过SysTick_Config()函数配置时钟中断的,然后SysTick_Handler()函数自动定时触发其中的函数. if(Sys ...
- Cortex-M0系统滴答定时器Systick详解
上图是LPC1114系统滴答定时器(SysTick)的结构图.系统滴答定时器位于Cortex-M0内核中,也就是说,不论是LPC1114,还是其他的Cortex-M0内核单片机,都有这个系统定时器.其 ...
- STM32 - SYSTICK(系统滴答定时器)
SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15).在以前,大多操作系统需要一个硬件定时器来产生操作系统需要的滴答中断,作为整个系统的时基.例如,为多个任务许以不同数目 ...
- 利用滴答定时器(SysTick)实现简单的延时函数
预备知识: 对标准库来说,如果定义了时钟频率,则系统会默认初始化该时钟频率. SysTick是CM4的内核外设,是一个24位的向下递减计数器,每次计数时间是1/SYSCLK,即1/168000000. ...
- liunx驱动----系统滴答时钟的使用
2019-3-12系统滴答定时器中断使用 定义一个timer 其实就是使用系统的滴答定时器产生一个中断. 初始化timer init_timer函数 实现如下 void fastcall ini ...
- STM32 系统滴答计时器
;//us与系统滴答的被乘数 ;//ms与系统滴答的被乘数 ;//系统运行秒数 /** * @description:系统滴答计时系统初始化 * @param 无 * @retval 无 */ voi ...
- uCOS的软件定时器、uCOS时钟节拍和滴答定时器的关系
uCOS2.81后的版本中有软件定时器的概念,如果要开启定时器任务,需要在OS_CFG.H文件中 #define OS_TMR_EN 1 软件定时器其实跟硬件中断是相 ...
- HAL库与Cubemx系列|Systick-系统滴答定时器详解
Systick是什么? 关于Systick,在Context-M3权威指南中如此描述: SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号: 15).在以前,大多操作系统需要一 ...
随机推荐
- 解密国内BAT等大厂前端技术体系-美团点评之上篇(长文建议收藏)
引言 进入2019年,大前端技术生态似乎进入到了一个相对稳定的环境,React在2013年发布至今已经6年时间了,Vue 1.0在2015年发布,至今也有4年时间了. 整个业界在前端框架不断迭代中,也 ...
- 豆瓣工程师为你解答关于 Python3 编程方面的问题
Python是如此活跃的一种语言,几乎伴随互联网的发生而创立,又伴随互联网的极速发展而繁荣.使用Python会遇到这样的问题:什么时候该用多进程?怎样提高代码执行效率?Flask为什么流行?学习Pyt ...
- ACL与OSPF综合实验
OSPF与ACL 综合实验 拓扑图如下: 分析: 配置基本配置: R1: R2: R3: 2.配置OSPF: R1: R2: R3: IT: 设置IT的ip 并划分到ospf2区域 3.配置ACL ...
- RTT学习之启动流程
总结RT-Thread的启动流程. 非运行时与运行时的image文件分别是什么样的,请画下来.是谁将 RW 段中的 RW-data(初始化的全局变量)搬运到 RAM 中? MDK环境下各种数据段存储 ...
- jquery Ajax标准规范写法
$.ajax({ url:"http://www.xxx",//请求的url地址 dataType:"json",//返回的格式为json async:true ...
- 使用MQTTBox连接阿里云平台
这篇只做一个简单的介绍,和上一篇没有根本的区别.只是就两个客户端的差异介绍一下. 一.需要参考的内容: 使用MQTT.fx连接阿里云平台: https://www.cnblogs.com/mhtc/p ...
- js中ES6的Set的基本用法
ES6 提供了新的数据结构 Set.它类似于数组,但是成员的值都是唯一的,没有重复的值. const s = new Set(); [2,3,5,4,5,2,2].forEach(x => s. ...
- 使用SQL计算宝宝每次吃奶的时间间隔(数据保障篇)
目前程序从功能上其实已经完全满足客户(当然我这里的客户都是指媳妇儿^_^)需求,具体可参考: 使用SQL计算宝宝每次吃奶的时间间隔 使用SQL计算宝宝每次吃奶的时间间隔(续) 那么本篇 使用SQL计算 ...
- 使用python实现归并排序、快速排序、堆排序
归并排序 使用分治法:分而治之 分: 递归地拆分数组,直到它被分成两对单个元素数组为止. 然后,将这些单个元素中的每一个与它的对合并,然后将这些对与它们的对等合并,直到整个列表按照排序顺序合并为止. ...
- Java入门笔记 03-面向对象(中)
介绍:这部分内容主要是介绍和总结封装.继承和多态. 一. 封装:把该隐藏的隐藏起来,把该暴露的暴露出来 封装是指将信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类所提供的方法来实现 ...