http://www.eemaker.com/stm32-180dupwm.html
Stm32产生两路相位差为180度的pwm
By derrick wang
由于上次用高级定时器产生的两路互补带死区的pwm 信号不能满足应用需求。如标题所示需要的是两路相位差为180度的pwm 信号,占空比和频率都是相同的,只是相位不同。仔细重读高级定时器的数据手册,发现产生的两路互补信号达不到这个要求。然后必然要考虑用两个通道产生了(两路互补属于一个通道)。仔细搜罗最终确定了两种发案可以实现,这两种方式具有异曲同工之妙但也有各自的不同。相同之处在于同采用定时器计数的中央对齐模式,不同就在于输出选择的模式不同(对TIM_CCMRX寄存器中OCXM位进行配置)。 下面待我一一详解。生成的波形图如下:
方案一:定时器计数采用中央对齐模式,两路输出配置为pwm 的输出比较模式。 1)配置定时器的计数器为中间对齐计数,即先向上计数再向下计数。 2)在该定时器上选择2个通道,并分别配置为输出比较模式,要输出如上图波形须把两路输出极性设置为不同。
3)配置自动重装载寄存器TIMx_ARR为要求输出频率的一半。 4)假定CC1为第一个输出信号的通道,再假定第一个信号的正脉冲宽度对应为W1,则配置TIMx_CCR1为TIMx_ARR-W1/2。 5) 同4),假定CC2为第二个输出信号的通道,正脉冲宽度对应为W2,配置TIMx_CCR2为W2/2。
下面我要产生频率为50khz,占空比为20%的两路pwm 信号。TIMx_ARR=72000/50/2=720;
TIMx_CCR1=720-720*0.2=576;TIMx_CCR2=720*0.2=144;
为什么这样算请看下图:
①和②对应得值就是576. ③和④对应得值就是144。但是他们之间的距离是相等的,也就保证了两路pwm产生的占空比是一样的。
具体配置代码如下所示:
GPIO_InitTypeDef GPIO_InitStructure2 ; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure ; TIM_OCInitTypeDef TIM_OCInitStructure ; RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOA , ENABLE ); RCC_APB1PeriphClockCmd ( RCC_APB1Periph_TIM3 , ENABLE ); /********TIM3_CH1 引脚配置*********/ GPIO_InitStructure2 . GPIO_Pin = GPIO_Pin_6 ; GPIO_InitStructure2 . GPIO_Speed = GPIO_Speed_50MHz ; GPIO_InitStructure2 . GPIO_Mode = GPIO_Mode_AF_PP ; //设置为复用浮空输出 GPIO_Init ( GPIOA ,& GPIO_InitStructure2 ); /********TIM3_CH2 引脚配置*********/ GPIO_InitStructure2 . GPIO_Pin = GPIO_Pin_7 ; GPIO_InitStructure2 . GPIO_Speed = GPIO_Speed_50MHz ; GPIO_InitStructure2 . GPIO_Mode = GPIO_Mode_AF_PP ; //设置为复用浮空输出 GPIO_Init ( GPIOA ,& GPIO_InitStructure2 ); /************定时器基本配置***************/ TIM_TimeBaseStructure . TIM_Period = 720 - 1 ; // 自动重装载寄存器的值 TIM_TimeBaseStructure . TIM_Prescaler = 0 ; // 时钟预分频数 TIM_TimeBaseStructure . TIM_ClockDivision = TIM_CKD_DIV1 ; // 采样分频 TIM_TimeBaseStructure . TIM_CounterMode = TIM_CounterMode_CenterAligned3 ; //中央对齐计数 TIM_TimeBaseStructure . TIM_RepetitionCounter = 0 ; //重复寄存器,用于自动更新pwm占空比 TIM_TimeBaseInit ( TIM3 , & TIM_TimeBaseStructure ); /**************pwm通道1输出配置*************/ TIM_OCInitStructure . TIM_OCMode = TIM_OCMode_PWM1 ; //设置为pwm1输出模式 TIM_OCInitStructure . TIM_Pulse = 200 ; //设置占空比时间 TIM_OCInitStructure . TIM_OCPolarity = TIM_OCPolarity_Low ; //设置输出极性 TIM_OCInitStructure . TIM_OutputState = TIM_OutputState_Enable ; //使能该通道输出 // //下面几个参数是高级定时器才会用到 // TIM_OCInitStructure.TIM_OCNPolarity=TIM_OCNPolarity_Low; //设置互补端输出极性 // TIM_OCInitStructure.TIM_OutputNState=TIM_OutputNState_Enable;//使能互补端输出 // TIM_OCInitStructure.TIM_OCIdleState=TIM_OCIdleState_Set; //死区后输出状态 // TIM_OCInitStructure.TIM_OCNIdleState=TIM_OCNIdleState_Set;//死区后互补端输出状态 TIM_OC1Init ( TIM3 ,& TIM_OCInitStructure ); //按照指定参数初始化 /**************pwm通道2输出配置*************/ TIM_OCInitStructure . TIM_OCMode = TIM_OCMode_PWM2 ; //设置为pwm1输出模式 TIM_OCInitStructure . TIM_Pulse = 520 ; //设置占空比时间 TIM_OCInitStructure . TIM_OCPolarity = TIM_OCPolarity_Low ; //设置输出极性 TIM_OCInitStructure . TIM_OutputState = TIM_OutputState_Enable ; //使能该通道输出 TIM_OC2Init ( TIM3 ,& TIM_OCInitStructure ); TIM_OC1PreloadConfig ( TIM3 , TIM_OCPreload_Enable ); //使能TIMx在CCR1上的预装载寄存器 TIM_ARRPreloadConfig ( TIM3 , ENABLE ); //使能TIMx在ARR上的预装载寄存器 TIM_Cmd ( TIM3 , ENABLE ); //打开TIM2 TIM_CtrlPWMOutputs ( TIM3 , ENABLE ); //pwm输出使能,一定要记得打开</span>