一、通用定时器
通用计数器可以实现输入捕获、输出捕获、定时器级联(一个定时器作为另一个定时器的预分频器)、中断等。
本实验通过输出捕获实现PWM波,PWM1与PWM2模式输出相反(本文以PWM1模式为例)。
二、PWM模式配置
本实验将PB5重映射为TIM3_CH2(IO复用)。
1、gtim.h文件
(1)初始化TIM3为向上计数模式
TIM_HandleTypeDef g_timx_pwm_chy_handle; /* 通用定时器PWM输出初始化函数 */ void gtim_timx_pwm_chy_init(uint16_t psc,uint16_t arr) { g_timx_pwm_chy_handle.Instance = TIM3; g_timx_pwm_chy_handle.Init.Prescaler = psc; g_timx_pwm_chy_handle.Init.Period = arr; g_timx_pwm_chy_handle.Init.CounterMode = TIM_COUNTERMODE_UP; /* 向上计数模式 */ }
(2)定时器输出PWM MSP初始化函数
/* 定时器输出PWM MSP初始化函数 */ /* 1、使能TIM时钟;2、使能IO时钟及引脚复用. */ void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim) { if(htim->Instance == TIM3) { GPIO_InitTypeDef g_init_struct; __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_TIM3_CLK_ENABLE(); g_init_struct.Pin = GPIO_PIN_5; g_init_struct.Mode = GPIO_MODE_AF_PP; /* 推挽复用功能 */ g_init_struct.Pull = GPIO_PULLUP; /* 上拉 */ g_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */ HAL_GPIO_Init(GPIOB, &g_init_struct); __HAL_RCC_AFIO_CLK_ENABLE(); /* 复用IO时钟使能 */ __HAL_AFIO_REMAP_TIM3_PARTIAL(); /* 部分复用使能 */ } }
__HAL_AFIO_REMAP_TIM3_PARTIAL(); /* 部分复用使能 */
(3)在(1)函数体中继续配置PWM模式、比较值(初始占空比)及极性,配置TIM3通道2,开启对应PWM通道。
void gtim_timx_pwm_chy_init(uint16_t psc,uint16_t arr) { TIM_OC_InitTypeDef timx_oc_pwm_chy; timx_oc_pwm_chy.OCMode = TIM_OCMODE_PWM1; /* 模式选择PWM1 */ timx_oc_pwm_chy.Pulse = arr / 2; /* 设置比较值CCRx,此值用来确定占空比 */ /* 这里默认设置比较值为自动重装载值的一半,即占空比为50% */ timx_oc_pwm_chy.OCPolarity = TIM_OCPOLARITY_LOW; /* 设定CCxP的值,低电平有效 */ HAL_TIM_PWM_ConfigChannel(&g_timx_pwm_chy_handle,&timx_oc_pwm_chy, TIM_CHANNEL_2); /* 配置TIM3通道2 */ HAL_TIM_PWM_Start(&g_timx_pwm_chy_handle, TIM_CHANNEL_2); /* 开启对应PWM通道 */ }
2、main.c文件
(1) __HAL_TIM_SET_COMPARE()修改比较值控制占空比。
#include "./SYSTEM/sys/sys.h" #include "./SYSTEM/usart/usart.h" #include "./SYSTEM/delay/delay.h" #include "./BSP/LED/led.h" #include "./BSP/KEY/key.h" #include "./BSP/TIMER/gtim.h" extern TIM_HandleTypeDef g_timx_pwm_chy_handle; int main(void) { uint32_t ledpwmval = 0; uint8_t dir = 1; HAL_Init(); /* 初始化HAL库 */ sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */ delay_init(72); /* 延时初始化 */ usart_init(115200); /* 初始化串口 */ gtim_timx_pwm_chy_init(72 - 1, 500 - 1); printf("程序开始: "); while(1) { delay_ms(10); /* 根据方向修改ledpwmval */ if (dir == 1) { ledpwmval++; } else { ledpwmval--; } /* 当ledpwmval大于500时,方向改为递减 */ if (ledpwmval > 500) { dir = 0; } /* 当ledpwmval等于0时,方向改为递增 */ if (ledpwmval == 0) { dir = 1; } /* 修改比较值控制占空比 */ __HAL_TIM_SET_COMPARE(&g_timx_pwm_chy_handle, TIM_CHANNEL_2, ledpwmval); } }
三、PWM为什么能控制led灯或者电机的速度?
原因是,PWM波形是具有一定占空比的矩形波,呈现高低电平交替的状态,频率较高,即波形周期较小。在高速变化过程中,led灯会呈现出一个平均亮度(人眼看出来的状态),通过不断改变PWM波的占空比,高低电平交替的速度会发生变化,此时这个平均亮度也会发生变化,故就可以通过改变PWM波的占空比以改变led灯的亮度,实现呼吸灯的效果。电机也相同,不再赘述。