cancel
Showing results for 
Search instead for 
Did you mean: 

Get PWM output state for interrupt purposes STM32F215

Zarck.zek
Associate II
Posted on February 01, 2018 at 09:37

Hi,

I'm working on STM32F215 and I generate a PWM output on TIM1. This signal is going to an other device.

For synchronization purposes on this signal, I would like to get the rising and falling edge of it.

My first thought is to link the PWM ouptut directly to a EXTI pin in order to get my edges interrupt.

I just begin working withTimerbut I'm just there is a simple way to get those PWM informations.

Could you please help me with a code example/interrupt configuration ?

Thank you very much,

Marc

#interrput #tim-pwm #stm32f2

Note: this post was migrated and contained many threaded conversations, some content may be missing.
1 ACCEPTED SOLUTION

Accepted Solutions
John Craven
Senior
Posted on February 01, 2018 at 15:28

Drill into the HAL_TIM_PWM_Start_IT method.

You'll see it sets the Compare event interrupt with;

      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CCx);

Directly after your Start IT call, add the following to also enable the Update event;

      __HAL_TIM_ENABLE_IT(htim, TIM_IT_UPDATE);

in your case, based on your code sample, it would look like;

      HAL_TIM_PWM_Start_IT(&_t_HTIM1, TIM_CHANNEL_3)

      __HAL_TIM_ENABLE_IT(&_t_HTIM1, TIM_IT_UPDATE);

If you are using a CubeMX generated project,

you have to check both interrupts

0690X00000609WbQAI.png

the interrupts can be handled in

TIM1_UP_TIM10_IRQHandler(void) for the update event

 

TIM1_CC_IRQHandler(void) for the compare event

 

or you can provide your own own handlers for the weak methods;

void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) for the compare event

 

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) for the update event

 

If you are using count UP, active HIGH polarity;

Update event is rising edge, state is HIGH in handler

Compare event is falling edge, state is LOW in handler

Note, if you were using another timer, say TIM2,

There would only be one global interrupt checkbox in cubemx,

The global handler would be;

TIM2_IRQHandler

and the your implementations of;

 

void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) for the compare event

 

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) for the update event

 

 

would be common to all your compare and update interrupt enabled timers.

 

View solution in original post

13 REPLIES 13
Posted on February 01, 2018 at 10:25

Rising and falling edge of PWM corresponds to Update and Compare events. Depending on PWM mode and output polarity setting which one is which. So you simply enable interrupt from Update and respective Compare in TIMx_DIER, and then in the ISR you check in TIMx_SR which one of them has happened (for TIM1 particularly, there are separate interrupt vectors for update and for the captures, so you don't need to distinguish them in the ISR).

JW

John Craven
Senior
Posted on February 01, 2018 at 15:28

Drill into the HAL_TIM_PWM_Start_IT method.

You'll see it sets the Compare event interrupt with;

      __HAL_TIM_ENABLE_IT(htim, TIM_IT_CCx);

Directly after your Start IT call, add the following to also enable the Update event;

      __HAL_TIM_ENABLE_IT(htim, TIM_IT_UPDATE);

in your case, based on your code sample, it would look like;

      HAL_TIM_PWM_Start_IT(&_t_HTIM1, TIM_CHANNEL_3)

      __HAL_TIM_ENABLE_IT(&_t_HTIM1, TIM_IT_UPDATE);

If you are using a CubeMX generated project,

you have to check both interrupts

0690X00000609WbQAI.png

the interrupts can be handled in

TIM1_UP_TIM10_IRQHandler(void) for the update event

 

TIM1_CC_IRQHandler(void) for the compare event

 

or you can provide your own own handlers for the weak methods;

void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) for the compare event

 

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) for the update event

 

If you are using count UP, active HIGH polarity;

Update event is rising edge, state is HIGH in handler

Compare event is falling edge, state is LOW in handler

Note, if you were using another timer, say TIM2,

There would only be one global interrupt checkbox in cubemx,

The global handler would be;

TIM2_IRQHandler

