一、简介
脉冲宽度调制(PWM),是英文“Pulse Width Modulation” 的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单来说,就是对脉冲宽度的控制。
STM32 的定时器除了 TIM6 和 7。其他的定时器都可以用来产生 PWM 输出。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出。而通用定时器也能同时产生多达 4路的 PWM 输出,这样, STM32 最多可以同时产生 30 路 PWM 输出。
二、配置
1、过程讲解
-
1 )相关寄存器: 捕获 /比较模式寄存器(TIMx_CCMR1/2)、捕获/比较使能寄存器(TIMx_CCER)、捕获/比较寄存器(TIMx_CCR1~4)
-
捕获 /比较模式寄存器(TIMx_CCMR1/2):CCMR1寄存器是控制CH1、CH2两个通道,CCMR2是控制CH3、CH4两个通道。寄存器的相关位可以参考《STM32中文参考手册》
-
捕获/比较使能寄存器(TIMx_CCER):该寄存器控制着各个输入输出通道的开关,使能的话对应位设置位1就好
-
捕获/比较寄存器(TIMx_CCR1~4):这个寄存器控制的是通道1~4的比较值,通过与计数器的CNT值进行比较,然后控制PWM波的脉冲宽度
-
2)写法:
1、使能相应的时钟
RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
2、配置引脚(如果是需要重映射就得相应配置)
GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
重映射:GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);
3、初始化定时器
TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
4、设置pwm输出并使能相应的通道
TIM_OC2Init(TIM_TypeDef* TIMx,TIM_OCInitTypeDef* TIM_OCInitStruct);//这里是通道2`
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);//使能预装载值
typedef struct
{
uint16_t TIM_OCMode;//输出模式
uint16_t TIM_OutputState;//使能 PWM 输出到端口
uint16_t TIM_OutputNState; //相应互补通道使能端
uint16_t TIM_Pulse;//比较值
uint16_t TIM_OCPolarity;//设置极性是高还是低
uint16_t TIM_OCNPolarity;//相应互补输出端的极性设置
uint16_t TIM_OCIdleState;
uint16_t TIM_OCNIdleState;
} TIM_OCInitTypeDef; //结构体里带有 N的是互补输出才能用到,stm32只有高级定时器才有互补输出
高级定时器必须加上下面这句:
TIM_CtrlPWMOutputs(TIM1, ENABLE);//TIM1举例
5、使能TIM
TIM_Cmd(TIM3, ENABLE);//这里是TIM3,放在最后可保证在参数设置完成之后定时器开始计数
三、代码
void PWM_Init(void)//TIM1_OC2互补输出: PA9 PB14
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 , ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
/* GPIOA Configuration: Channel 1, 2 and 3 as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* GPIOB Configuration: Channel 1N, 2N and 3N as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_Init(GPIOB, &GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = 999;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/* Channel 1, 2,3 and 4 Configuration in PWM mode */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_Pulse = 200;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器
TIM_OC2Init(TIM1, &TIM_OCInitStructure);
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
/* TIM1 counter enable */
TIM_Cmd(TIM1, ENABLE);
/* TIM1 Main Output Enable */
TIM_CtrlPWMOutputs(TIM1, ENABLE);
// 在运行当中想要改变pwm的频率和占空比调用:
// TIM_SetAutoreload(TIM1,1000); //设置重装载值,重新设置周期
// TIM_SetCompare2(TIM1,500);
}
续、、、、、、
网友评论