我的目标学习任务是使用STM32F429IG(挑战者)的基本定时器控制LED灯每隔0.5s闪烁一次。
首先我使用了CUBEMX工具进行基础部分配置,配置SYS,Debug为serial wire,RCC的HSE选择crystal/ceramic resonator。
一、设置clock configuration
使用HSE,PLLCLK,将HCLK设置为168,回车使CUBEMX自动生成配置
二、选择闪烁的LED
根据挑战者电路原理图,选择绿灯闪烁,绿灯为PH11,即GPIOH,GPIO_PIN_11,在CUBEMX上选择PH11引脚设置为OUTPUT模式
三、配置TIM
此实验选择TIM7基本定时器,我们知道定时事件生成时间主要由TIMx_PSC和TIMx_ARR两个寄存器值决定,这个也就是定时器的周期。比如我们需要一个1s周期的定时器,具体这两个寄存器值该如何设置内。假设,我们先设置TIMx_ARR寄存器值为9999,即当TIMx_CNT从0开始计算,刚好等于9999时生成事件,总共计数10000次,那么如果此时时钟源周期为100us即可得到刚好1s的定时周期。
接下来问题就是设置TIMx_PSC寄存器值使得CK_CNT输出为100us周期(10000Hz)的时钟。预分频器的输入时钟CK_PSC为84MHz,所以设置预分频器值为(8400-1)即可满足。
每0.5s闪烁一次,将counter period设置为5000-1.
开启NVIC。
然后生成代码
四、打开keil进行编程
在tim.c里面需加入初始化定时器并开启定时器更新中断语句:
HAL_TIM_Base_Init(&htim7);
HAL_TIM_Base_Start_IT(&htim7);
在tim.c里面加入翻转代码使LED灯实现电平翻转,即:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){HAL_GPIO_TogglePin(GPIOH,GPIO_PIN_11);}
tim.c完整代码:
#include "tim.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
TIM_HandleTypeDef htim7;
/* TIM7 init function */
void MX_TIM7_Init(void)
{/* USER CODE BEGIN TIM7_Init 0 *//* USER CODE END TIM7_Init 0 */TIM_MasterConfigTypeDef sMasterConfig = {0};/* USER CODE BEGIN TIM7_Init 1 *//* USER CODE END TIM7_Init 1 */htim7.Instance = TIM7;htim7.Init.Prescaler = 8400-1;htim7.Init.CounterMode = TIM_COUNTERMODE_UP;htim7.Init.Period = 5000-1;htim7.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;if (HAL_TIM_Base_Init(&htim7) != HAL_OK){Error_Handler();}sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;if (HAL_TIMEx_MasterConfigSynchronization(&htim7, &sMasterConfig) != HAL_OK){Error_Handler();}/* USER CODE BEGIN TIM7_Init 2 */
HAL_TIM_Base_Init(&htim7);
HAL_TIM_Base_Start_IT(&htim7);/* USER CODE END TIM7_Init 2 */
}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{if(tim_baseHandle->Instance==TIM7){/* USER CODE BEGIN TIM7_MspInit 0 *//* USER CODE END TIM7_MspInit 0 *//* TIM7 clock enable */__HAL_RCC_TIM7_CLK_ENABLE();/* TIM7 interrupt Init */HAL_NVIC_SetPriority(TIM7_IRQn, 0, 0);HAL_NVIC_EnableIRQ(TIM7_IRQn);/* USER CODE BEGIN TIM7_MspInit 1 *//* USER CODE END TIM7_MspInit 1 */}
}
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
{if(tim_baseHandle->Instance==TIM7){/* USER CODE BEGIN TIM7_MspDeInit 0 *//* USER CODE END TIM7_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_TIM7_CLK_DISABLE();/* TIM7 interrupt Deinit */HAL_NVIC_DisableIRQ(TIM7_IRQn);/* USER CODE BEGIN TIM7_MspDeInit 1 *//* USER CODE END TIM7_MspDeInit 1 */}
}
/* USER CODE BEGIN 1 */void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){HAL_GPIO_TogglePin(GPIOH,GPIO_PIN_11);}
/* USER CODE END 1 */
五.bug反思
连续调用了两次TIM的配置函数(如下),在main函数里面调用了一次,又在子函数tim.c里面调用了一次,导致重复调用
HAL_TIM_Base_Init(&htim7);
HAL_TIM_Base_Start_IT(&htim7);
调用的函数位置颠倒,应该先调用初始化定时器语句,再进行开启定时器更新中断语句,但是我抄的时候没注意位置,导致keil没有报错,但是没有led翻转现象。