cancel
Showing results for 
Search instead for 
Did you mean: 

Whats the difference betwee HAL_TIM_OC_Start and HAL_TIM_OC_Start_IT

Patrick Morwald
Associate II
Posted on September 07, 2017 at 14:43

Hi,

i am working on PWM output generation and input capture with the timers. What i see in the HAL description is that the OC and capture functions have always a '_IT' interrupt version counterpart.

1. I am generating a static PWM signal, i thought after starting the TIMER peripheral to generate a PWM signal it does this on its own. I assume the CPU is not loaded by the PWM signal generation. Why do i need an interrupt version of the function then if the timer peripheral is operating independently from CPU anyways? This concerns the difference between the two HAL functions HAL_TIM_OC_Start and HAL_TIM_OC_Start_IT.

2. My second case is that i want to measure the duty cycle of a PWM signal and i want to do this with HAL_TIM_IC_Start or HAL_TIM_IC_Start_IT. I really dont know what function to choose. The measured duty cycle is changing seldomly and i only want to do a short measurement from time to time. However, i cannot block the CPU at any time since i am running a lot of other processes on it. What approach is best?

Regards,

Patrick 

#timer #stm32f4 #pwm
9 REPLIES 9
Posted on September 08, 2017 at 00:50

Hello!

>>>''Why do i need an interrupt version of the function then if the timer peripheral is operating independently from CPU anyways?''

The only way to know when a PWM pulse starts, or stops is to generate interrupt by calling the IT version of function.

For a project like speed controller may be is not necessary to use the IT version. For an inverter e.g , when must start an ADC to measure the peak  current on an IGBT at every pulse, The use of IT version of function can do the job.

For the second case

To know the duty cycle need to know the period of a PWM signal and the pulse width.

Take a look at this approach from St

It's from RefManual of F4 series

0690X000006089yQAA.png

After you start HAL_TIM_IC_Start(..) you can continously read the  captured values of CCR1(Period) and CCR2(Pulse width)

There is an example also in F4 firmware (HAL) for PWM Input.

Regards

vf

Posted on September 08, 2017 at 12:57

Hi,

first thank you for your great answer. That made a lot clearer. Also i have to correct myself: I want to measure only the period of an incoming PWM signal, and dont care about the duty cycle. Can i achieve this with one timer channel? According to your example given, one channel of the timer is used for the duty cycle and the other for the period measurement, so i should be good with one channel when i only measure period?

Do i have to configure the single timer channel for slave mode too or how do i reset the counter on the rising edge and capture the next rising edge so i get the period?

Regards,

Patrick

Patrick Morwald
Associate II
Posted on September 08, 2017 at 17:19

Hi,

thanks for your reply again. Unfortunately i cant get two input channels running in parallel on the same timer (right now im am using TIM12) with slave mode reset. I guess its because if for example channel two triggers and resets the count register, the measurement on channel 1 gets messed up.

Right now my only idea is to measure the channels one after another in a round robin like way and reconfigure the timer between each measurement...

Am i missing a better solution?

Regards,

Patrick

Posted on September 08, 2017 at 16:22

Hello Patrick.

You gave the answer by yourself -> 'Do i have to configure the single timer channel for slave mode too or how do i reset the counter on the rising edge and capture the next rising edge so i get the period?'

An example for Ch. 2

Set channel 2 as Capture Input capturing on rising edges  and set the active input for channel 2 from TI2 (TIMx_CH2)

Set also the timer in slave mode reset  and trigered from TI2FP2. (which means that counter, etc resets at every trigger from rising edge from TI2)

Enable the capture. (no need to use the IT version of HAL_TIM_IC_Start)

The CCRx register will contains the period of measuring PWM signal (frequency).

Patrick Morwald
Associate II
Posted on September 08, 2017 at 18:49

Hi,

so you suggest not to use the reset feature? Btw i am using STM32F4VGT. What timers would you suggest? I have 5 input signals (tacho signals from fans) of which i have to only measure the period (no duty cycle). 

