ARM -- SysTick滴答定时器
SysTick滴答定时器
参考文献:《Cortex-M3 权威指南》
https://picture.iczhiku.com/resource/upload/6820519db1f84e7faaf51c573c48e013.pdf
———————————————————————————————————————————
SysTick(System Tick Timer)是 Cortex-M系列内核内置的一个 24 位递减计数器
-
捆绑在 NVIC(嵌套向量中断控制器)中,异常号 15。
-
所有 Cortex-M3 芯片均包含此定时器,且SysTick的处理方式都是相同的
SysTick功能
产生周期性的“滴答”(tick)中断,为操作系统(如 FreeRTOS、RT-Thread)或实时系统提供时间基准(时基)
SysTick作用
(1) 任务调度与时间片轮转
示例:
假设RTOS操作系统为任务 A 分配 3 个时间片(3ms),任务 B 分配 1 个时间片(1ms),SysTick 每 1ms 触发一次中断,RTOS 会在中断中检查是否需要切换任务,确保公平调度。
如果没有 SysTick,某个任务可能长期占用 CPU,导致系统卡死。
(2)定时功能
-
操作系统提供的延时函数(如
osDelay())、软件定时器、超时检测等均依赖 SysTick。
(3)维持系统“心跳”
-
SysTick 的寄存器通常由操作系统内核管理,用户程序无法直接修改,防止人为破坏系统节律。
SysTick 的时钟源
(1)内部时钟(FCLK):
-
Cortex-M3 的 自由运行时钟,频率与 CPU 主频相同(如
SystemCoreClock = 72MHz)。
(2)外部时钟(STCLK):
-
由芯片厂商定义,可能来自分频后的系统时钟或外部低速时钟(如 32.768kHz)。
控制SysTick定时器的4个寄存器
1、控制及状态寄存器

(1)COUNTFLAG (位16):状态标志位
-
功能:当SysTick计数器从1递减到0时,此位会自动置1。当程序读取这个位后,它会自动清零。
-
用途:常用于检测定时器是否完成了计数周期。
(2)CLKSOURCE (位2):时钟源选择位
功能:选择时钟源
- 0 = 使用外部时钟源(STCLK,通常是AHB时钟的分频)
- 1 = 使用处理器内核时钟(FCLK)
(3)TICKINT (位1):中断使能位
功能:控制是否产生中断
- 1 = 当计数器递减到0时产生SysTick异常请求(中断)
- 0 = 计数器递减到0时不产生中断
(4)ENABLE (位0):定时器使能位
功能:SysTick定时器的使能位
- 1 = 启用SysTick定时器
- 0 = 禁用SysTick定时器
2、重装载数值寄存器

RELOAD 寄存器用于设置 SysTick 定时器的重装载值
-
这个值决定了定时器的计数周期,它是一个24位的值,最大可设置为0xFFFFFF(16,777,215)
-
SysTick 定时器倒数计数从 RELOAD 值开始递减,直到0时会自动从这个寄存器重新加载数值
-
定时周期 = (RELOAD + 1) × 时钟周期
示例:
如果要配置 SysTick 每1ms产生一次中断:(假设时钟频率为16MHz)
RELOAD = (16000000 / 1000) - 1 = 15999
3、当前数值寄存器

功能描述:
(1) 读取操作:
读取时会返回 SysTick 定时器当前的倒计数值
(2) 写入操作:
向这个寄存器写入任何值都会导致:
-
当前计数值被清零
-
同时会清除 SysTick 控制及状态寄存器中的 COUNTFLAG 标志
实际应用
-
读取当前倒计数的剩余值
-
通过写入操作手动重置计数器
-
手动清除 COUNTFLAG 状态标志(当计数器从1减到0时,该标志会被置位)
4、校准数值寄存器

