【HAL库】STM32 Timer定时器开机立即进入中断问题

学习中发现配置Timer定时器后,MCU开机就进入中断,不符合逻辑。作者在各大博客未找到HAL库解决办法,通过Google找到方案。即在TIM初始化函数与启动中断函数间加语句清除更新中断标志位,也可将定时器状态寄存器置0。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


学习过程中发现配置号Timer定时器功能之后,原本应该定时到指定的时间再进入中断,结果MCU开机就会进入一次中断,不符合逻辑,所以尝试解决这个问题。

拜读各大佬的博客后发现没有HAL库的解决办法,于是转身向Google走去,找到了解决办法,分享给大家。


解决办法

在TIM初始化函数  HAL_TIM_Base_Init()   与   HAL_TIM_Base_Start_IT();

之间加一条语句 __HAL_TIM_CLEAR_FLAG(&htim7, TIM_SR_UIF); //注意将htim7改成自己的timer

其中TIM_SR_UIF是 Update interrupt Flag 寄存器。

原因就是HAL库中定时器初始化后没有更新中断标志位,__HAL_TIM_CLEAR_FLAG(&htim7, TIM_SR_UIF)后清除了更新中断标志位,此时TIM_SR_UIF为0,中断产生后TIM_SR_UIF为1。

另外

细心的朋友会发现TIM_SR_UIF其实是SR(定时器状态寄存器)的最低位,初始化时若TIM_SR_UIF为1则SR也为1,若TIM_SR_UIF为0则SR也为0,因此存在另一种解决办法:将__HAL_TIM_CLEAR_FLAG(&htim7, TIM_SR_UIF);换成htim7.Instance->SR = 0也是可以的。

示范

/**
  * @brief TIM7 Initialization Function
  * @param None
  * @retval None
  */
void MX_TIM7_Init(uint16_t arr, uint16_t psc)
{

  /* USER CODE BEGIN TIM7_Init 0 */

  /* USER CODE END TIM7_Init 0 */

  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM7_Init 1 */
	//(uint32_t)ceil(SECOND_WAKEUP) * 10000 / 2, 8400 - 1
  /* USER CODE END TIM7_Init 1 */
  htim7.Instance = TIM7;
  htim7.Init.Prescaler = psc;
  htim7.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim7.Init.Period = arr;
  htim7.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim7) != HAL_OK)// 定时器初始化
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM7_Init 2 */

   __HAL_TIM_CLEAR_FLAG(&htim7, TIM_SR_UIF);//添加这条语句解决问题
   //htim7.Instance->SR = 0; //这是另一种解决办法

   HAL_TIM_Base_Start_IT(&htim7);//开启定时器中断

  /* USER CODE END TIM7_Init 2 */
}

 

### 使用 HAL 庿配置 STM32F103 定时器中断 #### 初始化定时器 为了使用 HAL STM32F103 上实现定时器中断配置,初始化是第一步。这通常通过 CubeMX 工具自动生成大部分代码来完成。 ```c // 在 main.c 中调用 MX_TIM_Init 函数进行定时器硬件资源初始化 void MX_TIM1_Init(void) { TIM_HandleTypeDef htim1; __HAL_RCC_TIM1_CLK_ENABLE(); htim1.Instance = TIM1; htim1.Init.Prescaler = 7999; htim1.Init.CounterMode = TIM_COUNTERMODE_UP; htim1.Init.Period = 999; htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; if (HAL_TIM_Base_Init(&htim1) != HAL_OK) { Error_Handler(); } } ``` 上述代码设置了预分频器和周期值以控制 LED 的闪烁频率[^1]。 #### 开启定时器并使能中断 接下来,在 `main()` 或者其他适当的位置启动定时器并启用其中断功能: ```c int main(void) { /* MCU Configuration */ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_TIM1_Init(); // 启动定时器并使能中断 HAL_TIM_Base_Start_IT(&htim1); while (1) { // 主循环体可以为空或加入其他处理逻辑 } } ``` 这段代码展示了如何在主函数中调用 `HAL_TIM_Base_Start_IT` 来激活定时器及其关联的中断服务程序。 #### 实现回调函数 当发生定时事件时会触发相应的 ISR(Interrupt Service Routine),对于 HAL 而言,则需定义特定于该外设实例的回调方法: ```c /* USER CODE BEGIN Private_Functions */ /** * @brief Timer callback function. * This will be called when timer interrupt occurs. */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { static uint8_t state = 0; if(htim->Instance==TIM1){ GPIO_PinState pin_state = (state++) % 2 ? GPIO_PIN_SET : GPIO_PIN_RESET; HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, pin_state); } } /* USER CODE END Private_Functions */ ``` 这里实现了 `HAL_TIM_PeriodElapsedCallback` 回调函数用于切换连接到 PA5 引脚上的 LED 状态。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值