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.
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
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- 【ST NUCLEO-G071RB Review】+ My review process
- Share a learning material: Comic electronic circuit
- Help: Current-type voltage transformer detects AC voltage circuit
- Share two PPT lectures on MOS tubes, very good
- The application circuit of the operational amplifier as a battery pack indicator light is shown in the figure
- Countdown 4 days: NXP i.MX processor quiz prize draw (including facial recognition demo source code)
- Sharing of experience in single board circuit design (1) - power supply filtering
- Reference circuit design
- Exclusive violent disassembly of active noise reduction neck-worn voice smart headphones
- Introduction to TI_DSP link command file (*.cmd)