Is it possible using the TIMx PWM Output Mode to produce a wave with a controllable Duty cycle (as in j1850 PWM)?
Example: Bit 0 represents a wave with a 25% duty cycle |^|____ Bit 1 resresents a wave with a 75% duty cycle. |^^^|_ So if I send 0100101 I would see a wave with a variable duty cycle that changes on each bit I transmit. |^|____|^^^|_|^|____|^|____|^^^|_|^|____|^^^|_ Your help will be very much appreciated
of course, the compare registers are optionally shadowed. you get an interrupt at the start of a cycle and you've got full cycle to decide what the duty of the next cycle will be; you just have to program the value before this cycle ends.
you should use the time base periodic int, not the CC3 int. and enable the interrupt before enabling the timer.
> the very first pulse is 1us longer than it should be the PWM output is probably active before you start the time-base 1) make the first PWM cycle have zero width: PWM_TIM_OCInitStructure.TIM_Pulse = 0; // this goes through to the CC reg since preloading is disabled; it'll be active now and during the first PWM cycle. PWM_TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInit(TIM2, &PWM_TIM_OCInitStructure); TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable); TIM_ARRPreloadConfig(TIM2, ENABLE); TIM2->CCR3 = 432; // now this sits in the preload and will rule cycle 2. /* TIM enable counter */ TIM_Cmd(TIM2, ENABLE); // note that if this immediately causes a time-base int (I don't think so) then the above statement should be removed (the ISR would set width of the 2nd cycle). } 2) if the 1 cycle delay at the beginning is a problem and you need an accurate first pulse, you need to preset the time base counter with a value near the upper limit so that the first PWM cycle is reduced to one or two time-base clocks.
Thank-you lanchon - your response made me persist. I feel I should post the working code for completeness
void SetUpTimer2(void) { /* Time base configuration */ PWM_TIM_TimeBaseStructure.TIM_Period = 1728; /* 1728 at 72MHz gives us 24us bit time */ PWM_TIM_TimeBaseStructure.TIM_Prescaler = 0; PWM_TIM_TimeBaseStructure.TIM_ClockDivision = 0; PWM_TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &PWM_TIM_TimeBaseStructure); /* PWM1 Mode configuration: Channel1 */ PWM_TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; PWM_TIM_OCInitStructure.TIM_Channel = TIM_Channel_3; PWM_TIM_OCInitStructure.TIM_Pulse = 432; PWM_TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInit(TIM2, &PWM_TIM_OCInitStructure); TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable); TIM_ARRPreloadConfig(TIM2, ENABLE); /* TIM enable counter */ TIM_Cmd(TIM2, ENABLE); /* Enable the CC3 Interrupt Request */ TIM_ITConfig(TIM2, TIM_IT_CC3, ENABLE); } Then the interrupt is simply this: void TIM2_IRQHandler(void) { if ( TIM_GetITStatus(TIM2, TIM_IT_CC3)) { /* rising edge detected */ /* Clear TIM2 Capture compare interrupt pending bit */ TIM_ClearITPendingBit(TIM2, TIM_IT_CC3); if (Pulse == 432) Pulse = 1296; /*75% Pulse*/ else Pulse = 432; /*25% Pulse*/ TIM2->CCR3 = Pulse; } } The only slight thing it is doing wrong now is the very first pulse is 1us longer than it should be(the 25% high pulse is 7us rather than 6us). I have no idea why. Thanks again Adam
I have also face this problem now, could you please give some detailed information? I managed to generate PWM from TIM3_CH3 and the result is good seen on an Oscilloscope, but, i couldn't capture the TIM3 interrupt, code as following:
, GPIO_LED0_PIN, (BitAction)((1-GPIO_ReadOutputDataBit(GPIO_LED, GPIO_LED0_PIN)))); //IC3value = TIM_GetCapture3(TIM3); TIM_ClearITPendingBit(TIM3, TIM_IT_CC3); } } Why doesn't The LED toggle with the TIM interrupt? How can I ''you get an interrupt at the start of a cycle and you've got full cycle to decide what the duty of the next cycle will be'' Thank you advanced.
Thanks again lanchon - I hope ST pay you for this service.
I did as you said and stopped the long first pulse problem by setting Pulse to 0 initially. I have now successfully transmitted a J1850PWM message this way to a vehicle ECU and received the expected response (seen on a scope). Adam
I did use the ''TIM_ITConfig(TIM3, TIM_IT_CC3, ENABLE)'' instead of '' TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE)'' and they act as no differece, so that could not be the reason. I just wondering should i take another timer to set as input to cature the interrupt.