STM32除TIM6和TIM7外都可以产生PWM输出。高级定时器TIM1和TIM8可以同时产生7路PWM,通用定时器可以产生4路PWM输出。
1.TIM1 CH1输出PWM配置步骤
①开启TIM1时钟,配置PA8为复用输出
APB2外设时钟使能寄存器(RCC_APB2ENR)
APB1外设复位寄存器 (RCC_APB1RSTR)
置1开启。清0关闭。
Eg:RCC->APB2ENR|=1<<11; //使能TIM1时钟
配置I/O口: 参见stm32寄存器版学习笔记01 GPIO口的配置。
Eg:GPIOA->CRH&=0XFFFFFFF0; //PA8清除之前的设置
GPIOA->CRH|=0X0000000B; //PA8复用功能输出
②设置TIM1的ARR和PSC
自动重装载寄存器(TIMx_ARR)
TIM1和TIM8预分频器(TIMx_PSC)
③设置TIM1_CH1的PWM模式及通道方向
TIM1和TIM8捕获/比较模式寄存器1(TIMx_CCMR1)
输出比较模式
Eg:TIM1->CCMR1|= 7<<4; //CH1 PWM2模式
TIM1->CCMR1|= 1<<3; //CH1预装载使能
CH1为输出,CC1S[1:0] 默认为00.
④使能TIM1的CH1输出,使能TIM1
设置TIM1_CCER来开启TIM1的通道1的输出。设置TIM1_CR1来开启TIM1的时钟。
TIM1和TIM8捕获/比较使能寄存器(TIMx_CCER)
Eg:TIM1->CCER|= 1<<3; //OC1输出使能
TIM1和TIM8控制寄存器1(TIMx_CR1)
ARPE:自动重装载预装载允许位 0:TIMx_ARR寄存器没有缓冲; 1:TIMx_ARR寄存器被装入缓冲器。
CEN:使能计数器 位0 0:禁止计数器; 1:使能计数器。
Eg:TIM1->CR1=0x0080; //ARPE使能
TIM1->CR1|=0X01; //使能定时器1
⑤设置MOE输出,使能PWM输出
普通定时器在完成以上设置后可以输出PWM,但高级定时器要使能刹车和死区寄存器。
TIM1和TIM8刹车和死区寄存器(TIMx_BDTR)
Eg:TIM1->BDTR|=1<<15; //MOE主输出使能
⑥修改TIM1_CCR1来控制占空比
Eg:#define PWM_VAL TIM1->CCR1 (可以直接设置)
2.TIMx复用功能重印象
……
3.高级定时器TIM1输出PWM应用
1 //timer.c 2 //TIM1_CH1 PWM输出初始化 3 //arr:自动重装值 4 //psc:时钟预分频数 5 void TIM1_PWM_Init(u16 arr,u16 psc) 6 { 7 //此部分需手动修改IO口设置 8 RCC->APB2ENR|=1<<11; //TIM1时钟使能 9 GPIOA->CRH&=0XFFFFFFF0; //PA8清除之前的设置 10 GPIOA->CRH|=0X0000000B; //复用功能输出 11 12 TIM1->ARR=arr; //设定计数器自动重装值 13 TIM1->PSC=psc; //预分频器设置 14 15 TIM1->CCMR1|=7<<4; //CH1 PWM2模式 16 TIM1->CCMR1|=1<<3; //CH1预装载使能 17 TIM1->CCER|=1<<0; //OC1 输出使能 18 TIM1->BDTR|=1<<15; //MOE 主输出使能 19 20 TIM1->CR1=0x0080; //ARPE使能 21 TIM1->CR1|=0x01; //使能定时器1 22 }
1 //timer.h 2 #ifndef __TIMER_H 3 #define __TIMER_H 4 #include "sys.h" 5 //通过改变TIM1->CCR1的值来改变占空比,从而控制LED0的亮度 6 #define LED0_PWM_VAL TIM1->CCR1 7 8 void TIM1_PWM_Init(u16 arr,u16 psc); 9 #endif
4.普通定时器TIM2输出2路PWM 应用
1 //TIM2_CH3~4 PWM输出初始化 2 //arr:自动重装值 3 //psc:时钟预分频数 4 void TIM2_PWM_Init(u16 arr,u16 psc) 5 { 6 //此部分需手动修改IO口设置 7 RCC->APB1ENR|=1<<0; //TIM2时钟使能 8 GPIOA->CRL&=0XFFFF00FF; //PA2-3清除之前的设置 9 GPIOA->CRL|=0X0000BB00; //复用功能输出 10 11 TIM2->ARR=arr; //设定计数器自动重装值 12 TIM2->PSC=psc; //预分频器设置 13 14 15 TIM2->CCMR2|=7<<4; //CH3 PWM2模式(输出) 16 TIM2->CCMR2|=1<<3; //CH3预装载使能 17 TIM2->CCER|=1<<8; //OC3 输出使能 18 19 TIM2->CCMR2|=7<<12; //CH4 PWM2模式(输出) 20 TIM2->CCMR2|=1<<11; //CH4预装载使能 21 TIM2->CCER|=1<<12; //OC4 输出使能 22 23 TIM2->CR1=0x0080; //ARPE使能 24 TIM2->CR1|=0x01; //使能定时器2 25 } 26 27 28 //设定占空比 duty<899 29 //设置多少就是多少低的 30 void pwm_duty1(u16 duty) 31 { 32 33 TIM2->CCR3=duty; 34 } 35 36 void pwm_duty2(u16 duty) 37 { 38 TIM2->CCR4=duty; 39 }
5.普通定时器TIM3输出2路PWM 应用
1 //timer.c 2 //TIM3_CH1~2 PWM输出初始化 3 //arr:自动重装值 4 //psc:时钟预分频数 5 void TIM3_PWM_Init(u16 arr,u16 psc) 6 { 7 //此部分需手动修改IO口设置 8 RCC->APB1ENR|=1<<1; //TIM3时钟使能 9 GPIOA->CRL&=0X00FFFFFF; //PA6-7清除之前的设置 10 GPIOA->CRL|=0XBB000000; //复用功能输出 11 12 TIM3->ARR=arr; //设定计数器自动重装值 13 TIM3->PSC=psc; //预分频器设置 14 15 TIM3->CCMR1|=7<<4; //CH1 PWM2模式(输出) 16 TIM3->CCMR1|=1<<3; //CH1预装载使能 17 TIM3->CCER|=1<<0; //OC1 输出使能 18 19 TIM3->CCMR1|=7<<12; //CH2 PWM2模式(输出) 20 TIM3->CCMR1|=1<<11; //CH2预装载使能 21 TIM3->CCER|=1<<4; //OC2 输出使能 22 23 TIM3->CR1=0x0080; //ARPE使能 24 TIM3->CR1|=0x01; //使能定时器3 25 } 26 void pwm_duty3(u16 duty) 27 { 28 29 PWM3_PWM_VAL=duty; 30 } 31 32 void pwm_duty4(u16 duty) 33 { 34 PWM4_PWM_VAL=duty; 35 } 36 37 //timer.h 38 #define PWM3_PWM_VAL TIM3->CCR1 39 #define PWM4_PWM_VAL TIM3->CCR2
切记在主函数前添加输出化函数!
Eg:TIM2_PWM_Init(899,0);//不分频。PWM频率=72000/(899+1)=80Khz