位段说明
(1)NOREF (位31):外部参考时钟信息
-
1表示没有外部参考时钟(STCLK不可用)
-
0表示外部参考时钟可用
(2)SKEW (位30):校准值信息
-
1表示校准值不是准确的10ms
-
0表示校准值是准确的10ms
(3)TENMS (位23:0):实现跨平台的恒定 SysTick 中断频率
当 SysTick 定时器以 系统时钟(SYSCLK) 运行时,TENMS存储的是 10ms 内 SysTick 需要计数的 ticks(时钟周期数)。(芯片厂商会默认写入这个值)。
例如:
- 如果
SYSCLK = 50MHz,则TENMS = 50,000,000 × 0.01 = 500,000如果
SYSCLK = 8MHz,则TENMS = 8,000,000 × 0.01 = 80,000。
TENMS寄存器提供了 10ms 对应的 ticks 数,直接写入RELOAD 寄存器即可在所有兼容 Cortex-M3 的芯片上实现 精确的 10ms 中断,无需关心具体时钟频率。
注意:如果看到TENMS = 0,表示 该芯片不支持自动校准功能。
RX32程序示例
1、systick_init( )函数
/********************************************************************************************************
**函数信息 :systick_init()
**功能描述 :systick延时函数初始化
**输入参数 :无
**输出参数 :无
********************************************************************************************************/
void systick_init()
{
// 配置 SysTick 定时器,设置中断频率为 4.2kHz
if (SysTick_Config((SystemCoreClock) / 10000))
{
/* 如果配置失败(SysTick_Config函数返回 1 ),则进入死循环(错误处理) */
while (1);
}
// 设置 SysTick 中断优先级为 0x2(中等优先级)
NVIC_SetPriority(SysTick_IRQn, 0x2);
}
SysTick_Config()函数说明
- SysTick_Config(uint32_t ticks)函数配置 SysTick 定时器,使其按照设定的时间间隔触发中断。
- ticks表示滴答定时器运行多少步数后中断一次。
- ticks(中断步数) = SystemCoreClock(系统主频) / 中断频率
- 已知系统主频是42MHz,这里配置滴答定时器的定时中断频率为4.2kHz,也就是约等于每 300us 触发一次中断
2、SysTick_Config( )函数
#if defined (__Vendor_SysTickConfig) && (__Vendor_SysTickConfig == 0U)
// ARM Cortex-M 的通用 SysTick 初始化模板
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) // 检查重载值是否超出最大允许范围
{
return (1UL); /* 重载值超出有效范围,设置失败 */
}
SysTick->LOAD = (uint32_t)(ticks - 1UL); /* 设置重装载寄存器值(实际写入值为ticks-1) */
NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* 设置SysTick中断优先级为最低优先级 */
SysTick->VAL = 0UL; /* 清零SysTick计数器当前值(强制重装载) */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | /* 选择处理器时钟作为时钟源 */
SysTick_CTRL_TICKINT_Msk | /* 使能SysTick中断 */
SysTick_CTRL_ENABLE_Msk; /* 启动SysTick计数器 */
return (0UL); /* 返回无符号长整型0,表示函数执行成功 */
}
}
#endif
条件编译说明:
厂商自定义了SysTick初始化时,则令_Vendor_SysTickConfig为1
厂商使用ARM自带的SysTick初始化模板,令_Vendor_SysTickConfig为0
这里的条件编译就是检查_Vendor_SysTickConfig的值,决定是否使用ARM自带的SysTick初始化模板。
SysTick_Config()函数详解:
(1)函数输入ticks的值,也就是中断步数的值
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)(2)函数通过该语句判断重载值是否越界,越界则结束函数并返回1表示错误
if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return (1UL); }(3) 函数通过该语句设置重装载寄存器值,寄存器值应该是ticks - 1(因为数到0后才触发中断)
SysTick->LOAD = (uint32_t)(ticks - 1UL);(4) 函数通过该语句设置SysTick中断优先级为最低优先级
NVIC_SetPriority (SysTick_IRQn , (1UL << __NVIC_PRIO_BITS) - 1UL);(5) 函数通过该语句设置强制重装载(给当前数值寄存器写0)
SysTick->VAL = 0UL;(6) 函数通过该语句完成以下配置:(使用位掩码的方式给控制与状态寄存器写值)
选择处理器内核时钟(FCLK)作为时钟源
使能SysTick中断
启动SysTick计数器
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;(7) 函数配置完成后,返回0表示SysTick配置成功
return (0UL);
更多推荐



所有评论(0)