1.硬件为stm32f407vet6,外部8M时钟
2.微秒级延时函数最大延时99.86ms
函数实现:
void Delay_Init(void) {
SysTick->CTRL = 0; // 关闭SysTick
SysTick->VAL = 0; // 清空当前计数值
// 选择时钟源:默认分频HCLK/8,168MHz/8=21MHz
SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk; // 若需更高精度,可移除分频(直接使用168MHz)
/*
选择 HCLK 作为时钟源(不分频)
SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk;
选择 HCLK/8 作为时钟源(分频)
SysTick->CTRL &= ~SysTick_CTRL_CLKSOURCE_Msk;
*/
}
void delay_us(uint32_t us) {
// 计算计数值(168MHz下不分频:us*168;分频后21MHz:us*21)
SysTick->LOAD = us * 21 - 1; // 分频21MHz,每us需21个周期,不分频168MHz,每us需168个周期
SysTick->VAL = 0; // 重置计数器
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // 启动计数
while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk)); // 等待计数完成
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; // 关闭SysTick
}
void delay_ms(uint32_t ms) {
while (ms--) {
delay_us(1000); // 调用微秒级延时1000次
}
}
优势
利用系统滴答定时器(SysTick)实现的延时函数具有以下核心优点:
1. 高精度与稳定性
- 硬件级计时:SysTick是Cortex-M内核集成的24位递减计数器,直接基于系统时钟(如STM32F407的168MHz)工作,计时精度可达微秒级。
- 独立运行:SysTick独立于CPU核心,即使CPU处理其他任务,计时仍持续进行,不受代码阻塞或中断抢占的显著影响。
- 低误差:相比软件循环延时(误差±5%),SysTick的误差可控制在±0.1%以内。
2. 低资源占用与高效性
- 无需额外外设:SysTick是内核内置功能,无需配置通用定时器(如TIM2),节省硬件资源。
- 低CPU占用:采用中断或轮询方式时,CPU可在延时期间执行其他任务(如多任务调度),而非空转等待。
- 高效的中断处理:SysTick中断优先级固定且独立,触发周期稳定,适合作为实时操作系统(RTOS)的时间基准。
3. 灵活性与易用性
- 时钟源可选:支持HCLK(不分频)或HCLK/8两种时钟源,适应不同精度与功耗需求。例如,168MHz下不分频可提供微秒级延时,分频后适合低功耗场景。
- 兼容性强:HAL库已封装`HAL_Delay()`函数,用户无需手动配置寄存器即可快速实现毫秒级延时。
- 多场景适用:既可用于简单延时(如LED闪烁),也可支持复杂任务调度(如FreeRTOS的时间片轮转)。
4. 代码简洁与可维护性
- 标准化接口:通过`SysTick_Config()`等函数即可完成初始化,代码量少且易于移植。
- 避免优化干扰:使用硬件计数器而非软件循环,编译器优化(如空循环删除)不会影响延时精度。
- 易于调试:通过读取`SysTick->VAL`寄存器可直接验证当前计数值,便于调试时序问题。
5. 低功耗特性
- 动态功耗控制:在分频模式下(如HCLK/8),SysTick的时钟频率降低,减少动态功耗。
- 与其他低功耗模式兼容:在延时期间,若结合CPU睡眠模式(如WFI指令),可进一步降低系统功耗。
总结
SysTick延时函数凭借其高精度、低资源占用和内核级集成特性,成为STM32开发中的首选延时方案。尤其在实时操作系统、传感器时序控制等对时间敏感的场景中,其优势更为显著。如需更高灵活性(如纳秒级延时),可结合DWT计数器或通用定时器扩展功能。
关于 SysTick计数器溢出问题(核心原因)
现象: delay_us(1000000) 试图延时1秒(1,000,000μs),但实际表现接近1ms。
原因:
SysTick是 24位递减计数器,最大计数值为 0xFFFFFF (即16,777,215)。
当系统时钟为168MHz时, LOAD 值计算为 1,000,000 * 168 - 1 = 167,999,999 ,远超24位最大值,导致 高位截断,实际加载值变为 167,999,999 & 0xFFFFFF = 16,777,215 。