Hello,小伙伴们,大家好。这里是左左右。上回咱们说到,HAL_Delay那个延时函数。其实,就是靠芯片内部一个叫滴答定时器的(SysTick)来实现的。今天这期视频,咱们就把它彻底拆开。看看它到底是怎么工作的?顺便亲手写一个自己的延时函数。
首先,我们翻开Cortex-M3内核的编程手册第150页。从这里看出,SysTick本质上是一个 24位的向下计数器。说白了就是倒数,也就是倒计时。翻到第154页可以看到滴答定时器一共有四个核心寄存器。学寄存器我们抓住三个要点就行。分别是基地址,偏移量、和位含义。基地址和偏移量在手册中一眼就可以找到。
接着,我们往上翻来找一下每个寄存器的位含义。首先,来看这里的STK_CTRL寄存器。它的的全称是 SysTick Control and Status Register。通常译为SysTick 控制与状态寄存器。STK_CTRL寄存器别看它32位。只有4位起作用,第0位是计数的使能位,也就是CTRL这个寄存器的总开关,所以这一位是一定要置1的。

位 1 设置SysTick中断使能。置0代表禁用中断。置1代表当倒数到0时进入中断。位 2是时钟源选择。这个在上期视频是提到过的,置0,是系统时钟的8分频。置1代表时钟源直接就是系统主时钟,不分频。位16 COUNTFLAG:计数完成标志位,这是一个状态标志位。如果定时器已经完成了一轮计数,减到零了,这一位就会被硬件自动置1。
你可以通过读它来查询定时是否完成?接着,来看STK_LOAD这个寄存器。它是一个24位的值。RELOAD值可以是0x00000001至0x00FFFFFF范围内的任意值。这里放的就是要倒数到0的那个数STK_VAL全称SysTick Current Value Register。

中文译为SysTick 当前值寄存器。它实时记录被倒计时的当前值。STK_CALIB全称SysTick calibration value register。通常译为SysTick校准值寄存器。这里我们可以看到前面三个寄存器这里都是rw,也就是可读可写,而这个寄存器只有一个r,也就是这个寄存器是只读的,它是芯片出厂时就写好的,告诉你一些硬件特性。
比如,在标准参考时钟下,实现1毫秒定时需要多少计数值。位31称作无参考时钟标志位(NOREF),当读取到NOREF=0时,代表SysTick可以选择使用处理器时钟 (AHB) 也可以使用,外部参考时钟 (HCLK/8) ,而当读取到NOREF=1时,代表SysTick只能使用处理器时钟 (AHB),由于我们这里的时钟源是NOREF=0的这种情况,所以当我们读取这一位时肯定是0,位30被称作校准偏差标志位,它是用来指示TENMS值的精确度的,SKEW = 0时,TENMS值精确 ,SKEW = 1时TENMS值不精确。

stm32f103系列在出厂校准时,SysTick校准值是基于内部RC振荡器测量的,也就是HSI,HSI本身的精度并不高,所以这一位是1。位0:到位23存储的是1ms校准值,它这里显示的在外部参考时钟(HCLK/8)下,产生1ms定时所需的计数值,以HCLK最高72Mhz为例。
TENMS = (72,000,000 / 8) × 0.001。= 9,000,000 × 0.001。= 90,00。= 0x2328 (十六进制)。STK_CALIB这个寄存器使用频率并不高,所以我们只做了解就可以了,光说不练假把式。咱们来实战配置一下寄存器,让SysTick精确地每1毫秒完成一次倒数,这里我们默认HCLK位72M赫兹的最大频率,前面我们说过72兆赫兹相当于72分之一微秒就记一次数,那么1毫秒需要记72000个数,但是这里的零也算一个数,比如我们要记10个数,记0到9就可以了,所以这里的72000要减去一个1,这时的计数值就是1毫秒。

所以,重载值寄存器这里就存入71999这个数,CLKSOURCE这里我们选的是最快的72M赫兹,不需要分频,所以这里置1,TICKINT这里置0,先不触发中断,纯计时。ENABLE这里置1,倒计时开启,STK_VAL中的值从71,999开始递减,当倒数到0时,COUNTFLAG这是一个状态标志位就会自动置1,紧接着STK_LOAD中值会自动装进STK_VAL,COUNTFLAG这是一个状态标志位就会自动置1,这时就进入下一轮1毫秒的计时了,以此类推永不停息,接着我们使用寄存器在stm32cubeide中快速的来写一个毫秒级的延时函数,同时我们点击调试,可以打开寄存器,观察一下里面的值是不是和我们前面所讲一样?

