一、STM32F103 PWM介绍
STM32F1除了基本定时器TIM6和TIM7,其他定时器都可以产生PWM输出:其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出,而通用定时器也能同时产生多达 4路的 PWM 输出。
PWM的输出其实就是对外输出脉宽可调(即占空比调节)的方波信号,信号频率是由自动重装寄存器ARR的值决定,占空比由比较寄存器CCR的值决定。
PWM输出比较模式总共有8种,具体由寄存器 CCMRx 的位 OCxM[2:0]配置。这里只讲解最常用的两种PWM输出模式:PWM1和PWM2。PWM1和PWM2这两种模式用法差不多,区别之处就是输出电平的极性不同。
二、PWM输出配置步骤
(1)使能定时器及端口时钟,并设置引脚复用器映射
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //使能定时器时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //使能引脚复用时钟
GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE); //TIM3完全重映射
(2)初始化相应的GPIO,模式选复用推挽输出
(3)初始化定时器参数,包含自动重装值,分频系数,计数方式等
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct); //TIMx为对应的定时器,TIM_TimeBaseInitStruct为配置结构体
(4)初始化PWM输出参数,包含PWM模式、输出极性,使能等
void TIM_OCxInit(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct); //TIM_OCInitStruct为配置结构体
//TIM_OCInitTypeDef的部分成员
typedef struct{
uint16_t TIM_OCMode; //比较输出模式
uint16_t TIM_OutputState; //比较输出使能
uint16_t TIM_OCPolarity; //输出极性
}TIM_OCInitTypeDef;
TIM_OCMode | 描述 |
---|---|
TIM_OCMode_PWM1 | TIM脉宽宽度调制模式1 |
TIM_OCMode_PWM2 | TIM脉宽宽度调制模式2 |
TIM_OutputState | 比较输出使能/失能 |
---|---|
TIM_OutputState_Enable | 使能 |
TIM_OutputState_Disable | 失能 |
TIM_OCCPolarity | 输出极性 |
---|---|
TIM_OCPlarity_High | 高电平有效 |
TIM_OCPlarity_Low | 低电平有效 |
(5)开启定时器
TIM_Cmd(TIM3,ENABLE); //开启定时器
(6)使能TIMx在CCRx上的预装载寄存器
//第一个参数用于选择定时器,第二个参数用于选择使能还是失能输出比较预装载寄存器,可选择为TIM_OCPreload_Enable、TIM_OCPreload_Disable。
void TIM_OCxPreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
(7)使能 TIMx 在 ARR 上的预装载寄存器允许位
//第一个参数用于选择定时器,第二个参数用于选择使能还是失能。
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);
(8)修改TIMx_CCRx的值控制占空比
//第一个参数用于选择定时器,第二个参数用于控制占空比
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint32_t Compare1);
三、总结写法如下
/******************************
函数名:void TIM3_PWM_Init(u16 pre,u16 psc);
参数:pre为周期,psc为预分频
功能:使用通用定时器TIM3产生四路pwm,因使用完全重映射,故输出引脚分别为PC6、PC7、PC8、PC9
*******************************/
void TIM3_PWM_Init(u16 pre,u16 psc){
GPIO_InitTypeDef GPIO_initStructure; //GPIO配置结构体
TIM_TimeBaseInitTypeDef TIM_InitStructure; //定时器配置结构体
TIM_OCInitTypeDef TIM_OCInitTypeDefStructure; //PWM输出参数配置结构体
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //使能定时器时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //使能GPIOC时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); //使能复用功能时钟
GPIO_initStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;
GPIO_initStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_initStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&GPIO_initStructure); //初始化GPIO
GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE); //复用使能,完全重映射
TIM_InitStructure.TIM_Period = pre; //定时器周期
TIM_InitStructure.TIM_Prescaler = psc; //定时器预分频器
TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频
TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数模式
TIM_TimeBaseInit(TIM3,&TIM_InitStructure); //初始化TIM3
TIM_OCInitTypeDefStructure.TIM_OCMode = TIM_OCMode_PWM1; //PWM输出模式
TIM_OCInitTypeDefStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性,根据实际需要更改
TIM_OCInitTypeDefStructure.TIM_OutputState = TIM_OutputState_Enable; //使能比较输出
TIM_OC1Init(TIM3,&TIM_OCInitTypeDefStructure); //初始化通道1PWM输出
TIM_OC2Init(TIM3,&TIM_OCInitTypeDefStructure); //初始化通道2PWM输出
TIM_OC3Init(TIM3,&TIM_OCInitTypeDefStructure); //初始化通道3PWM输出
TIM_OC4Init(TIM3,&TIM_OCInitTypeDefStructure); //初始化通道4PWM输出
TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable); //使能TIM3在CCR1上的预装载寄存器
TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable); //使能TIM3在CCR2上的预装载寄存器
TIM_OC3PreloadConfig(TIM3,TIM_OCPreload_Enable); //使能TIM3在CCR3上的预装载寄存器
TIM_OC4PreloadConfig(TIM3,TIM_OCPreload_Enable); //使能TIM3在CCR4上的预装载寄存器
TIM_ARRPreloadConfig(TIM3,ENABLE); //使能 TIMx 在 ARR 上的预装载寄存器允许位
TIM_Cmd(TIM3,ENABLE); //开启定时器
}
//在main中调用函数修改占空比
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint32_t Compare1); //修改通道1占空比
void TIM_SetCompare2(TIM_TypeDef* TIMx, uint32_t Compare2); //修改通道2占空比
void TIM_SetCompare3(TIM_TypeDef* TIMx, uint32_t Compare3); //修改通道3占空比
void TIM_SetCompare4(TIM_TypeDef* TIMx, uint32_t Compare4); //修改通道4占空比
占空比计算: 占空比 = Compare1 / pre * 100%