Patrick

Posted on September 08, 2017 at 17:36

You are right!

In this case if you don't want to use another timer you must  use the capture callback  enabling it by the use of HAL_TIM_IC_StartIT for both channels, not to use the slave controler, and inside callback for each channel to subtract the current captured value from previous saved in a global variable.

I dont know which device you use  but there are timers with one channel only to do this job without software involved at run time.

Regards

vf

Posted on September 08, 2017 at 19:03

Hi again.

You mean stm32f407vgt6?  Timers 1,2,3,4,5(32bits),8,9,12  are available to read the signals without involve software  after initialization. (using slave controler reset mode)

The choose depends only from MCU's pin availability.

Patrick Morwald
Associate II
Posted on September 11, 2017 at 13:45

Hi,

i dont get why my approach with a global variable for the last capture event time doesnt work:

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)

{

if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2){

/* Get the Input Capture value */

uwIC2ValueCH2 = abs(HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2) - lastValueCH2);

uwFrequency = (HAL_RCC_GetHCLKFreq())/198 / uwIC2ValueCH2;

lastValueCH2 = uwIC2ValueCH2;

}

if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1){

/* Get the Input Capture value */

uwIC2ValueCH1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1) - lastValueCH1;

uwFrequency = (HAL_RCC_GetHCLKFreq())/198 / uwIC2ValueCH1;

lastValueCH1 = uwIC2ValueCH1;

}

}

Please ignore the HAL_TIM_ACTIVE_CHANNEL_1 branch, its currently not executed because nothing is connected tpo the pin.

Here is how i initialize the timer:

static void CIP_TIM12_Init(void)

{

TIM_ClockConfigTypeDef sClockSourceConfig;

TIM_IC_InitTypeDef sConfigIC;

/* Slave configuration structure */

TIM_SlaveConfigTypeDef sSlaveConfig;

htim12.Instance = TIM12;

htim12.Init.Prescaler = timPrescalerValue*2;

htim12.Init.CounterMode = TIM_COUNTERMODE_UP;

htim12.Init.Period = timCounterPeriodValue;

htim12.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

if (HAL_TIM_Base_Init(&htim12) != HAL_OK)

{

//TODO: Handle error

}

sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;

if (HAL_TIM_ConfigClockSource(&htim12, &sClockSourceConfig) != HAL_OK)

{

//TODO: Handle error

}

if (HAL_TIM_IC_Init(&htim12) != HAL_OK)

{

//TODO: Handle error

}

sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;

sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;

sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;

sConfigIC.ICFilter = 0;

if (HAL_TIM_IC_ConfigChannel(&htim12, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)

{

//TODO: Handle error

}

if (HAL_TIM_IC_ConfigChannel(&htim12, &sConfigIC, TIM_CHANNEL_2) != HAL_OK)

{

//TODO: Handle error

}

/*##-3- Configure the slave mode ###########################################*/

/* Select the slave Mode: Reset Mode */

// sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET;

// sSlaveConfig.InputTrigger = TIM_TS_TI2FP2;

// if(HAL_TIM_SlaveConfigSynchronization(&htim12, &sSlaveConfig) != HAL_OK)

// {

// //TODO: Handle error

// }

HAL_TIM_IC_Start_IT(&htim12, TIM_CHANNEL_1);

HAL_TIM_IC_Start_IT(&htim12, TIM_CHANNEL_2);

}

Please help!

Posted on September 11, 2017 at 14:55

Hi

with a first glance, at this part of code

0690X00000608BlQAI.png

you assigned to lastValueCH2  the difference  and not the last captured value.

The result finaly is not correct.

Also there is not need to take the absolute value of difference. you may treat all variables as unsigned  and the result will  allways correct. (0xFFFFFFFF+5=4  , 4-0XFFFFFFFF=5 for 32 bit operations or  0xFFFF+5=4  , 4-0XFFFF=5 for 16 bit operations)