STM32 timer--Toggle mode realizes 2-way pwm phase shift

Publisher:幸福的家园Latest update time:2018-07-01 Source: eefocusKeywords:STM32 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Here’s how it works:


The following code implements the use of TIM3's CH3 and CH4 to output two phase-shifted PWMs with a phase shift angle of 225 degrees.

void TIM3_PWMShiftInit(void)

{

TIM_TimeBaseInitTypeDef  TIM_TimeBaseInitStruct;

GPIO_InitTypeDef  GPIO_InitStruct;

TIM_OCInitTypeDef TIM_OCInitStruct;

 

/**********************TIM3 GPIO configuration****************************/

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);

/**********************Initialize TimBase structure****************************/

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; //The level flips once in one period, Frequency = 36000000/PSC/(ARR+1);

TIM_TimeBaseInitStruct.TIM_Prescaler = 7199;     

TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);

/**********************Initialize TIM3 OC structure****************************/

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; //In the first cycle, CCR and CNT will not be compared

 

TIM_OC3Init(TIM3,&TIM_OCInitStruct);

  TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;   

  TIM_OCInitStruct.TIM_Pulse = 1; //Phase shift degree = 180*CCR/(ARR+1)

TIM_OC4Init(TIM3,&TIM_OCInitStruct);

 

TIM_Cmd(TIM3, ENABLE);

}

Waveform captured by the oscilloscope:

CH1:TIM3 CH3

CH2:TIM3 CH4




Then add the following code to the above program:

 TIM_OCInitStruct.TIM_Pulse = 1; //Phase shift degree = CCR/(ARR+1)

TIM_OC4Init(TIM3,&TIM_OCInitStruct);

To:


 TIM_OCInitStruct.TIM_Pulse = 3; //Phase shift degree = CCR/(ARR+1)

TIM_OC4Init(TIM3,&TIM_OCInitStruct);

The waveform is as follows:



A few points to note:


1. Initial level, by observing TIM_OCInitStruct.TIM_Pulse = 1; and TIM_OCInitStruct.TIM_Pulse = 3;      

     From the oscilloscope waveforms in these two cases, we can see that when TIM_OCInitStruct.TIM_Pulse = 0; theoretically, the waveform on the CH1 channel of the oscilloscope should be

     The complementary waveform of the current CH1 channel. It can be understood that in the first ARR cycle, the waveform on the oscilloscope CH1 did not flip, so the current waveform is

     The complementary waveform of the theoretical waveform is in line with the actual waveform. Therefore, at this time, the CH1 waveform is low in the first ARR cycle, while CH2 is high in the first ARR cycle.

     1/4 is low level and the remaining 3/4 is high level.

2. You cannot achieve a 180-degree phase shift by modifying the value of the structure member TIM_Pulse in TIM_OCInitStruct.TIM_Pulse = 1;. The maximum phase shift

    Angle according to:

Phase shift degree = 180*CCR/(ARR+1)

    When CCR=ARR, the maximum phase shift angle is obtained, angle = ARR/ARR+1. From the program and oscilloscope waveform, we can know that the maximum value of TIM_Pulse is the value of ARR.

    In the above program, the value is "3". When it is 3, the waveform should theoretically be phase-shifted by: 180*(TIM_Pulse/(ARR+1)) = 180*(3/4) = 135 degrees.

     However, from the first item above, when TIM_Pulse=0, the level of the first ARR cycle does not flip (proven at the end of the article), so

    The phase shift angle seen on the oscilloscope is now 180+135=315 degrees. Because when ARR is 3, CNT counts from 0 to 3 for a total of 4 counting cycles, and CCR is

    The value of TIM_Pulse is 3, and an interrupt event is generated when CNT counts to 3. At this time, after 3 counting cycles, there is a difference of one counting cycle between them.

    To achieve 180-degree phase shift, that is, complementary output, it is only necessary to make the other configurations of the two channels consistent and the output polarity (TIM_OCPolarity) opposite.

3. Because one ARR cycle flips the level once, which is less than twice in PWM mode, the PWM frequency obtained by this mode is half of that in PWM mode.

    When calculating the frequency, use 36000000 instead of 72000000 (when the timer division factor is 1):

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

4. The PWM duty cycle output in this mode is 50% and cannot be adjusted. If you want to change the duty cycle, you can enable the CCR interrupt and change the CCR value of the corresponding channel in the interrupt.

     Realize the change of duty cycle.


/********************************************Procedure to change the duty cycle using interrupts********************************************/


//CH3 linked list

struct TIM_CH3CCR

{

   u16 CCRValue;

   struct TIM_CH3CCR *next;

}; 

struct TIM_CH3CCR  CCR3a,CCR3b,*p3;

 

