【NUCLEO_F767ZI开发板系列】六、TIM1高级定时器——中断+PWM

时间:2021-09-29 04:19:55

 定时器是一个十分通用的外设,STM32F767的定时器有十几个,包含了基本定时器、通用定时器、高级定时器和低功耗定时器。

一、定时器中断


 配置CubeMX工程:

 1、选择Clock Source里的Internal Clock(内部时钟) 另外一个ETR2是外部触发输入 。

【NUCLEO_F767ZI开发板系列】六、TIM1高级定时器——中断+PWM


2、接着在TIM3 配置页弹出的界面中点击 Parameter Settings 选项卡,Counter Settings配置栏下面的四个选项用来配置定时器的预分频系数,自动装载值,计数模式以及时钟分频因子。TIM1挂载到APB1的时钟总线上,频率为108MHz,所以这里设置成1s。

【NUCLEO_F767ZI开发板系列】六、TIM1高级定时器——中断+PWM


3、接着再使能定时器更新中断

【NUCLEO_F767ZI开发板系列】六、TIM1高级定时器——中断+PWM


4、再到NVIC的选项卡里设置中断优先级分组:

【NUCLEO_F767ZI开发板系列】六、TIM1高级定时器——中断+PWM

 生成代码,在"tim.c"里定时器1的初始化函数:

TIM_HandleTypeDef htim1;

/* TIM1 init function */
void MX_TIM1_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;

htim1.Instance = TIM1;
htim1.Init.Prescaler = 10800-1;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 10000-1;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
5、在主循环之前添加代码,开启定时器和定时器中断:

	HAL_TIM_Base_Start_IT(&htim1);
6、在主函数后面的用户代码区写定时器溢出回调函数:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
}
编译下载到开发板就可以看到LED1以一定的频率闪烁了。

二、PWM输出


使用TIM1的CH2_N来输出PWM信号,来控制LED3的亮灭,TIM1的CH2_N在PB14口上,

1、设置IO口复用功能:

【NUCLEO_F767ZI开发板系列】六、TIM1高级定时器——中断+PWM【NUCLEO_F767ZI开发板系列】六、TIM1高级定时器——中断+PWM

2、修改预分频系数和时钟分频因子使输出的频率为1KHz,

【NUCLEO_F767ZI开发板系列】六、TIM1高级定时器——中断+PWM

【NUCLEO_F767ZI开发板系列】六、TIM1高级定时器——中断+PWM

3、关闭定时器中断使能。生成代码

 在定时器初始化的函数中,PWM的初始化部分:

  sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 5400;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
4、为了方便后续程序里修改占空比,将pwm初始化的结构体定义为全局变量:

【NUCLEO_F767ZI开发板系列】六、TIM1高级定时器——中断+PWM

5、在"tim.c"后面的用户代码区添加修改占空比的函数并且在  tim.h  文件里声明:

/* USER CODE BEGIN 1 */

void PWM_Pulse_Change(uint16_t num)
{
sConfigOC.Pulse = num;
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

//开启高级定时器PWM开始函数
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2);
}

/* USER CODE END 1 */
这里需要注意的是:

HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2);
这里使用的是通道Channel 2N 。开启这个通道的pwm生成的函数在“stm32f7xx_hal_tim_ex.c”文件中定义的。

6、在 main.c 文件里添加变量:

  /* USER CODE BEGIN 1 */

uint16_t pwm=0; //修改的PWM的值
int step; //控制pwm增或减

/* USER CODE END 1 */
7、主循环前添加:

  /* USER CODE BEGIN 2 */

printf("Hello,Nucleo!\n"); //打印提示信息
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2); //初始化pwm通道CH2N

/* USER CODE END 2 */
8、主循环内添加:

		HAL_Delay(30);  
if(pwm == 0) step = 100;
if(pwm == 10000) step = -100;
pwm += step;
PWM_Pulse_Change(pwm);
编译下载到开发板里,可以看到红色的led3逐渐变量变暗,达到了呼吸灯的效果。

以往经常使用的通用定时器,配制方法虽然差别不大,但是一些功能还是有些差别,比一般定时器功能更加强大:

【NUCLEO_F767ZI开发板系列】六、TIM1高级定时器——中断+PWM

PWM实验里开启Channel 2N通道,最初就被配置成了:

	HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
结果LED灯怎么也不亮。上网查找资料也找不到,最终还是去看官方的例程发现了这个函数:

HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2);