STM32CubeMX与HAL库学习--基本定时器定时中断
背景
本人小白,最近在学着使用STM32CubeMX与HAL库进行开发,这是学习过程的一些记录。
STM32CubeMX版本:6.3.0
HAL:STM32CubeF4 Firmware Package V1.26.1
MDK:V5.32.0.0
开发板:野火的霸天虎V2(主控芯片是STM32F407ZG)
STM32CubeMX生成初始化代码
选择MCU型号,新建工程
配置时钟树,配置之前要在RCC的HSE那里选择外部谐振器作为时钟来源
GPIO设置,PA0和PC13是我之前实验外部中断的时候定义的。PF6和PF7连的LED灯,低电平灯亮。
TIM7设置
NVIC设置
选择IDE等选项,然后就可以生成代码了
在MDK-ARM里编辑代码
打开工程,打开stm32f4xx_it.c,找到void TIM7_IRQHandler(void),这是TIM7的中断处理函数,我添加了一行代码调用HAL_GPIO_TogglePin,用于反转控制LED的GPIO电平。
/**
* @brief This function handles TIM7 global interrupt.
*/
void TIM7_IRQHandler(void)
{
/* USER CODE BEGIN TIM7_IRQn 0 */
HAL_GPIO_TogglePin(LED_GREEN_GPIO_Port,LED_GREEN_Pin);
/* USER CODE END TIM7_IRQn 0 */
HAL_TIM_IRQHandler(&htim7);
/* USER CODE BEGIN TIM7_IRQn 1 */
/* USER CODE END TIM7_IRQn 1 */
}
然后编译、下载,发现程序一直在while循环无法进入定时器中断,进入调试,查看TIM7的寄存器,发现它开始计时的使能位CEN和更新中断使能都没有开,CubeMX初始化之后要用户自己开。
于是我在main函数里GPIO和TIM7初始化代码后面加了两行代码使能这两个位
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM7_Init();
/* USER CODE BEGIN 2 */
__HAL_TIM_ENABLE(&htim7);
__HAL_TIM_ENABLE_IT(&htim7, TIM_IT_UPDATE);
/* USER CODE END 2 */
这两个“函数”其实是宏,在stm32f4xx_hal_tim.h里面定义,内容如下:
/**
* @brief Enable the TIM peripheral.
* @param __HANDLE__ TIM handle
* @retval None
*/
#define __HAL_TIM_ENABLE(__HANDLE__) ((__HANDLE__)->Instance->CR1|=(TIM_CR1_CEN))
/** @brief Enable the specified TIM interrupt.
* @param __HANDLE__ specifies the TIM Handle.
* @param __INTERRUPT__ specifies the TIM interrupt source to enable.
* This parameter can be one of the following values:
* @arg TIM_IT_UPDATE: Update interrupt
* @arg TIM_IT_CC1: Capture/Compare 1 interrupt
* @arg TIM_IT_CC2: Capture/Compare 2 interrupt
* @arg TIM_IT_CC3: Capture/Compare 3 interrupt
* @arg TIM_IT_CC4: Capture/Compare 4 interrupt
* @arg TIM_IT_COM: Commutation interrupt
* @arg TIM_IT_TRIGGER: Trigger interrupt
* @arg TIM_IT_BREAK: Break interrupt
* @retval None
*/
#define __HAL_TIM_ENABLE_IT(__HANDLE__, __INTERRUPT__) ((__HANDLE__)->Instance->DIER |= (__INTERRUPT__))
然后LED灯就可以正常闪烁了。
其他
1、中断处理最好写在回调函数里面。
往往不止一种情况触发同一个中断,各个情况都有对应回调函数,库函数会去检查相关标志位并调用对应的回调函数,这样就不需要我们自己去检查中断标志来确定中断来源以及清除标志位,比如上面的中断程序可以写在void HAL_TIM_PeriodElapsedCallback里面。
库的回调函数都有__weak修饰,我们可以自己定义回调函数。
2、时钟与它的中断使能可以用函数HAL_TIM_Base_Start_IT()。(笑哭)