STM32库开发:无需DelayHandle_t实现延时及全局myTicks中断适配
STM32延时库开发问题解决方案
1. 移除DelayHandle_t指针实现延时函数
可以把DelayHandle_t实例定义为全局变量(如果是库开发,也可以用源文件内的静态全局变量避免全局污染),这样延时函数不用再传递指针,直接操作全局实例即可。另外注意原代码里的TIM_CR1_CNE是笔误,应该是TIM_CR1_CEN(定时器使能位),Deleyms拼写错误修正为Delayms。
修改后代码示例:
// 先定义延时句柄结构体,若用于库,可放在头文件并加extern声明 typedef struct { volatile uint32_t myTicks; // 必须加volatile,中断会修改该变量 } DelayHandle_t; DelayHandle_t g_delayHandle; // 全局延时句柄实例 void Delayus(uint8_t value) { // 使能TIM4定时器 TIM4->CR1 |= TIM_CR1_CEN; g_delayHandle.myTicks = 0; while(g_delayHandle.myTicks < value); // 关闭TIM4定时器 TIM4->CR1 &= ~TIM_CR1_CEN; } void Delayms(uint8_t value) { TIM4->CR1 |= TIM_CR1_CEN; g_delayHandle.myTicks = 0; // 强制转成uint32_t避免溢出 while(g_delayHandle.myTicks < (uint32_t)value * 1000); TIM4->CR1 &= ~TIM_CR1_CEN; }
2. 设置全局myTicks适配中断使用
核心注意两点:
- 给
myTicks加volatile关键字:因为中断服务函数会修改它,主程序会读取,volatile能阻止编译器优化变量读写,确保每次都从内存取最新值。 - 将
myTicks(或其所在的句柄实例)设为全局变量,让中断服务函数能直接访问。
修改后中断服务函数:
void TIM4_IRQHandler() { // 先检查更新中断标志,避免误触发 if(TIM4->SR & TIM_SR_UIF) { g_delayHandle.myTicks++; TIM4->SR &= ~TIM_SR_UIF; // 清除中断标志位 } }
如果不想用结构体,直接单独定义全局myTicks也可以:
volatile uint32_t g_myTicks = 0; // 全局volatile计数变量 void Delayus(uint8_t value) { TIM4->CR1 |= TIM_CR1_CEN; g_myTicks = 0; while(g_myTicks < value); TIM4->CR1 &= ~TIM_CR1_CEN; } void Delayms(uint8_t value) { TIM4->CR1 |= TIM_CR1_CEN; g_myTicks = 0; while(g_myTicks < (uint32_t)value * 1000); TIM4->CR1 &= ~TIM_CR1_CEN; } void TIM4_IRQHandler() { if(TIM4->SR & TIM_SR_UIF) { g_myTicks++; TIM4->SR &= ~TIM_SR_UIF; } }
额外注意:
- 要提前配置好TIM4的预分频和自动重载值,确保每次中断触发间隔是1us,这样
myTicks每加1对应1us,符合延时函数的逻辑。 - 合理配置TIM4的中断优先级,避免影响其他关键中断的响应。
内容的提问来源于stack exchange,提问作者metisai02
相关产品推荐
相关产品推荐

