STM32_SysTick_寄存器操作

文章目录

  • [一、SysTick 核心寄存器](#一、SysTick 核心寄存器)
    • [   SysTick 寄存器地址固定在 0xE000E010,核心 4 个寄存器:](#   SysTick 寄存器地址固定在 0xE000E010,核心 4 个寄存器:)
    • [   核心规则:](#   核心规则:)
  • [二、SysTick 寄存器编程](#二、SysTick 寄存器编程)
    • [   1、精准 us/ms 延时函数(非中断方式)](#   1、精准 us/ms 延时函数(非中断方式))
    • [   2、SysTick 周期性中断(1ms 中断)](#   2、SysTick 周期性中断(1ms 中断))
  • 三、小结

SysTick(系统滴答定时器)是 Cortex-M 内核自带的外设,无需依赖 STM32 片上外设,常用来实现精准延时、系统心跳(如 RTOS 时钟节拍)。

一、SysTick 核心寄存器

SysTick 寄存器地址固定在 0xE000E010,核心 4 个寄存器:

核心规则:

SysTick 时钟源默认是系统时钟(72MHz)(STM32F103);

递减计数:从 LOAD 值减到 0,触发 COUNTFLAG(或中断),然后自动重载;

延时计算公式:LOAD = (时钟频率 × 延时时间) - 1(减 1 是因为从 0 开始计数)。

二、SysTick 寄存器编程

1、精准 us/ms 延时函数(非中断方式)

实现微秒 / 毫秒级阻塞延时,无中断、占用 CPU 但简单高效。

c 复制代码
		#include "stm32f10x.h"
		
		// 全局变量:SysTick时钟频率(72MHz)
		#define SYSTICK_CLK 72000000
		
		/**
		 * @brief  SysTick初始化(关闭中断,仅用于延时)
		 */
		void SysTick_Init(void)
		{
		    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;  // 先关闭SysTick
		    SysTick->VAL = 0;                           // 清空当前计数值
		}
		
		/**
		 * @brief  SysTick微秒延时(寄存器版)
		 * @param  us:延时微秒数(最大支持 999999us,超过需拆分)
		 */
		void SysTick_Delay_us(uint32_t us)
		{
		    uint32_t load_val;
		    
		    // 1. 计算重装载值:72MHz → 1us需要计数72次
		    load_val = (SYSTICK_CLK / 1000000) * us - 1;
		    // 防止重载值超过SysTick_LOAD_RELOAD_Msk(24位最大值)
		    if(load_val > SysTick_LOAD_RELOAD_Msk)
		    {
		        load_val = SysTick_LOAD_RELOAD_Msk;
		    }
		
		    // 2. 设置重装载值
		    SysTick->LOAD = load_val;
		    // 3. 清空当前计数值
		    SysTick->VAL = 0;
		    // 4. 开启SysTick(关闭中断,时钟源=系统时钟)
		    SysTick->CTRL = SysTick_CTRL_ENABLE_Msk;
		
		    // 5. 等待计数完成(COUNTFLAG位为1)
		    while(!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
		
		    // 6. 关闭SysTick
		    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
		}
		
		/**
		 * @brief  SysTick毫秒延时(寄存器版)
		 * @param  ms:延时毫秒数
		 */
		void SysTick_Delay_ms(uint32_t ms)
		{
		    // 拆分长延时,避免LOAD值溢出(24位最大值约186ms@72MHz)
		    while(ms--)
		    {
		        SysTick_Delay_us(1000);
		    }
		}
		
		/**
		 * @brief  测试:LED闪烁(PC13)
		 */
		void GPIO_Init_LED(void)
		{
		    // 开启GPIOC时钟
		    RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
		    // 配置PC13为推挽输出
		    GPIOC->CRH &= ~(GPIO_CRH_MODE13 | GPIO_CRH_CNF13);
		    GPIOC->CRH |= GPIO_CRH_MODE13_0;
		    GPIOC->ODR |= GPIO_ODR_ODR13; // 初始熄灭
		}
		
		// 主函数测试
		int main(void)
		{
		    SysTick_Init();       // 初始化SysTick
		    GPIO_Init_LED();      // 初始化LED
		
		    while(1)
		    {
		        GPIOC->ODR ^= GPIO_ODR_ODR13; // 翻转LED
		        SysTick_Delay_ms(500);        // 延时500ms
		    }
		}

2、SysTick 周期性中断(1ms 中断)

用于系统节拍(如 RTOS 时钟、定时任务),中断方式不阻塞 CPU。

c 复制代码
		#include "stm32f10x.h"
		
		// 全局变量:1ms中断计数
		uint32_t SysTick_Count = 0;
		
		/**
		 * @brief  SysTick初始化(1ms中断)
		 */
		void SysTick_IRQ_Init(void)
		{
		    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;  // 关闭SysTick
		    SysTick->VAL = 0;                           // 清空计数值
		
		    // 1. 设置1ms重装载值:72MHz → 1ms需要72000次计数
		    SysTick->LOAD = (SYSTICK_CLK / 1000) - 1;
		
		    // 2. 配置NVIC(SysTick中断优先级)
		    // SysTick是内核中断,优先级由SCB->SHPR3的bit24-31配置
		    SCB->SHPR3 |= (0x20 << 24);  // 抢占优先级2(高4位有效)
		
		    // 3. 开启SysTick中断 + 开启SysTick + 时钟源=系统时钟
		    SysTick->CTRL = SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
		}
		
		/**
		 * @brief  SysTick中断服务函数(内核中断,名称固定)
		 */
		void SysTick_Handler(void)
		{
		    // 清除中断标志(读COUNTFLAG自动清,或写VAL=0)
		    SysTick->VAL = 0;
		    // 业务逻辑:1ms计数+1
		    SysTick_Count++;
		}
		
		/**
		 * @brief  基于SysTick计数的ms延时(非阻塞版)
		 * @param  ms:延时毫秒数
		 */
		void SysTick_Delay_ms_IRQ(uint32_t ms)
		{
		    uint32_t target = SysTick_Count + ms;
		    while(SysTick_Count < target);
		}
		
		// 主函数测试
		int main(void)
		{
		    SysTick_IRQ_Init();   // 初始化SysTick中断(1ms)
		    GPIO_Init_LED();      // 复用上面的GPIO_Init_LED函数
		
		    while(1)
		    {
		        GPIOC->ODR ^= GPIO_ODR_ODR13; // 翻转LED
		        SysTick_Delay_ms_IRQ(500);    // 基于中断的500ms延时
		    }
		}

三、小结

SysTick 寄存器编程核心:配置LOAD(重装载值)→ 清空VAL → 控制CTRL(开启 / 中断);

非中断版延时简单高效,适合短延时;中断版不阻塞 CPU,适合系统节拍;

注意 24 位 LOAD 寄存器的溢出限制,长延时需拆分处理,且时钟源需与计算值匹配。

相关推荐
UTP协同自动化测试3 小时前
物联网模组测试难点 |APP指令下发+UART 响应+GPIO 电平变化,如何一次性验证?
功能测试·嵌入式硬件·物联网·模块测试
4caf16 小时前
作业2:6位数码管静态显示
嵌入式硬件·51单片机
不做无法实现的梦~6 小时前
STM32解析PPM协议
stm32·单片机·嵌入式硬件
北京青翼科技7 小时前
青翼科技PCIe总线架构的2路10G光纤通道适配器丨数据采集卡丨PCIe接口板卡 2 路 SFP+光纤收发器
fpga开发·采集卡·fpga板卡·pcie接口·多功能板卡
czhaii7 小时前
基于Arm Cortex-M7内核GD32H7
单片机·嵌入式硬件
番茄灭世神7 小时前
MCU开发常见软件BUG总结(持续更新)
c语言·stm32·单片机·嵌入式·gd32
wanghanjiett7 小时前
双轮平衡车建模及控制 2 PID控制原理与调参
嵌入式硬件·控制算法
EVERSPIN7 小时前
SQPI PSRAM为单片机提供RAM扩展方案
单片机·嵌入式硬件·psram·sqpi psram
Ar-Sr-Na8 小时前
STM32现代化AI开发指南-VSCode环境配置(macOS)
c语言·人工智能·vscode·stm32·嵌入式硬件·硬件工程
进击的小头8 小时前
第6篇:嵌入式芯片算力核心来源:多级流水线架构与指令并行机制详解
单片机·嵌入式硬件·架构