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

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

一、定时器中断


 配置CubeMX工程:

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


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



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



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

 生成代码,在"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口复用功能:

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



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初始化的结构体定义为全局变量:

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逐渐变量变暗,达到了呼吸灯的效果。

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


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

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

HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2);

猜你喜欢

转载自blog.csdn.net/qq_37147721/article/details/79279015