基础概念: STM32F407VG是一款基于ARM Cortex-M4内核的微控制器。ISR(中断服务例程)是在特定中断发生时由处理器执行的特殊函数。HAL_Delay()是STM32 HAL库中的一个函数,用于产生延时。
为什么不能在ISR中使用HAL_Delay(): HAL_Delay()函数依赖于SysTick定时器来实现延时功能。在ISR中调用HAL_Delay()会导致SysTick定时器被阻塞,进而影响系统的实时性和其他中断的处理。
原因分析:
解决方案: 在ISR中应避免使用HAL_Delay(),可以采用以下替代方案:
配置一个硬件定时器,在定时器中断中处理延时相关的任务。
// 配置定时器中断
TIM_HandleTypeDef htim;
void MX_TIMx_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim.Instance = TIMx;
htim.Init.Prescaler = SystemCoreClock / 10000 - 1; // 10kHz
htim.Init.CounterMode = TIM_COUNTERMODE_UP;
htim.Init.Period = 1000 - 1; // 1ms
htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim) != HAL_OK)
{
// 初始化错误处理
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim, &sClockSourceConfig) != HAL_OK)
{
// 配置时钟源错误处理
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim, &sMasterConfig) != HAL_OK)
{
// 主从同步配置错误处理
}
HAL_TIM_Base_Start_IT(&htim);
}
// 定时器中断回调函数
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIMx)
{
// 处理延时相关的任务
}
}
在中断中设置一个标志位,在主循环中检查该标志位并执行延时操作。
volatile uint8_t delayFlag = 0;
// 中断服务例程
void EXTI0_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_0)
{
delayFlag = 1;
}
}
// 主循环
int main(void)
{
while (1)
{
if (delayFlag == 1)
{
HAL_Delay(1000); // 延时1秒
delayFlag = 0;
}
// 其他任务处理
}
}
如果系统中使用了实时操作系统(RTOS),可以将延时相关的任务放在一个独立的任务中,并使用RTOS提供的延时函数。
// 任务函数
void Task_Delay(void *argument)
{
while (1)
{
// 延时任务处理
osDelay(1000); // 延时1秒
}
}
// 创建任务
osThreadDef(Task_Delay, osPriorityNormal, 1, 0);
osThreadCreate(osThread(Task_Delay), NULL);
应用场景:
通过以上方案,可以在ISR中避免使用HAL_Delay(),确保系统的实时性和稳定性。
领取专属 10元无门槛券
手把手带您无忧上云