SysTick—系统定时器是属于 STM32 内核中的一个外设,内嵌在 NVIC 中。该定时器的时钟源可以是内部时钟,也可以是外部时钟。系统定时器是一个 24bit 的向下递减的计数器,SysTick设定初值并使能后,计数器每计数一次的时间为 1/SYSCLK, 即每经过 1 个时钟周期,计数值就减 1,一般我们设置系统时钟 SYSCLK 等于 48MHz。计数到 0 时,SysTick 计数器自动重装初值并继续计数,同时内部的 COUNTFLAG 标志会置位,触发中断(如果中断使能情况下),以此循环往复。 因为 SysTick 是属于 STM32 内核的外设,所有的STM32芯片都带有这个定时器,软件在不同STM32器件间很容易移植。SysTick定时器一般用来做延时,或者实时系统的心跳时钟。这样可以节省MCU资源,不用浪费一个定时器。比如UCOS中,分时复用,需要一个最小的时间戳,一般在STM32 + UCOS系统中,都采用SysTick做UCOS心跳时钟。
SysTick—系统定时器有4个寄存器,简要介绍如下。在使用 SysTick 产生定时的时候,只需要配置前三个寄存器,最后一个校准寄存器不需要使用。
寄存器名称寄存器描述SYS_CTRLSystick 控制及状态寄存器SYS_LOADSystick 重装在数值寄存器SYS_VALSystick 当前数值寄存器SYS_CALIBSystick 校准数值寄存器SYS_CTRL 控制寄存器 第0位:ENABLE,SysTick 使能位 (0:关闭SysTick功能;1:开启SysTick功能) 第1位:TICKINT,SysTick 中断使能位(0:关闭SysTick中断;1:开启SysTick中断) 第2位:CLKSOURCE,SysTick时钟源选择(0:AHB/8;1:AHB时钟) 第16位:COUNTFLAG,SysTick计数比较标志,如果在上次读取本寄存器后,SysTick已经计数到了0,则该位为1。如果读取该位,该位将自动清零。
STK_LOAD 重载寄存器 SysTick是一个递减的定时器,当定时器递减至0时,重载寄存器中的值就会被重装载,继续开始递减。STK_LOAD 重载寄存器是个24位的寄存器,最大计数值为 0xFFFFFF。
STK_VAL 当前值寄存器 也是个24位的寄存器,读取时返回当前倒计数的值,写它则使之清零,同时还会清除在 SysTick 控制及状态寄存器中的 COUNTFLAG 标志。
使用SysTick定时器做精确延时,通过调整延时时间来调节 LED1 闪烁时间。LED的相关定义和代码请参考上一篇文章,此处不在列出。
步骤: 1、配置RCC时钟 2、配置SysTick 至此,要点配置以完成,至于LED1引脚的相关配置及项目生成的配置本篇不在叙述,请参考上一篇文章。无论是查询方式还是中断方式,CubeMX的配置是一样的,下面针对查询方式和中断方式在代码上的区别进行说明。
3、编写相关代码
说明:因为有CubeMX生成的项目中默认有一个HAL库的延时函数 HAL_Delay(),此函数是毫秒级延时函数,HAL_Delay(500);就代表延时500ms,而且是基于SysTick中断的方式实现的,所以直接使用就行,不需要再进行额外的配置。
/*----------------------------------------- led.h -----------------------------------------*/ /** ********************************* STM32F0xx ******************************** * @文件名 : led.h * @作者 : JayYang * @库版本 : V1.5.0 * @文件版本 : V1.0.0 * @日期 : 2020年06月24日 * @摘要 : LED驱动头文件 ******************************************************************************/ /* 定义防止递归包含 ----------------------------------------------------------*/ #ifndef _LED_H #define _LED_H /* 包含的头文件 --------------------------------------------------------------*/ #include "main.h" #include "stm32f0xx_hal.h" /* 宏定义 --------------------------------------------------------------------*/ #define LED_1_ON HAL_GPIO_WritePin(LED_1_GPIO_Port, LED_1_Pin, GPIO_PIN_RESET) //点亮LED1 #define LED_1_OFF HAL_GPIO_WritePin(LED_1_GPIO_Port, LED_1_Pin, GPIO_PIN_SET) //熄灭LED1 #define LED_1_TOGGLE HAL_GPIO_TogglePin(LED_1_GPIO_Port,LED_1_Pin) //LED1取反 #endif /**** Copyright (C)2020 JayYang. All Rights Reserved **** END OF FILE ****/ /*----------------------------------------- led.c -----------------------------------------*/ /** ******************************** STM32F0xx ********************************* * @文件名 : led.c * @作者 : JayYang * @库版本 : V1.5.0 * @文件版本 : V1.0.0 * @日期 : 2020年06月24日 * @摘要 : LED驱动源文件 ******************************************************************************/ /*---------------------------------------------------------------------------- 更新日志: 2020-06-24 V1.0.0:初始版本 ----------------------------------------------------------------------------*/ /* 包含的头文件 --------------------------------------------------------------*/ #include "bsp.h" /**** Copyright (C)2020 JayYang. All Rights Reserved **** END OF FILE ****/ /*----------------------------------------- bsp.h -----------------------------------------*/ /** ********************************* STM32F0xx ******************************** * @文件名 : bsp.h * @作者 : JayYang * @库版本 : V1.5.0 * @文件版本 : V1.0.0 * @日期 : 2020年06月24日 * @摘要 : BSP板级支持包头文件 ******************************************************************************/ /* 定义防止递归包含 ----------------------------------------------------------*/ #ifndef _BSP_H #define _BSP_H /* 包含的头文件 --------------------------------------------------------------*/ #include "main.h" #include "stm32f0xx_hal.h" #include "gpio.h" #include "led.h" #include "systick.h" /* 函数声明 --------------------------------------------------------------*/ void BSP_Initializes(void); //底层初始化 #endif /**** Copyright (C)2020 JayYang. All Rights Reserved **** END OF FILE ****/ /*----------------------------------------- bsp.c -----------------------------------------*/ /** ******************************** STM32F0xx ********************************* * @文件名 : bsp.c * @作者 : JayYang * @库版本 : V1.5.0 * @文件版本 : V1.0.0 * @日期 : 2020年06月24日 * @摘要 : BSP板级支持包源文件 ******************************************************************************/ /*---------------------------------------------------------------------------- 更新日志: 2020-06-24 V1.0.0:初始版本 ----------------------------------------------------------------------------*/ /* 包含的头文件 --------------------------------------------------------------*/ #include "bsp.h" /************************************************ 函数名称 : BSP_Initializes 功 能 : 底层初始化 参 数 : 无 返 回 值 : 无 作 者 : JayYang *************************************************/ void BSP_Initializes(void) { } /**** Copyright (C)2020 JayYang. All Rights Reserved **** END OF FILE ****/ /*----------------------------------------- main.c -----------------------------------------*/ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); /* USER CODE BEGIN 2 */ BSP_Initializes(); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { LED_1_TOGGLE; HAL_Delay(500); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }总结,上面是关于 Contex 内核中的 SysTick 系统嘀嗒定时器的一些学习笔记及汇总,总的来说,常规情况下是不使用非中断的方式实现精确延时的,只使用系统嘀嗒定时器的计数功能来达到精确延时的目的,如果采用中断的方式,频繁进中断有时会影响系统,严重的会导致系统卡死。所以无论是采用标准库还是HAL库编程,都建议采用查询的方式来达到精确延时的实现。