STM32F0单定时器能否生成多延迟时间中断?
STM32F0单定时器实现多延迟中断方案
可以实现,利用STM32F0通用定时器的输出比较(OC)模式,通过4个独立的比较通道,就能在单次启动定时器后,分别在指定的20us、50us、100us、300us触发中断,无需占用多个定时器。
核心原理
STM32F0的16位通用定时器(如TIM2、TIM3、TIM4)具备最多4个输出比较通道,每个通道拥有独立的捕获/比较寄存器(CCR1~CCR4)。当定时器计数器(CNT)的值等于某个通道的CCRx值时,该通道会触发中断,以此实现不同时间点的中断触发。
具体实现步骤(基于HAL库)
定时器基础配置
假设APB1时钟为48MHz(STM32F0默认总线时钟),将定时器预分频器设为47,这样定时器计数频率为48MHz/(47+1)=1MHz,即每计数1次对应1us。将自动重装载寄存器(ARR)设为最大值65535,让定时器持续向上计数。TIM_HandleTypeDef htim2; void MX_TIM2_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_OC_InitTypeDef sConfigOC = {0}; htim2.Instance = TIM2; htim2.Init.Prescaler = 47; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 65535; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_Base_Init(&htim2) != HAL_OK) { Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) { Error_Handler(); } if (HAL_TIM_OC_Init(&htim2) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) { Error_Handler(); } }通道比较值配置与中断开启
分别为4个通道设置对应的CCRx值(20、50、100、300),并开启每个通道的比较中断:// 配置通道1:20us触发 sConfigOC.OCMode = TIM_OCMODE_TIMING; sConfigOC.Pulse = 20; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; if (HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) { Error_Handler(); } HAL_TIM_OC_Start_IT(&htim2, TIM_CHANNEL_1); // 通道2:50us触发 sConfigOC.Pulse = 50; if (HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) { Error_Handler(); } HAL_TIM_OC_Start_IT(&htim2, TIM_CHANNEL_2); // 通道3:100us触发 sConfigOC.Pulse = 100; if (HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK) { Error_Handler(); } HAL_TIM_OC_Start_IT(&htim2, TIM_CHANNEL_3); // 通道4:300us触发 sConfigOC.Pulse = 300; if (HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_4) != HAL_OK) { Error_Handler(); } HAL_TIM_OC_Start_IT(&htim2, TIM_CHANNEL_4);中断回调处理
在HAL库中,通道比较中断会触发HAL_TIM_OC_DelayElapsedCallback函数,通过判断当前触发的通道,执行对应逻辑:void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM2) { if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC1)) { __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_CC1); // 执行20us延迟后的任务 } else if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC2)) { __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_CC2); // 执行50us延迟后的任务 } else if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC3)) { __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_CC3); // 执行100us延迟后的任务 } else if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC4)) { __HAL_TIM_CLEAR_FLAG(htim, TIM_FLAG_CC4); // 执行300us延迟后的任务 } } }
注意事项
- 如果需要重复触发某一延迟的中断,需在对应通道的中断处理中,将CCRx的值加上当前计数器值(或固定偏移),确保下一次触发时间正确。
- STM32F0的TIM1是高级定时器,也支持多通道比较,但通用定时器TIM2/TIM3/TIM4已足够满足需求,无需占用高级定时器资源。
- 务必在NVIC中正确配置定时器中断的优先级,避免与其他中断冲突。
内容的提问来源于stack exchange,提问作者ElecDesigner
相关产品推荐
相关产品推荐

