STM32定时器----Toggle模式实现2路pwm移相

原理如下:

以下代码实现了利用TIM3的CH3以及CH4输出两路移相的PWM

 

void TIM3_PWMShiftInit(void)
{
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseInitStruct;
	GPIO_InitTypeDef  GPIO_InitStruct;
	TIM_OCInitTypeDef TIM_OCInitStruct;

	
	/**********************TIM3 GPIO配置*****************************/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

	GPIO_Init(GPIOB,&GPIO_InitStruct);
	
	/**********************初始化TimBase结构体*************************/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStruct.TIM_Period =  3;  //一个周期翻转一次电平,Frequence = 36000000/PSC/(ARR+1);
	TIM_TimeBaseInitStruct.TIM_Prescaler = 7199;     
	
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);
	
	/**********************初始化TIM3 OC结构体*************************/
	TIM_OCInitStruct.TIM_OCIdleState = TIM_OCIdleState_Set;
	TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_Toggle;
	TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStruct.TIM_Pulse = 0;   //第一个周期,CCR与CNT不会进行比较

	TIM_OC3Init(TIM3,&TIM_OCInitStruct);
	
  TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;   
  TIM_OCInitStruct.TIM_Pulse = 1;   //移相度数 = 180*CCR/(ARR+1)
	TIM_OC4Init(TIM3,&TIM_OCInitStruct);

	TIM_Cmd(TIM3, ENABLE);
}

示波器抓取的波形:

CH1:TIM3 CH3

CH2:TIM3 CH4

 


 

 

 

然后将上述程序中的以下代码:

 TIM_OCInitStruct.TIM_Pulse = 1;   //移相度数 = CCR/(ARR+1)
	TIM_OC4Init(TIM3,&TIM_OCInitStruct);

 

改成:

 

 TIM_OCInitStruct.TIM_Pulse = 3;   //移相度数 = CCR/(ARR+1)
	TIM_OC4Init(TIM3,&TIM_OCInitStruct);

波形如下图:

 

 

需要注意几点:

 

1、初始电平,通过观察TIM_OCInitStruct.TIM_Pulse = 1;   与  TIM_OCInitStruct.TIM_Pulse = 3;      

     这两种情况下的示波器波形图可以知道,TIM_OCInitStruct.TIM_Pulse = 0; 时,理论上示波器CH1通道上波形应该为

     现在的CH1通道的互补波形。可以理解为,在第一个ARR周期,示波器CH1上的波形并没有翻转,如此现在的波形为

     理论上波形的互补波形就符合实际了。所以,此时CH1波形在第一个ARR周期为低电平,而CH2在第一个ARR周期中

     1/4为低电平,剩下3/4为高电平。

2、不能通过修改 TIM_OCInitStruct.TIM_Pulse = 1;    中结构体成员TIM_Pulse 的值,来实现180度的移相。最大的移相

    角度根据:

移相度数 = 180*CCR/(ARR+1)

    当CCR=ARR时获得最大移相角度,角度=ARR/ARR+1。通过程序以及示波器波形可知,TIM_Pulse最大值为ARR的值,

    在以上程序为“3”。为3时,理论上波形应该移相:180*(TIM_Pulse/(ARR+1))= 180*(3/4)= 135度。

     但由上述第一条事项可知,在TIM_Pulse=0;时,第一个ARR周期电平不发生翻转(文章的最后有证明),所以

    现在示波器上看到的移相角度为180+135=315度。因为ARR为3时CNT从0计数到3共4个计数周期,而CCR即

    TIM_Pulse的值为3,CNT计数到3的瞬间产生中断事件,此时经过3个计数周期,他们之间相差一个计数周期。如果

    要实现180度移相,也就是互补输出。只需将两通道的其他配置一致,输出极性(TIM_OCPolarity)相反即可。

3、因为一个ARR周期翻转一次电平,少于PWM模式的2次。所以采用这种模式出来的PWM频率为PWM模式下的一半。

    计算频率时用36000000而不是72000000(定时器分频系数为1情况下):

Frequence = 36000000/PSC/(ARR+1);

4、此模式下输出的PWM占空比为50%不可调。如果要改变占空比,可以开启CCR中断,在中断中改变对应通道的CCR的值

     实现占空比的改变。

 

/*****************************************利用中断更改占空比的程序*******************************************/

 

//CH3链表
struct TIM_CH3CCR
{
   u16 CCRValue;
   struct TIM_CH3CCR *next;
}; 
struct TIM_CH3CCR  CCR3a,CCR3b,*p3;

