STM32延时函数详解与实践
在 STM32 微控制器中,实现延时函数通常有两种常见方法:
- 使用循环空转(阻塞式延时):通过循环计数实现延时,简单但会占用 CPU 资源。
- 使用定时器(非阻塞式延时):利用硬件定时器实现精确延时,效率更高。
以下分别介绍这两种方法的实现。
方法 1:使用循环空转实现延时(阻塞式)
这种方法通过循环计数实现延时,适用于简单的应用场景。
#include "stm32f10x.h" // 根据你的 STM32 型号包含对应的头文件
// 简单延时函数(单位:毫秒)
void Delay_ms(uint32_t ms)
{
for (uint32_t i = 0; i < ms; i++)
{
for (volatile uint32_t j = 0; j < 7200; j++); // 调整循环次数以适配你的时钟频率
}
}
// 简单延时函数(单位:微秒)
void Delay_us(uint32_t us)
{
for (uint32_t i = 0; i < us; i++)
{
for (volatile uint32_t j = 0; j < 7; j++); // 调整循环次数以适配你的时钟频率
}
}
说明:
Delay_ms
和 Delay_us
是通过空循环实现的延时函数。方法 2:使用定时器实现延时(非阻塞式)
利用 STM32 的硬件定时器可以实现更精确的延时,同时释放 CPU 资源。
步骤:
- 配置一个定时器(如 TIM2)。
- 在延时函数中启动定时器并等待定时器标志位。
以下是实现代码:
#include "stm32f10x.h" // 根据你的 STM32 型号包含对应的头文件
// 初始化定时器(以 TIM2 为例)
void Timer_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 使能 TIM2 时钟
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = 7200 - 1; // 自动重装载值
TIM_TimeBaseStructure.TIM_Prescaler = 1000 - 1; // 预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_Cmd(TIM2, ENABLE); // 使能 TIM2
}
// 毫秒级延时函数
void Delay_ms(uint32_t ms)
{
for (uint32_t i = 0; i < ms; i++)
{
TIM_SetCounter(TIM2, 0); // 清零计数器
while (TIM_GetCounter(TIM2) < 72); // 等待计数器达到 72(1ms)
}
}
// 微秒级延时函数
void Delay_us(uint32_t us)
{
TIM_SetCounter(TIM2, 0); // 清零计数器
while (TIM_GetCounter(TIM2) < us); // 等待计数器达到指定值
}
说明:
Timer_Init
初始化 TIM2 定时器,配置为 1ms 的定时周期(假设系统时钟为 72MHz)。Delay_ms
和 Delay_us
通过读取定时器的计数器值实现精确延时。方法 3:使用 SysTick 定时器实现延时
SysTick 是 Cortex-M 内核提供的一个系统定时器,非常适合用于实现延时函数。
实现代码:
#include "stm32f10x.h" // 根据你的 STM32 型号包含对应的头文件
// 初始化 SysTick 定时器
void SysTick_Init(void)
{
SysTick_Config(SystemCoreClock / 1000); // 配置 SysTick 为 1ms 中断
}
// 毫秒级延时函数
void Delay_ms(uint32_t ms)
{
uint32_t start = SysTick->VAL; // 获取当前 SysTick 计数器值
while (ms--)
{
while ((start - SysTick->VAL) < (SystemCoreClock / 1000)); // 等待 1ms
start = SysTick->VAL; // 更新起始值
}
}
// 微秒级延时函数
void Delay_us(uint32_t us)
{
uint32_t start = SysTick->VAL; // 获取当前 SysTick 计数器值
while (us--)
{
while ((start - SysTick->VAL) < (SystemCoreClock / 1000000)); // 等待 1us
start = SysTick->VAL; // 更新起始值
}
}
说明:
SysTick_Config(SystemCoreClock / 1000)
将 SysTick 定时器配置为 1ms 中断。Delay_ms
和 Delay_us
通过读取 SysTick 计数器的值实现精确延时。总结
作者:追月亮的少年