目录
在ST的数据手册中无法找到与内核相关的详细内容,因为M4内核使用的是ARMv7-M指令集,通过ARM官网可以找到并下载内核架构的数据手册
一、简介
SysTick是ARM Cortex-M4内核内置的系统定时器,不属于外设定时器 ,而是内核的一部分。它是一个24位递减计数器,主要用于:
- 提供操作系统的时钟节拍(如FreeRTOS的时间片调度)
- 实现精确的延时函数
- 作为简单的时间基准
1.寄存器组成(4个关键寄存器)
- CTRL - 控制和状态寄存器
- LOAD - 重装载值寄存器
- VAL - 当前值寄存器
- CALIB - 校准值寄存器
2.时钟源配置
在STM32F4中,SysTick的时钟源有两种选择:
// 查看 SystemCoreClock 的值(通常为168MHz)
SystemCoreClock = 168000000; // HCLK频率
// 选择时钟源
SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk; // 使用HCLK
// 或
SysTick->CTRL &= ~SysTick_CTRL_CLKSOURCE_Msk; // 使用HCLK/8
3.小结
| 特性 | 说明 |
|---|---|
| 位数 | 24位递减计数器 |
| 时钟源 | AHB时钟 或 AHB/8(可配置) |
| 中断能力 | 计数器到0时产生SysTick中断 |
| 自动重载 | 支持自动重载功能 |
| 精度 | 高精度,基于系统时钟(最大只能计时1ms) |
二、示例程序
#include "stm32f4xx.h"
// 定义微秒和毫秒延时的基础计数值
// 注意:这些值需要根据你的实际SysTick时钟频率进行计算和调整
static uint32_t fac_us = 168 - 1; // 假设SysTick时钟为168MHz时,1us的计数值
static uint32_t fac_ms = 168000 - 1; // 1ms的计数值,注意防止溢出
void Delay_Init(void)
{
// SysTick时钟源通常默认是HCLK,这里不更改配置,如果需要配置为HCLK/8,可以取消下一行的注释
// SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
}
void Delay_us(uint32_t nus)
{
uint32_t temp;
SysTick->LOAD = nus * fac_us; // 设置重载值
SysTick->VAL = 0x00; // 计数前先清空当前计数器
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // 使能SysTick,使用内核时钟,不开启中断
// SysTick_CTRL_ENABLE_Msk == 0x01
do
{
temp = SysTick->CTRL;
} while ((temp & 0x01) && !(temp & (1 << 16))); // 等待时间到达,并检查计数器是否仍使能
SysTick->CTRL = 0x00; // 关闭计数器
SysTick->VAL = 0x00; // 清空计数器
}
void Delay_ms(uint32_t nms)
{
uint32_t temp;
// 注意:nms * fac_ms 的值可能超过24位,实际使用中需确保重载值不超过0xFFFFFF
SysTick->LOAD = nms * fac_ms; // 设置重载值
SysTick->VAL = 0x00; // 清空当前计数器
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // 使能SysTick,使用内核时钟,不开启中断
// SysTick_CTRL_ENABLE_Msk == 0x01
do
{
temp = SysTick->CTRL;
} while ((temp & 0x01) && !(temp & (1 << 16))); // 等待时间到达
SysTick->CTRL = 0x00; // 关闭计数器
SysTick->VAL = 0x00; // 清空计数器
}
其中
temp = Systick->CTRL,用temp检测Systick->CTRL寄存器
(temp & 0x01) 表示定时器仍在运行
!(temp & (1 << 16)) 表示COUNTFLAG位为0(时间未到)