一、初始化TIM基本計數器參數函數
void MX_TIM2_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; htim2.Instance = TIM2; htim2.Init.Prescaler = 36000-1; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 2000-1; 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(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) { Error_Handler(); } }
二、HAL_TIM_Base_Init(&htim2)應用參數基本參數配置spa
HAL_StatusTypeDef HAL_TIM_Base_Init(TIM_HandleTypeDef *htim) { /* Check the TIM handle allocation */ if (htim == NULL) { return HAL_ERROR; } /* Check the parameters */ assert_param(IS_TIM_INSTANCE(htim->Instance)); assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode)); assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision)); assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload)); if (htim->State == HAL_TIM_STATE_RESET) { /* Allocate lock resource and initialize it */ htim->Lock = HAL_UNLOCKED; #if (USE_HAL_TIM_REGISTER_CALLBACKS == 1) /* Reset interrupt callbacks to legacy weak callbacks */ TIM_ResetCallback(htim); if (htim->Base_MspInitCallback == NULL) { htim->Base_MspInitCallback = HAL_TIM_Base_MspInit; } /* Init the low level hardware : GPIO, CLOCK, NVIC */ htim->Base_MspInitCallback(htim); #else /* Init the low level hardware : GPIO, CLOCK, NVIC */ HAL_TIM_Base_MspInit(htim); #endif /* USE_HAL_TIM_REGISTER_CALLBACKS */ } /* Set the TIM state */ htim->State = HAL_TIM_STATE_BUSY; /* Set the Time Base configuration */ TIM_Base_SetConfig(htim->Instance, &htim->Init); /* Initialize the TIM state*/ htim->State = HAL_TIM_STATE_READY; return HAL_OK; }
三、HAL_TIM_Base_MspInit(htim) 初始化中斷信息(該函數須要重寫,CubeMX在配置生成代碼時會自動重寫該函數)調試
/** * @brief Initializes the TIM Base MSP. * @param htim TIM Base handle * @retval None */ __weak void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim) { /* Prevent unused argument(s) compilation warning */ UNUSED(htim); /* NOTE : This function should not be modified, when the callback is needed, the HAL_TIM_Base_MspInit could be implemented in the user file */ }
重寫實現code
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle) { if(tim_baseHandle->Instance==TIM2) { /* USER CODE BEGIN TIM2_MspInit 0 */ /* USER CODE END TIM2_MspInit 0 */ /* TIM2 clock enable */ __HAL_RCC_TIM2_CLK_ENABLE(); /* TIM2 interrupt Init */ HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0); HAL_NVIC_EnableIRQ(TIM2_IRQn); /* USER CODE BEGIN TIM2_MspInit 1 */ /* USER CODE END TIM2_MspInit 1 */ } }
四、使能TIM中斷blog
雖然通過以上配置,TIM的參數信息都已完整應用,可是TIM的中斷並沒用真正使能.這個地方困擾了我很久(運行沒錯誤,可是計數中斷就不觸發, 不計數),必需調用如下函數使能中斷,串口中斷使能也是相似的.回調函數
HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *TIM);//開啓定時器中斷requests
該函數的調用地點只要是在 HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle) 函數以後就行,能夠在main.c中也能夠在上面的代碼以後.it
下面的代碼存在一個BUG,若是 HAL_TIM_Base_Start_IT 函數調用寫在下面的位置,雖然可使能中斷,但會形成MCU上電即觸發中斷的狀況.io
HAL_TIM_Base_MspInit調用以後會從新設置寄存器的值,__HAL_TIM_CLEAR_FLAG(tim_baseHandle, TIM_SR_UIF)清理的寄存器被改寫.event
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle) { if(tim_baseHandle->Instance==TIM2) { /* USER CODE BEGIN TIM2_MspInit 0 */ /* USER CODE END TIM2_MspInit 0 */ /* TIM2 clock enable */ __HAL_RCC_TIM2_CLK_ENABLE(); /* TIM2 interrupt Init */ HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0); HAL_NVIC_EnableIRQ(TIM2_IRQn); /* USER CODE BEGIN TIM2_MspInit 1 */ //清理TIM開啓時的中斷標識 __HAL_TIM_CLEAR_FLAG(tim_baseHandle, TIM_SR_UIF);//添加這條語句解決問題 //htim2.Instance->SR = 0; //這是另外一種解決辦法 //使能TIM中斷 HAL_TIM_Base_Start_IT(tim_baseHandle); /* USER CODE END TIM2_MspInit 1 */ } }
正確的作法是在 HAL_TIM_Base_Init(&htim2) 以後使能TIM中斷,並清理TIM的更新中斷寄存器
void MX_TIM2_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; htim2.Instance = TIM2; htim2.Init.Prescaler = 36000-1; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 10000-1; 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(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) { Error_Handler(); } //清理TIM開啓時的中斷標識 __HAL_TIM_CLEAR_IT(&htim2, TIM_IT_UPDATE); //使能TIM中斷 HAL_TIM_Base_Start_IT(&htim2); }
五、計數中斷處理
/** * @brief This function handles TIM2 global interrupt. */ void TIM2_IRQHandler(void) { /* USER CODE BEGIN TIM2_IRQn 0 */ /* USER CODE END TIM2_IRQn 0 */ HAL_TIM_IRQHandler(&htim2); /* USER CODE BEGIN TIM2_IRQn 1 */ /* USER CODE END TIM2_IRQn 1 */ }
HAL_TIM_IRQHandler(&htim2)中斷函數處理
/** * @brief This function handles TIM interrupts requests. * @param htim TIM handle * @retval None */ void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim) { /* Capture compare 1 event */ if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_CC1) != RESET) { if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_CC1) != RESET) { { __HAL_TIM_CLEAR_IT(htim, TIM_IT_CC1); htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1; /* Input capture event */ if ((htim->Instance->CCMR1 & TIM_CCMR1_CC1S) != 0x00U) { #if (USE_HAL_TIM_REGISTER_CALLBACKS == 1) htim->IC_CaptureCallback(htim); #else HAL_TIM_IC_CaptureCallback(htim); #endif /* USE_HAL_TIM_REGISTER_CALLBACKS */ } /* Output compare event */ else { #if (USE_HAL_TIM_REGISTER_CALLBACKS == 1) htim->OC_DelayElapsedCallback(htim); htim->PWM_PulseFinishedCallback(htim); #else HAL_TIM_OC_DelayElapsedCallback(htim); HAL_TIM_PWM_PulseFinishedCallback(htim); #endif /* USE_HAL_TIM_REGISTER_CALLBACKS */ } htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED; } } } ........................ ........................ /* TIM Update event */ if (__HAL_TIM_GET_FLAG(htim, TIM_FLAG_UPDATE) != RESET) { if (__HAL_TIM_GET_IT_SOURCE(htim, TIM_IT_UPDATE) != RESET) { __HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE); #if (USE_HAL_TIM_REGISTER_CALLBACKS == 1) htim->PeriodElapsedCallback(htim); #else HAL_TIM_PeriodElapsedCallback(htim); #endif /* USE_HAL_TIM_REGISTER_CALLBACKS */ } } ........................ ........................ }
HAL_TIM_PeriodElapsedCallback(htim);當計數溢出時調用的回調函數,須要用戶根據實際需求具體實現
/** * @brief Period elapsed callback in non-blocking mode * @param htim TIM handle * @retval None */ __weak void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { /* Prevent unused argument(s) compilation warning */ UNUSED(htim); /* NOTE : This function should not be modified, when the callback is needed, the HAL_TIM_PeriodElapsedCallback could be implemented in the user file */ }
六、實現計數完成回調函數,調試代碼,查看計數器中斷效果.