//CH4链表
struct TIM_CH4CCR
{
   u16 CCRValue;
   struct TIM_CH4CCR *next;
}; 
struct TIM_CH4CCR  CCR4a,CCR4b,*p4;
void TIM3_PWMShiftInit(void)  
{  
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseInitStruct;  
    GPIO_InitTypeDef  GPIO_InitStruct;  
    TIM_OCInitTypeDef TIM_OCInitStruct;  
    NVIC_InitTypeDef  NVIC_InitStruct;

   //初始化链表
    CCR3a.CCRValue = 0;
    CCR3b.CCRValue = 9000;
    CCR4a.CCRValue = 18000;
    CCR4b.CCRValue = 27000;
	
    CCR3a.next = &CCR3b;
    CCR3b.next = &CCR3a;
    CCR4a.next = &CCR4b;
    CCR4b.next = &CCR4a;
	
    p3 = &CCR3a;
    p4 = &CCR4a;  
	
    /***********************NVIC配置*****************************/
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
		
    NVIC_InitStruct.NVIC_IRQChannel = TIM3_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
		
    NVIC_Init(&NVIC_InitStruct);
      
    /**********************TIM3 GPIO配置*****************************/  
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);  
      
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;  
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;  
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;  
  
    GPIO_Init(GPIOB,&GPIO_InitStruct);  
      
    /**********************初始化TimBase结构体*************************/  
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);  
      
    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;  
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;  
    TIM_TimeBaseInitStruct.TIM_Period =  35999;  //一个周期翻转两次电平,Frequence = 72000000/PSC/(ARR+1);  
    TIM_TimeBaseInitStruct.TIM_Prescaler = 0;       
      
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);  
      
    /**********************初始化TIM3 OC结构体*************************/  
    TIM_OCInitStruct.TIM_OCIdleState = TIM_OCIdleState_Set;  
    TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_Toggle;  
    TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;  
    TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;  
    TIM_OCInitStruct.TIM_Pulse = 0;   //第一个周期,电平不翻转
  
    TIM_OC3Init(TIM3,&TIM_OCInitStruct);  
      
    TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;     
    TIM_OCInitStruct.TIM_Pulse = 18000;   //移相度数 = 360*CCR/(ARR+1)  
    TIM_OC4Init(TIM3,&TIM_OCInitStruct);  
  
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC3|TIM_IT_CC4);
    TIM_ITConfig(TIM3, TIM_IT_CC3|TIM_IT_CC4,ENABLE);
	
    TIM_Cmd(TIM3, ENABLE);  
}  
void TIM3_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM3,TIM_IT_CC3)!=DISABLE)
	{
		p3 = p3->next;
		TIM3->CCR3 = p3->CCRValue;
		TIM_ClearITPendingBit(TIM3, TIM_IT_CC3);
	}
	else
	{
		p4 = p4->next;
		TIM3->CCR4 = p4->CCRValue;
		TIM_ClearITPendingBit(TIM3, TIM_IT_CC4);
	}
}

出来波形如图:

示波器CH1: TIM3 CH3

示波器CH2: TIM3 CH4





1、我们设定的频率为72000000/PSC/(ARR+1) = 72000000/1/36000 = 2000Hz。与示波器探测出来相符。

2、CH3起始CCR = 0,CH4 CCR=18000;根据:移相度数 = 360*CCR/(ARR+1),可知移相为180度。与示波器相符

3、CH3设定CCR为:0、9000,CH4为:18000,27000。所以占空比为25%。

 

注意几点:

1、频率算法,因为一个ARR周期触发2次,而不是原本的一次,所以公式为72000000/PSC/(ARR+1)而不是36000000。

2、移相角度算法,也是因为一个ARR周期触发两次电平翻转,所以不是180*CCR/(ARR+1),而是360。

3、因为是在中断中处理移相电平的翻转,所以注意不要让两通道中断时间叠加一起,且这种方法需要消耗CPU资源,

     高频率下易受到其他中断的干扰。

4、CCR设为0则第一个ARR周期电平不翻转,看以下示波器图得以证明:

图1,示波器调为单次触发模式,第一段高电平为TIM初始化,初始化完毕后开始输出PWM。

图2,为上述中断更改CCR程序中,屏蔽了中断的允许位开启代码后的波形:

 

    //TIM_ClearITPendingBit(TIM3, TIM_IT_CC3|TIM_IT_CC4);
    //TIM_ITConfig(TIM3, TIM_IT_CC3|TIM_IT_CC4,ENABLE);

其他代码不变。

图3,为正常的中断更改CCR实现调节占空比的程序的波形图。

 

 

  • 18
    点赞
  • 77
    收藏
    觉得还不错? 一键收藏
  • 18
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值