1通用PWM波输出原理
总结:PWM波周期或频率由ARR决定,PWM波占空比由CCRx决定
1通用PWM模式
1.1PWM模式1
PWM模式1:
递增:CNT < CCRx,输出有效电平1
CNT >= CCRx,输出无效电平0
递减:CNT > CCRx, 输出无效电平0
CNT <= CCRx,输出有效电频1
1.2PWM模式2
PWM模式2:
递增:CNT < CCRx,输出无效电平
CNT >= CCRx,输出有效电平
递减:CNT > CCRx,输出有效电平
CNT <= CCRx,输出无效电平
注意:
有/无效状态由TIMx_CCER决定
CCxP=0:OCx高电平有效
CCxP=1:Ocx低电平有效
2 定时器PWM输出比较结构体
typedef struct
{
uint32_t OCMode; /* 输出比较模式选择 /
uint32_t Pulse; / 设置比较值 /
uint32_t OCPolarity; / 设置输出比较极性 /
uint32_t OCNPolarity; / 设置互补输出比较极性 /
uint32_t OCFastMode; / 使能或失能输出比较快速模式 /
uint32_t OCIdleState; / 空闲状态下OC1输出 /
uint32_t OCNIdleState; / 空闲状态下OC1N输出 */
} TIM_OC_InitTypeDef;
2 PWM波周期与频率计算
3 通用定时器PWM波输出实验配置步骤
1,配置定时器基础工作参数 HAL_TIM_PWM_Init()
2,定时器PWM输出MSP初始化 HAL_TIM_PWM_MspInit() 配置NVIC、CLOCK、GPIO等
3,配置PWM模式/比较值等 HAL_TIM_PWM_ConfigChannel()
4,使能输出并启动计数器 HAL_TIM_PWM_Start()
5,修改比较值控制占空比(可选) __HAL_TIM_SET_COMPARE()
6,使能通道预装载(可选) __HAL_TIM_ENABLE_OCxPRELOAD()
4 通用定时器PWM波输出编程实战
目的:输出PWM波占空比为50%
4 .1gtim.c
#include "./BSP/TIMER/gtim.h"
#include "./BSP/LED/led.h"
//1.声明定时器句柄
TIM_HandleTypeDef g_timx_pwm_handler;
/**
* @brief 通用定时器TIMX 通道Y PWM输出 初始化函数(使用PWM模式1)
* @note
* 通用定时器的时钟来自APB1,当PPRE1 ≥ 2分频的时候
* 通用定时器的时钟为APB1时钟的2倍, 而APB1为42M, 所以定时器时钟 = 84Mhz
* 定时器溢出时间计算方法: Tout = ((arr + 1) * (psc + 1)) / Ft us.
* Ft = 定时器工作频率,单位:Mhz
*
* @param arr: 自动重装值
* @param psc: 预分频系数
* @retval 无
*/
//2.配置通用定时器基本工作参数,PWM输出初始化
void gtim_timx_pwm_chy_init(uint16_t arr, uint16_t psc) /* 通用定时器 PWM初始化函数 */
{
//4.1定时器输出比较定时器结构体初始化
TIM_OC_InitTypeDef tim_oc_pwm_chy = {0};
//2.1通用定时器PWM输出初始化
g_timx_pwm_handler.Instance = GTIM_TIMX_PWM;
g_timx_pwm_handler.Init.Period = arr;
g_timx_pwm_handler.Init.Prescaler = psc;
g_timx_pwm_handler.Init.CounterMode = TIM_COUNTERMODE_UP;
HAL_TIM_PWM_Init(&g_timx_pwm_handler);
//4.配置PWM模式和比较值
tim_oc_pwm_chy.OCMode = TIM_OCMODE_PWM1; //输出比较模式 PWM1
tim_oc_pwm_chy.Pulse = arr/2; //设置比较值为自动加载值的一般,则占空比为50%
tim_oc_pwm_chy.OCPolarity = TIM_OCPOLARITY_LOW; //设置输出比较的极性为低
HAL_TIM_PWM_ConfigChannel(&g_timx_pwm_handler,&tim_oc_pwm_chy,GTIM_TIMX_PWM_CHY);
//5,使能输出并启动计时器
HAL_TIM_PWM_Start(&g_timx_pwm_handler,GTIM_TIMX_PWM_CHY);
}
//3.定时器PWM输出底层初始化,定时器时钟、引脚时钟使能,引脚复用配置
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef * htm)
{
//3.1判断是否是TIM14
if(htm->Instance == GTIM_TIMX_PWM)
{
GPIO_InitTypeDef gpio_init_struct;
//3.3使能定时器时钟
GTIM_TIMX_PWM_CHY_CLK_ENABLE();
//3.4使能PF引脚口时钟
GTIM_TIMX_PWM_CHY_GPIO_CLK_ENABLE();
//3.2通道y的GPIO初始化
gpio_init_struct.Pin = GTIM_TIMX_PWM_CHY_GPIO_PIN; /* LED0引脚 */
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
gpio_init_struct.Alternate = GPIO_AF9_TIM14; /* 端口复用到TIM14 */
HAL_GPIO_Init(LED0_GPIO_PORT, &gpio_init_struct); /* 初始化LED0引脚 */
}
}
4 .2 gtim.c
#ifndef __GTIM_H
#define __GTIM_H
#include "./SYSTEM/sys/sys.h"
/* TIMX PWM输出定义
* 这里输出的PWM控制LED0(RED)的亮度
* 默认是针对TIM2~TIM5
* 注意: 通过修改这几个宏定义,可以支持TIM1~TIM8任意一个定时器,任意一个IO口输出PWM
*/
#define GTIM_TIMX_PWM_CHY_GPIO_PORT GPIOF
#define GTIM_TIMX_PWM_CHY_GPIO_PIN GPIO_PIN_9
#define GTIM_TIMX_PWM_CHY_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOF_CLK_ENABLE(); }while(0) /* PF口时钟使能 */
#define GTIM_TIMX_PWM_CHY_GPIO_AF GPIO_AF9_TIM14 /* 端口复用到TIM14 */
/* TIMX REMAP设置
* 因为我们LED0接在PF9上, 必须通过开启TIM14的部分重映射功能, 才能将TIM14_CH1输出到PF9上
*/
#define GTIM_TIMX_PWM TIM14 /* TIM14 */
#define GTIM_TIMX_PWM_CHY TIM_CHANNEL_1 /* 通道Y, 1<= Y <=4 */
#define GTIM_TIMX_PWM_CHY_CCRX TIM14->CCR1 /* 通道Y的输出比较寄存器 */
#define GTIM_TIMX_PWM_CHY_CLK_ENABLE() do{ __HAL_RCC_TIM14_CLK_ENABLE(); }while(0) /* TIM14 时钟使能 */
void gtim_timx_pwm_chy_init(uint16_t arr, uint16_t psc); /* 通用定时器 PWM初始化函数 */
#endif