cancel
Showing results for 
Search instead for 
Did you mean: 

examples/TIM2/TIM2_Input_Capture/main.c

spiovan9
Associate II
Posted on December 16, 2010 at 17:29

Hi all,

I was studying the examples on timers and so on.

I came across the source ''main.c'' in the STM8S Firmware Library package,

examples/TIM2/TIM2_Input_Capture/main.c,

a piece of which is shown below.

This example will show you how to measure the frequency of the LSI.

Although this is very clear what the purpose of activating an interrupt CC1?

/* Enable CC1 interrupt */

00057         (, );

I think we'd needn't any interrupt here ?

What do you think?

If you go through the same purposed example presented on TIM1 examples section, infact, there's no interrupt initialization at all...

Thank you

Stefano

void(

void

)

00050 {

00051 

00052        

/* Capture only every 8 events!!! */

00053  

/* Enable capture of TI1 */

00054         (, , , , 0x00);

00055  

00056        

/* Enable CC1 interrupt */

00057         (, );

00058        

00059        

/* Enable TIM2 */

00060   ();

00061                

00062        

/* Clear CC1 Flag*/

00063   ();

00064  

#tim2 #interrupt #capture-compare
5 REPLIES 5
lowpowermcu
Associate II
Posted on December 20, 2010 at 17:06

Hi piovan,

Yes, I share you point of view.

There is no code in TIM2 IRQ handler.

I think that it is a typo but I would prefer that the example uses the interrupt because in our case we need to off-load the CPU and process code only when interrupts occur.

MCU Lüfter

spiovan9
Associate II
Posted on December 21, 2010 at 22:07

Hi Lüfter,

thanks.

Another interesting fact I noticed in the example provided by ST.

If you set the TIM2 INPUT CAPTURE PRESCALER to divide by 4, for example,

TIM2_ICInit(TIM2_CHANNEL_1, TIM2_ICPOLARITY_FALLING, TIM2_ICSELECTION_DIRECTTI, TIM2_ICPSC_DIV4, 0x00);

 

or less than 8 anyway, it means that you should capture every 4 input events. In this way you should measure the clock frequency of the LSI nearly a HALF than when you set the prescaler IC division by 8 (i.e. 128kHz / 2 =  64 KHz).

Well, it doesn't ! The result you get is always the same 128KHz or so.

The same result when you set the prescaler division by less than 4 down to 1.

WHY?

To get into this apparent anomaly I modified the example code a little bit by toggling and hardware output port (i.e. PE.3) when the capture occured.

while (1)

{

  /* wait a capture on CC1 */

      while((TIM2->SR1 & TIM2_FLAG_CC1) != TIM2_FLAG_CC1);

      /* Get CCR1 value*/

    ICValue1 = TIM2_GetCapture1();

    TIM2_ClearFlag(TIM2_FLAG_CC1);

    /* debug */

    GPIO_WriteHigh(GPIOE, GPIO_PIN_3);

 

    /* wait a capture on cc1 */

      while((TIM2->SR1 & TIM2_FLAG_CC1) != TIM2_FLAG_CC1);

      /* Get CCR1 value*/

    ICValue2 = TIM2_GetCapture1();

    TIM2_ClearFlag(TIM2_FLAG_CC1);

    /* debug */

    GPIO_WriteLow(GPIOE, GPIO_PIN_3);

 

  /* Compute LSI clock frequency */

  // LSIClockFreq = (8*TIM2ClockFreq) / (ICValue2 - ICValue1);

    /* Insert a break point here */

  // while (1); 

}

So, the capture events were measured with the oscilloscope, an old fashion ''brute force'' method but very straightforward and effective 🙂

Well, actually the capture frequency of the events didn't changed when the IC prescaler was less then 8 thus confirming that the code captured correctly the LSI only when the IC PRESCALER was 8 and not less than that.

The only way to make things working was to rise up the CPU clock speed by adding the instruction

void main(void)

{

    CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);

...

at the beginning of the code.

The explanation was, therefore, that capturing the counter by using twice

ICValue1 = TIM2_GetCapture1();

and so on all the entire code made in this way is really time demanding for the cpu, leading to it is not capable to capture correctly the counter when the CPU clock is too slow. That's why ST developer recommended to ''capture only every 8 events !!! ''.

Stefano

lowpowermcu
Associate II
Posted on December 22, 2010 at 08:57

Hi piovan,

I didn't understand exactly your point but this is my understanding of the example:

using TIM2_ICInit() function you configure the capture when exactly it occurs.

So if you use TIM2_ICPSC_DIV4, the catpture event (flag) is set after 4 rising edges (orfalling edges that depends on the TIM2_ICPOLARITY_FALLING/TIM2_ICPOLARITYRISING)

consequently to compute the frequency of a signal (in the example it is the LSI) you should multiply by 4 (instaed of 8)in the formula below so it becomes

LSIClockFreq = (4*TIM2ClockFreq) / (ICValue2 - ICValue1);

Let's process the clock frequency, the general rule to compute the frequency value is:

capture divider * timer clock / (second capture - first capture)

In the example provided by ST,

 1- the capture is 8 (TIM2_ICPSC_DIV8)

 2- the timer clock is 2MHz (It is defined using #define TIM2ClockFreq  ((u32)2000000)

  Reminder: the timer is clocked at the same clock than the CPU and by default STM8 

  seems to run at 2MHz that is why it is defined at 2000000.

I hope this clear and it is useful for you.

Herzlich

 

MCU Lüfter

spiovan9
Associate II
Posted on December 22, 2010 at 10:50

hi,

what I'm concerned with the original example provided by ST is that if you test the example and put an IC prescaler division by 4 or less (instead of a division by 😎 the result you get in the variable 

LSIClockFreq = (8*TIM2ClockFreq) / (ICValue2 - ICValue1);

is NOT what you would expect (I mean 1/2 of 128KHz -> nearly 64 KHz). It keeps getting you still the same 128KHz or so, whatever IC division factor you put.

Otherwise, to get the LSIClockFreq value proportional to the IC division factor you have to rise the CPU clock as most as you can (i.e. full 16MHz). The reason why with low frequencies CPU the example doesn't work with IC DIV <= 4 is that the C code is time demanding and the CPU is not able to read the TIM2 capture counter in time.

Regards,

Stefano

lowpowermcu
Associate II
Posted on December 22, 2010 at 11:59

Hi piova,

yeah, I understand you now....

I didn't tested it as you described but I think that it would be better if the example uses the interrupts.

Herzlich,

 

MCU Lüfter