STM32 SysTick定时器

打印 上一主题 下一主题

主题 1761|帖子 1761|积分 5283

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
一、SysTick体系定时器概述

1.1 什么是SysTick定时器

SysTick(System Tick Timer)是ARM Cortex-M系列处理器内核集成的24位体系定时器,作为ARM架构的标准外设,它被深度整合在NVIC(嵌套向量中断控制器)中。该定时器接纳向下递减计数方式,具有主动重装载功能,可以或许产生周期性的中断哀求。
SysTick的通用性设计使得基于Cortex-M3内核的微控制器(如STM32F1系列)都具备这一外设,极大提升了代码的可移植性。其主要应用场景包罗:


  • 实时操纵体系(RTOS)的心跳时钟
  • 高精度延时函数实现
  • 时间片轮询任务调度
  • 性能监测与基准测试
1.2 SysTick技术特性

特性参数/描述计数器位宽24位(最大计数值16,777,215)时钟源内核时钟或外部参考时钟(通常AHB/8)中断触发计数到零时主动产生非常(非常号15)重装载机制主动加载预置值并继承计数典范应用频率STM32F103系列最高支持72MHz https://img-blog.csdnimg.cn/direct/3d1a6f6a0e3e4c8a9b0b6c4c4d4c8e9a.png
(图示:SysTick与处理器内核的连接关系)
二、SysTick寄存器深度解析

SysTick通过四个寄存器实现完整控制,其内存映射地址为0xE000E010:
2.1 寄存器结构体

c
Copy
  1. typedef struct {
  2.     __IO uint32_t CTRL;    // 控制及状态寄存器
  3.     __IO uint32_t LOAD;    // 重装载值寄存器
  4.     __IO uint32_t VAL;     // 当前值寄存器
  5.     __I  uint32_t CALIB;   // 校准值寄存器(只读)
  6. } SysTick_Type;
复制代码
2.2 控制寄存器(CTRL)

地址偏移:0x00,复位值:0x0000 0000
位域名称类型描述16COUNTFLAGR计数完成标记位(读取主动清零)2CLKSOURCER/W时钟源选择:0=外部时钟(AHB/8),1=内核时钟1TICKINTR/W中断使能:1=计数到零时触发中断0ENABLER/W定时器使能位   注:STM32F103的AHB总线时钟与内核时钟同频,典范值为72MHz
  2.3 关键寄存器操纵

重装载值计算:
c
Copy
  1. // 计算1ms延时的重载值(假设系统时钟72MHz)
  2. uint32_t reload = SystemCoreClock / 1000 - 1;
  3. SysTick->LOAD = reload;
