PWM,中文释义:脉冲宽度调制。它是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。
PWM 是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。
STM32的定时器除了TIM6和7。其他的定时器都可以用来产生PWM输出。其中高级定时器TIM1和TIM8可以同时产生多达7路的PWM输出。而通用定时器也能同时产生多达4路的PWM输出,这样,STM32最多可以同时产生30路PWM输出!(在编程过程中的定时器重映像时涉及到)
STM32 的PWM是TIMx_ARR寄存器确定频率(周期)、由TIMx_CCRx寄存器确定占空比的信号。
PWM 模式
脉冲宽度调制模式可以产生一个由 TIM1_ARR 寄存器确定频率、由TIM1_CCRx寄存器确定占空比的信号。在 TIM1_CCMRx寄存器中的OCxM位写入“110”(PWM 模式 1)或“111”(PWM 模式 2),能够独立地设置每个通道工作在 PWM模式,每个 OCx 输出一路 PWM。必须通过设置 TIM1_CCMRx 寄存器 OCxPE 位使能相应的预装载寄存器,最后还要设置 TIM1_CR1 寄存器的 ARPE 位使能自动重装载的预装载寄存器(在向上计数或中心对称模式中)。
PWM 边沿对齐模式
向上计数配置 当 TIM1_CR1 寄存器中的 DIR 位为低的时候执行向上计数。 在 PWM 模式 1,当 TIM1_CNT<TIM1_CCRx 时 PWM 参考信号,OCxREF 为高,否则为低。如果 TIM1_CCRx中的比较值大于自动重装载值(TIM1_ARR),则 OCxREF 保持为“1"。如果比较值为 0,则 OCxREF 保持为“0"。 图 3-1 为 TIM1_ARR=8 时边沿对齐的 PWM 波形实例。
向下计数的配置 当 TIM1_CR1 寄存器的 DIR 位为高时执行向下计数。 在 PWM 模式 1,当 TIM1_CNT>TIM1_CCRx 时参考信号 OCxREF 为低,否则为高。如果 TIM1_CCRx 中的比较值大于 TIM1_ARR 中的自动重装载值,则 OCxREF保持为“1"。该模式下不能产生 0%的 PWM 波形。
PWM 中央对齐模式
当TIM1_CR1寄存器中的CMS位不为 00时为中央对齐模式(所有其他的配置对OCxREF/OCx信号都有相同的作用)。根据不同的CMS位的设置,比较标志可能 在计数器向上计数时被置 1、在计数器向下计数时被置 1、或在计数器向上和向下计数时被置 1。TIM1_CR1寄存器中的计数方向位(DIR)由硬件更新,不要用软件修改它。 图 3-2给出了一些中央对齐的PWM波形的例子 · TIM1_ARR=8 ; · PWM模式 1; · TIM1_CR1 寄存器中的 CMS=01,在中央对齐模式 1 时,当计数器向下计数时标志被设置。
测试用例:(PWM控制led亮度的渐变)
1 #include "pbdata.h" 2 #include "led.h" 3 #include "misc.h" 4 #include "stm32f10x_tim.h" 5 6 void RCC_Configration(void) 7 { 8 SystemInit(); 9 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); 10 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //定时器时钟使能 11 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //端口复用使能,因为要使用PWM 12 } 13 14 void GPIO_Configration(void) 15 { 16 GPIO_LED_Configration(); 17 } 18 19 void TIM_Configuration(void) 20 { 21 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 22 TIM_OCInitTypeDef TIM_OCInitStructure; 23 24 GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE); // 定时器管脚映射,部分重映像到PB5,PB5正好为接led的管脚(搜索“复用功能重映射”) 25 26 TIM_TimeBaseStructure.TIM_Period = 2000; //设置初始值,定时1s 27 TIM_TimeBaseStructure.TIM_Prescaler = 35999; //设置预分频 28 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //时钟分割 29 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数 30 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); 31 32 //pwm 初始化 33 TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; //设置为PWM模式1 34 TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable; // 输出使能????? 35 TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low; //设置输出极性 36 37 TIM_OC2Init(TIM3,&TIM_OCInitStructure); //选择定时器通道2 38 TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable); //预装载使能 39 TIM_Cmd(TIM3,ENABLE); //定时器外设打开 40 } 41 42 43 int main(void) 44 { 45 u8 led_fx = 1; 46 u16 led_dt = 0; 47 RCC_Configration(); 48 GPIO_Configration(); 49 TIM_Configuration(); 50 while(1) 51 { 52 // delay_ms(10); 53 if(led_fx==1) 54 { 55 led_dt++; 56 } 57 else 58 { 59 led_dt--; 60 } 61 if(led_dt>1000) led_fx=0; 62 if(led_dt==0) led_fx=1; 63 64 TIM_SetCompare2(TIM3,led_dt); 65 } 66 }
2014-08-26 01:17:28