Hello,小伙伴们,大家好。这里是左左右。回咱们说到,HAL_Delay这个延时函数。其实,就是靠芯片内部一个叫滴答定时器的来实现的。今天这期视频。咱们就把它彻底拆开。看看它到底是怎么工作的?顺便亲手写一个自己的延时函数。
首先,我们翻开 Cortex M3 内核的编程手册第150页。从这里看出,SysTick本质上是一个 24位的向下计数器。说白了就是倒数,也就是倒计时。翻到第154页可以看到滴答定时器一共有四个核心寄存器。学寄存器我们抓住三个要点就行。分别是基地址,偏移量、和位含义。基地址和偏移量在手册中一眼就可以找到。
接着,我们往上翻。来找一下每个寄存器的位含义。首先,来看这里的STK_CTRL寄存器。它的全称是 SysTick Control and Status Register。通常译为SysTick 控制与状态寄存器。STK_CTRL寄存器别看它32位。只有4位起作用。第0位是计数的使能位。
它是计数器的总开关。想让计数器工作。这一位必须置1。位1设置SysTick中断使能。置0代表禁用中断。置1代表当倒数到0时进入中断。位 2是时钟源选择。这个在上期视频是提到过的,置0,是HCLK的8分频。置1代表时钟源直接就是HCLK,不分频。位16 COUNTFLAG。
计数完成标志位。这是一个状态标志位。如果定时器已经完成了一轮计数,减到零了,这一位就会被硬件自动置1。你可以通过读它来查询定时是否完成?接着,来看 S T K L O A D这个寄存器。它的全称是 SysTick reload value register。通常译为SysTick 崇装载值寄存器。
它是一个24位的值。RELOAD值可以是0x00000001至0x00FFFFFF范围内的任意值。这里放的就是要倒数到0的那个数。STK_VAL全称 SysTick Current Value Register。中文译为SysTick 当前值寄存器。它实时记录被倒计时的当前值,STK_CALIB全称SysTick calibration value register。
通常译为SysTick校准值寄存器。这里我们可以看到前面三个寄存器这里都是r w,也就是可读可写,而这个寄存器只有一个r,也就是这个寄存器是只读的,它是芯片出厂时就写好的,告诉你一些硬件特性。比如,在标准参考时钟下,实现1毫秒定时需要多少计数值。位31称作无参考时钟标志位(N O R E F)。
当读取到N O R E F = 0 时,代表SysTick可以选择使用处理器时钟 (A H B) 也可以使用。外部参考时钟 (H C L K除以8),而当读取到N O R E F = 1 时。代表SysTick只能使用处理器时钟 (A H B)。由于我们这里的时钟源是N O R E F = 0 的这种情况,所以,当我们读取这一位时肯定是0。
位30被称作校准偏差标志位。它是用来指示TENMS值的精确度的,S K E W = 0时,T E N M S 值精确。S K E W = 1时T E N M S 值不精确。S t m 3 2 f 1 0 3 系列在出厂校准时。SysTick校准值是基于内部 R C 振荡器测量的,也就是H S I,H S I本身的精度并不高。
所以,位0到位23存储的是1毫秒校准值。它这里显示的是在外部参考时钟H C L K除以8下。产生1毫秒定时所需的计数值。以HCLK最高72兆赫兹为例。TENMS等于9000。STK_CALIB这个寄存器使用频率并不高。所以,我们只做了解就可以了。光说不练假把式。咱们来实战配置一下寄存器,让SysTick精确地每1毫秒完成一次倒数。
这里我们默认H C L K为72兆赫兹的最大频率。前面我们说过72兆赫兹相当于72分之一微秒就记一次数。那么1毫秒需要记72000个数。但是,这里的零也算一个数。比如,我们要记10个数,记0到9就可以了。所以,这里的72000要减去一个1。这时的计数值就是1毫秒。所以,重载值寄存器这里就存入71999这个数。
CLKSOURCE这里我们选的是最快的72兆赫兹。不需要分频,所以这里置1。TICKI NT这里置0,先不触发中断。纯计时,ENABLE这里置1,倒计时开启。STK_VAL中的值从71999开始递减。当倒数到0时,COUNTFLAG这一状态标志位就会自动置1。紧接着STKLOAD中值会自动装进STKVAL。
COUNTFLAG这一状态标志位就会自动置0。这时就进入下一轮1毫秒的计时了。以此类推永不停息。接着,我们使用寄存器在 s t m32 cubeide中快速的来写一个毫秒级的延时函数。
同时,我们点击调试。可以打开寄存器。观察一下里面的值是不是和我们前面所讲一样?好的,今天的视频就到这里了。下期视频我们来看一下HAL_Delay这个函数是如何实现延时的?您的关注、点赞和收藏是我持续更新下去的最大动力。我们下期见。