and the your implementations of;

 

void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) for the compare event

 

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) for the update event

 

 

would be common to all your compare and update interrupt enabled timers.

 

Posted on February 01, 2018 at 14:50

Hi,

Thank you for your answer!

My code is based on the STM Cube generated code.

Ok, so I enabled TIM1_UP_TIM10_IRQn and TIM1_CC_IRQn in the dedicated MSP function.

This is my OC configuration :

__t_ConfigOC.OCMode = TIM_OCMODE_PWM1;

__t_ConfigOC.Pulse = 63; // default 6.3ms

__t_ConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;

__t_ConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;

__t_ConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

__t_ConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;

__t_ConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;

I start the PWM using HAL_TIM_PWM_Start_IT(&_t_HTIM1, TIM_CHANNEL_3) function.

I go to the CC Handler but not into the Update Handler. Do I miss something? 

Thank you,

Marc

Posted on February 01, 2018 at 15:02

I don't use Cube. Have you set both interrupt enable bits in TIMx_DIER?

JW

henry.dick
Senior II
Posted on February 01, 2018 at 16:04

OCiREF xor OCiP is the signal you need. OCiP (polarity) is readily available. OCiREF is not but can be extracted from the counter value and match point.

Not difficult at all if you can take a look at the datasheet.

edit:

I wrote this little piece to test out the concept above:

//reset TIM3OC3's state

//timer: upcounting

char OC3_get(TIM_TypeDef *TIMx) {

  int tmp = TIMx->CNT < TIMx->CCR3; //1 if CNTR < CCR3

  switch (TIMx->CCMR2 & TIM_CCMR2_OC3M) {

  //0b110->PWM mode 1: OC3REF active if CNTR < CCR3

  case TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | 0x00: tmp = !tmp; break; //do nothing (positive logic)

  //0b111->PWM mode 2: OC3REF active if CNTR > CCR3

  case TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0: tmp = tmp; break; //negative logic

  default: break;  //should list out all other cases

  }

  return (TIMx->CCER & TIM_CCER_CC3P)?tmp:!tmp;

}

In the mains loop, I had this:

if (TIM3OC3_get()) IO_SET(LEDG_PORT, LEDG); else IO_CLR(LEDG_PORT, LEDG); //if OC3 is high, set LEDG, otherwise, clear it

The TIM3OC3 was set up to output a PWM waveform, to be replicated on LEDG.

When ran on STM32F100RB, the code does precisely what it was supposed to.

Note: 1) as shown in OC3_get(), I didn't list out all cases. 2) the logic becomes slightly more complex is deadtime management is activated. 3) the code doesn't rely on anything other than the device header file so it should run under any libraries.

Posted on February 01, 2018 at 16:16

Both interrupts can be handled with the global

TIM1_IRQHandler

AFAIK there's no such.

(for TIM1 particularly, there are separate interrupt vectors for update and for the captures, so you don't need to distinguish them in the ISR)

JW

Posted on February 01, 2018 at 16:20

Hi John!

Thank you very much.

I see now in the 'HAL_TIM_PWM_Start_IT' function, it enables only CCx. 

The 'HAL_TIM_Base_Start_IT' function performes the __HAL_TIM_ENABLE_IT(htim, TIM_IT_UPDATE);

I get into both interrupts now.

Thank you guys,

Marc
Posted on February 01, 2018 at 16:38

If he generated the project with CubeMX, and enabled the TIM1 global interrupt there is!

he would have a handler like this;

void TIM1_IRQHandler(void)

{

  /* USER CODE BEGIN TIM2_IRQn 0 */

  /* USER CODE END TIM2_IRQn 0 */

  HAL_TIM_IRQHandler(&htim1);

  /* USER CODE BEGIN TIM2_IRQn 1 */

  /* USER CODE END TIM2_IRQn 1 */

}

It calls HAL_TIM_IRQHandler(&htim1);

which then calls the event specific handlers;

void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)

 

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

 

Posted on February 01, 2018 at 16:44

Does CubeMX generate also the vector table source?

JW