2015-10-28 07:57 AM
Hi all
We need some help on a PWM setup. I�ll first present the use case then the issue we�re having and code. I�m pretty sure this is a PWM/timer understanding/register setup issue, but I just can figure out what is wrong. Please note that we are not using most of the STM libraries as our current project does not allow it. The question/issue can probably be answered without the code though. Use:PWM at approx 200kHz with even (50%) duty cycle. Both P and N channel used. PWM is turned on and off after a certain amout of pulses, e.g 10 off, 10 on. Timer 1 is used for PWM and Timer17 for turning on and off the PWM, interrupt based. Issue: First and last PWM pulse do either have too long or too short duty cycle. Seems that 0,9 microseconds after turning on the PWM from the interrupt the pin gets set. What we would want is it to wait until next pulse/timer1 hits. See image below.Yellow
: Low indicates PWM onBlue
: PWM signal, shows short first PWM pulse, long last pulseViolet
: PWM n signal.Question:Is it possible to do what we want to do here; Turn on and off the PWM but resetting the output/counter so that we only get 50% duty cycle pulses?------------------------- Code:I�ve done a real effort at cherry picking and replacing dynamic code for the example this time. Giving it all would just be too much for anyone to bother looking into.Microprocessor STM32F106////////////////////
// INITIALIZATION //////////////////////{ // TIM1 used for PWM RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; RCC->APB2RSTR |= RCC_APB2RSTR_TIM1RST; RCC->APB2RSTR &= ~RCC_APB2RSTR_TIM1RST; TIM1->ARR = 1; TIM1->PSC = (24000000 / (200000 * 2)) - 1; // Original code: (PowerPwmClockFrequency / (Frequency * 2)) - 1 TIM1->CCMR1 |= (TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2PE); TIM1->CR1 = TIM_CR1_ARPE | TIM_CR1_CEN; TIM1->EGR = TIM_EGR_UG; TIM1->BDTR = TIM_BDTR_MOE; // TIM17 used for turning on and off PWM RCC->APB2ENR |= RCC_APB2ENR_TIM17EN; RCC->APB2RSTR |= RCC_APB2RSTR_TIM17RST; RCC->APB2RSTR &= ~RCC_APB2RSTR_TIM17RST; TIM17->ARR = TIM1->ARR; TIM17->PSC = TIM1->PSC; NVIC_SetPriority(TIM1_TRG_COM_TIM17_IRQn, 0); // Highest interrupt level NVIC_DisableIRQ(TIM1_TRG_COM_TIM17_IRQn); TIM17->CR1 = TIM_CR1_ARPE | TIM_CR1_CEN; // Enable timer TIM17->DIER = TIM_DIER_UIE; // Enable timer interrupt TIM17->EGR = TIM_EGR_UG; // Set interval time/*....*/ TIM17->ARR = SafeModeOffCycleTime; // e.g. 20 for 10 pulses TIM1->CCR2 = 1; TIM1->CCER = (TIM1->CCER & ~((TIM_CCER_CC1NP | TIM_CCER_CC1NE | TIM_CCER_CC1P | TIM_CCER_CC1E) << 2)) | ((TIM_CCER_CC1NE | TIM_CCER_CC1E) << 2); NVIC_EnableIRQ(TIM1_TRG_COM_TIM17_IRQn);}//////////////////////////////////////////////// INTERRUPT HANDLER TO TURN PWM ON AND OFF ////////////////////////////////////////////////void TIM1_TRG_COM_TIM17_IRQHandler(void){ TIM17->SR = 0x0000; // Clear interrupt flag if (PwmSleepModeActive == FALSE) { TIM17->ARR = SafeModeOffCycleTime; // SafeModeOffCycleTime e.g. 20 for 10 pulses PwmSleepModeActive = TRUE; TIM1->CCR2 = 1; } else { TIM17->ARR = SafeModeOnCycleTime; // SafeModeOnCycleTime e.g. 20 for 10 pulses PwmSleepModeActive = FALSE; TIM1->CCR2 = 0; }} #stm32f1 #pwm2015-10-28 10:53 AM
Perhaps you want to write TIM17->CNT = 0 in the interrupt to ensure the starting phase setting. Or wait for it to hit a specific phase angle when turning off.
2015-10-30 07:25 AM
Thanks clive1
I expect you mean TIM1->CNT = 0; or perhaps both of them. This had a minor effectonly improving the first pulse somewhat. We have preload bits set to enable shadow registers so I don't quite understand why this is happening. Still to me it seems to be a setting missing that should prevent PWM to start up/stop before the next change for the PWM. As it is now as soon as CCRx=1 is set the P and N pins are set and this leads to the problem seen.Any further suggestions would be very appreciated.Waiting for a specific phase angle without help from the PWM/Timer subsystem itself seems like a big challenge.EDIT: I've identified what is wrong. Please wait till I get back with more information on the bug. I still have no solution so there will be a followup question on how to do what was originally attempted here.Best RegardsKim