【NUCLEO_F767ZI开发板系列】六、TIM1高级定时器——中断+PWM
程序员文章站
2022-03-13 19:25:53
...
定时器是一个十分通用的外设,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);