复制代码
状态检测本领:
c
Copy
  1. // 高效等待计数完成
  2. while(!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
复制代码
三、SysTick延时函数实现

3.1 微秒级延时实现

c
Copy
  1. void delay_us(uint32_t us)
  2. {
  3.     SysTick->CTRL &= ~SysTick_CTRL_CLKSOURCE_Msk; // 选择外部时钟(AHB/8)
  4.     SysTick->LOAD = 21 * us - 1;                  // 72MHz/8=9MHz → 每微秒9周期 → 实际需要9*us
  5.     SysTick->VAL = 0;                             // 清除当前值
  6.     SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;     // 启动定时器
  7.    
  8.     while(!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
  9.    
  10.     SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;    // 关闭定时器
  11. }
复制代码
参数计算推导:


  • 外部时钟频率 = 72MHz / 8 = 9MHz
  • 周期时间 = 1 / 9MHz ≈ 111.11ns
  • 1μs所需周期数 = 1μs / 111.11ns ≈ 9 → 实际取9*us
   注意:示例代码中的21us存在计算错误,精确应为9us,后续分析将说明
  3.2 毫秒级延时优化

c
Copy
  1. void delay_ms(uint16_t ms)
  2. {
  3.     SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk;  // 使用内核时钟
  4.     uint32_t reload = SystemCoreClock / 1000 - 1; // 精确计算重载值
  5.    
  6.     for(uint16_t i=0; i<ms; i++){
  7.         SysTick->LOAD = reload;
  8.         SysTick->VAL = 0;
  9.         SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
  10.         
  11.         while(!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
  12.     }
  13.    
  14.     SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
  15. }
复制代码
3.3 代码中的关键问题分析


  • 时钟源选择矛盾:

    • 原代码利用CTRL &= ~(1<<2)选择外部时钟(9MHz)
    • 但LOAD值计算基于21*us(对应21MHz时钟)
    • 精确做法应同一时钟源选择

  • 最大延时限定:
    c
    Copy
    1. // 错误用法示例
    2. delay_us(1000000); // 试图延时1秒
    3. // 正确实现方式
    4. #define MAX_US_DELAY 0xFFFFFF / 21
    5. void safe_delay_us(uint32_t us){
    6.     while(us > MAX_US_DELAY){
    7.         delay_us(MAX_US_DELAY);
    8.         us -= MAX_US_DELAY;
    9.     }
    10.     delay_us(us);
    11. }
    复制代码
  • 中断使能缺失:

    • 原代码未启用TICKINT中断位
    • 在非阻塞延时场景下需要中断服务例程

四、SysTick高级应用本领

4.1 操纵体系心跳实现

c
Copy
  1. // FreeRTOS配置示例
  2. #define configSYSTICK_CLOCK_HZ    ( 72000000UL )
  3. #define configTICK_RATE_HZ        ( 1000UL )
  4. void vConfigureSysTick(void){
  5.     SysTick->LOAD = (configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ) - 1UL;
  6.     SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
  7.                    SysTick_CTRL_TICKINT_Msk |
  8.                    SysTick_CTRL_ENABLE_Msk;
  9. }
复制代码
4.2 精确时间测量

c
Copy
  1. uint32_t measure_execution_time(void (*func)(void)){
  2.     SysTick->CTRL = 0; // 关闭定时器
  3.     SysTick->LOAD = 0xFFFFFF; // 最大计数值
  4.     SysTick->VAL = 0;
  5.     SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
  6.    
  7.     func(); // 执行被测函数
  8.    
  9.     SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
  10.     return 0xFFFFFF - SysTick->VAL; // 返回实际计数值
  11. }
复制代码
4.3 低功耗模式集成

c
Copy
  1. void enter_stop_mode(uint32_t ms){
  2.     SysTick->LOAD = ms * (SystemCoreClock / 1000) - 1;
  3.     SysTick->VAL = 0;
  4.     SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
  5.    
  6.     PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
  7.     SystemCoreClockUpdate(); // 唤醒后恢复时钟
  8. }
复制代码
五、性能优化与调试本领

5.1 临界区掩护

c
Copy
  1. __disable_irq(); // 关闭全局中断
  2. // 执行关键时序操作
  3. __enable_irq();
复制代码
5.2 示波器验证方法


  • 设置GPIO引脚作为测试点
  • 在延时函数前后翻转电平
  • 利用示波器测量脉冲宽度
c
Copy
  1. GPIO_SetBits(TEST_PIN);
  2. delay_us(500);
  3. GPIO_ResetBits(TEST_PIN);
复制代码
5.3 误差分析表

误差来源影响水平解决方案中断响应延迟1-5周期利用硬件计数器补偿时钟源抖动<0.1%选择高精度晶振指令实验时间固定偏差校准基准值电源电压波动可忽略保持稳固供电 六、常见问题解答

Q1:为什么SysTick更适合作为RTOS时基?
A:SysTick具有以下优势:


  • 内核集成,所有Cortex-M芯片通用
  • 独立时钟源,不受外设时钟门控影响
  • 精确的中断触发机制
  • 24位宽计数器支持长时间定时
Q2:如何实现微秒级以下精度?
A:可接纳以下方法:

  • 利用更高频率的时钟源(如168MHz)
  • 启用DWT(数据观察点跟踪)周期计数器
  • 利用硬件定时器的输入捕获功能
Q3:SysTick校准寄存器有什么作用?
A:CALIB寄存器提供:


  • 出厂校准的10ms重载值(TENMS域)
  • 时钟源信息(SKEW位)
  • 参考时钟是否存在(NOREF位)
七、结语

SysTick作为Cortex-M3内核的精妙设计,在嵌入式开辟中发挥偏紧张作用。通过深入明白其工作机制,开辟者可以:


  • 实现精准的时序控制
  • 构建可靠的体系底子
  • 优化功耗管理策略
  • 提升代码的跨平台兼容性
随着物联网和实时体系的发展,SysTick的应用将更加广泛。发起开辟者结合详细芯片手册,机动运用本文先容的技术要点,打造高性能的嵌入式体系。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

温锦文欧普厨电及净水器总代理

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表