//CH4 linked list

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;

 

   // Initialize the linked list

    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 configuration********************************/

    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 configuration****************************/  

    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);  

      

    /**********************Initialize TimBase structure****************************/  

    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; //The level flips twice in one period, Frequency = 72000000/PSC/(ARR+1);  

    TIM_TimeBaseInitStruct.TIM_Prescaler = 0;       

      

    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);  

      

    /**********************Initialize TIM3 OC structure****************************/  

    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; //The first cycle, the level does not flip

  

    TIM_OC3Init(TIM3,&TIM_OCInitStruct);  

      

    TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;     

    TIM_OCInitStruct.TIM_Pulse = 18000; //Phase shift degree = 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);

}

}

The waveform is as shown below:

Oscilloscope CH1: TIM3 CH3


Oscilloscope CH2: TIM3 CH4





1. The frequency we set is 72000000/PSC/(ARR+1) = 72000000/1/36000 = 2000Hz. This is consistent with the frequency detected by the oscilloscope.

2. CH3 starts with CCR = 0, CH4 CCR = 18000; According to: Phase shift degree = 360*CCR/(ARR+1), it can be known that the phase shift is 180 degrees. This is consistent with the oscilloscope.

3. Set CCR of CH3 to 0, 9000, and CH4 to 18000, 27000. So the duty cycle is 25%.


A few points to note:

1. Frequency algorithm. Because an ARR cycle is triggered twice instead of once, the formula is 72000000/PSC/(ARR+1) instead of 36000000.

2. The phase shift angle algorithm is also because one ARR cycle triggers two level flips, so it is not 180*CCR/(ARR+1), but 360.

3. Because the flip of the phase shift level is processed in the interrupt, be careful not to let the interrupt time of the two channels overlap, and this method consumes CPU resources.

     Susceptible to interference from other interruptions at high frequencies.

4. If CCR is set to 0, the level of the first ARR cycle will not flip, as shown in the following oscilloscope diagram:




Figure 1, the oscilloscope is set to single trigger mode, the first high level is TIM initialization, after initialization, it starts to output PWM.

Figure 2 shows the waveform of the interrupt modification CCR program after the interrupt enable bit is masked and the code is turned on:


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

The other codes remain unchanged.

Figure 3 is a waveform diagram of the procedure for changing the CCR to adjust the duty cycle for a normal interrupt.


Keywords:STM32 Reference address:STM32 timer--Toggle mode realizes 2-way pwm phase shift

Previous article:STM32 Study Notes - PWM Waveform Output
Next article:STM32 general timer output comparison mode

Recommended ReadingLatest update time:2024-11-16 14:45

Case Study: KST3420 and KST3220 use ST's FlightSenseToF sensor and STM32 for rapid prototyping
Case Study: KST3420 and KST3220 use ST's FlightSenseToF sensor and STM32 for rapid prototyping The KST3420 and KST3220 are distance measurement sensors developed by KS Technologies (also known as KST), an authorized member of the ST Partner Program, and are also an applicat
[sensor]
Case Study: KST3420 and KST3220 use ST's FlightSenseToF sensor and STM32 for rapid prototyping
Use of STM32 advanced timer
       The reason for writing this article is that I found that there are few articles on the Internet that analyze the principles of STM32 registers. Maybe it is too simple and no one is willing to write. So I will write it down and try to make it simple and easy to understand, so as to leave a commemoration. It is d
[Microcontroller]
STM32-Library Development-Address Mapping
1. stm32 has AHB, APB2, and APB1 buses.    The APB2 peripheral address space is from 0x40010000 to 0x40013FFF. The first address is called the base address. 2. The port configuration register in the reference manual has an address offset of 0x04, so the address of GPIOC_CRH is GPIOC_BASE+0x04   GPIO_TypeDef structur
[Microcontroller]
STM32 timer timing calculation formula
Tout = ((arr+1)*(psc+1))/Tclk; in: Tclk: Timer input clock frequency (unit: MHZ) Tout: Timer overflow time (unit: us)   .TIM_Period = arr; eg; 4999   .TIM_Prescaler = psc; eg: 7199   Tout = ((4999+1) × (7199+1))/72 = 500000us = 500ms.
[Microcontroller]
STM32 fast read and write AT24C16 code simulation I2C
This post is only applicable to chips AT24C16 and below. The reading and writing methods of chips AT24C32 and above are different, so it is not applicable!!! If your code can read and write 24C01/02 normally, you can use it to read 24C16 directly, but it can only read 256 bytes. AT24C16 is different from AT24C01/0
[Microcontroller]
STM32 fast read and write AT24C16 code simulation I2C
STM32 RTC reading and writing incorrectly
When debugging RTC, I found that the reading and writing were incorrect. Reading and writing are library functions that are called, and the year, month, day, hour, minute, and second are operated separately When reading and writing, it is found that after the year, month and day are written, it takes several secon
[Microcontroller]
Understanding the Difficulties of STM32 Interface FSMC/FMC
1. FSMC Brief           FSMC, the Flexible Static Storage Controller, is capable of interfacing with synchronous or asynchronous memories and 16-bit PC memory cards. The FSMC interface of STM32 supports memories including SRAM, NAND FLASH, NOR FLASH and PSRAM. 2. FSMC storage block The STM32F767's FMC divides
[Microcontroller]
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号