系统定时器(中断延时(定时中断执行功能))
《STM32中文参考手册》P108
SysTick叫做系统滴答时钟(系统定时器),属于Cortex-M4内核中的一个外设(外围设备),并且是24bit向下递减的计数器。
RCC向Cortex系统定时器(SysTick)馈送8分频的AHB时钟(HCLK)。SysTick可使用此时钟作为时钟源,也可使用HCLK作为时钟源,具体可在SysTick控制和状态寄存器中配置。(168MHZ(HCLK时钟)、21MHZ(8分频的AHB时钟(HCLK)
注意:
- 定时器的位数越多,定时时间更长。
- 通过计数值间接计算定时时间,不能像操作系统直接调用函数实现延时或定时功能。计数值,就是要进行多少个计数。
系统定时器(事件延时)
《Cortex M3与M4权威指南.pdf》第351页
1. 官方标准例程代码:
c
SysTick->CTRL = 0; // Disable SysTick 0 0000 0000 0000 0000SysTick->LOAD = 0xFF; // Count from 255 to 0 (256 cycles)SysTick->VAL = 0; // Clear current value as well as count fl
SysTick->CTRL = 5; // Enable SysTick timer with processor clock 0 0000 0000 0000 0101
while ((SysTick->CTRL & 0x00010000)==0); // Wait until count flag is set 0000 0000 0000 0001 0000 0000 0000 0000
SysTick->CTRL = 0; // Disable SysTicki
2. 相关寄存器说明
a. 控制和状态寄存器 SysTick CTRL 寄存器

地址:0xE000E010
作用:控制 SysTick 的启停、时钟源、中断,以及读取计数完成标志。
| 位 | 名称 | 说明 |
|---|---|---|
| 0 | ENABLE | 1 = 启动 SysTick 计数器;0 = 禁止计数 |
| 1 | TICKINT | 1 = 计数到 0 时触发中断;0 = 不触发中断 |
| 2 | CLKSOURCE | 1 = 内部处理器时钟(HCLK);0 = 外部时钟(通常为 HCLK/8) |
| 16 | COUNTFLAG | 1 = 计数到 0 时自动置位,读后自动清零;0 = 未完成 |
其余位通常保留,写 0 即可。
代码中的用法:
SysTick->CTRL = 0; // 关闭
SysTick->CTRL = 5; // 5 = 0b101 -> ENABLE=1, TICKINT=0, CLKSOURCE=1
while ((SysTick->CTRL & 0x00010000) == 0); // 等待 COUNTFLAG = 1
b. 重装载寄存器 SysTick LOAD 寄存器

地址:0xE000E014
作用:设置倒计数的初始值,计数器每次从 LOAD 的值开始倒数到 0。
- 可设置范围:0~0xFFFFFF(24 位)
- 当计数到 0 时:
- COUNTFLAG = 1
- 如果 ENABLE=1,计数器自动重新加载
LOAD值(形成循环计数)
代码中的用法:
SysTick->LOAD = 0xFF; // 计数 256 个周期(255->0)
c. 当前数值寄存器 SysTick VAL 寄存器

地址:0xE000E018
作用:当前倒计数值。写 0 会:
- 清零计数器(下次从 LOAD 开始计数)
- 清除 COUNTFLAG 标志
代码中的用法:
c
SysTick->VAL = 0; // 清零计数器和标志
3. 操作说明
a. 关闭 SysTick
SysTick->CTRL = 0; // Disable SysTick
CTRL是 SysTick 控制寄存器。- 写 0 表示 关闭 SysTick 定时器。
- 注释里的二进制:
0 0000 0000 0000 0000表示所有位都清零。
作用:保证开始时定时器是关闭状态,防止计数异常。
b. 设置计数值
SysTick->LOAD = 0xFF; // Count from 255 to 0 (256 cycles)
LOAD寄存器设置计数器的初始值。0xFF= 255,计数器会从 255 倒数到 0。- SysTick 倒计数器 ,所以总共计数 256 个时钟周期(包含 0)。
c. 清零当前计数
SysTick->VAL = 0; // Clear current value as well as count flag
VAL是当前计数值寄存器。- 写 0 会:
- 清除当前计数器的值(马上从
LOAD开始计数)。 - 清除计数完成标志(COUNTFLAG)。
- 清除当前计数器的值(马上从
- 注释中的 "clear count fl" 就是指这个标志。
d. 启动定时器
SysTick->CTRL = 5; // Enable SysTick timer with processor clock
CTRL控制寄存器:- Bit 0 (ENABLE) = 1 → 使能 SysTick。
- Bit 2 (CLKSOURCE) = 1 → 选择 处理器时钟(HCLK) 作为时钟源。
- Bit 1 (TICKINT) = 0 → 不产生中断。
- 二进制:
0 0000 0000 0000 0101- 从右到左:
- Bit0=1 (ENABLE)
- Bit1=0 (TICKINT)
- Bit2=1 (CLKSOURCE)
- 其他位=0
- 从右到左:
e. 等待计数完成
while ((SysTick->CTRL & 0x00010000) == 0);
-
Bit16 (
COUNTFLAG) = 1 → 表示计数器从LOAD倒数到 0。 -
这里是一个 阻塞等待,直到计数完成。
-
二进制注释:
0000 0000 0000 0001 0000 0000 0000 0000正是 Bit16 的掩码。
f. 再次关闭 SysTick
SysTick->CTRL = 0; // Disable SysTick
- 延时完成后关闭定时器,防止误触发。
使用配置
时间配置
c
SysTick_Config(SystemCoreClock/1000) ; //系统滴答定时器1ms触发一次
系统滴答定时中断函数
事件触发后,需要去执行的中断函数,函数内容按照需求即可。
c
void SysTick_Handler(void);
注意:函数格式(函数名,返回值,参数)必须一致,具体函数名可参考启动文件 startup_stm32f40_41xxx.s。

补充说明
ST官方给的例程代码,是没有考虑意外关闭中断的问题的,需要额外补充。
c
uint32_t temp = 0;
// 系统滴答时钟配置
SysTick->CTRL = 0;
SysTick->LOAD = sysclk_nus-l;
SysTick->VAL=0;
SysTick->CTRL = sysclk_clh_flag:
while(1)
{
temp = SysTick->CTRL;
//检测COUNTFLAG标志位
if(temp & 0x00010000)
break;
//检查系统定时器是否意外关闭
if((temp &0x1)==0)
return -1: // 意外关闭,直接退出
}
SysTick->CTRL = 0;
注:以上均是学习笔记。