cancel
Showing results for 
Search instead for 
Did you mean: 

Measure 2 signals on TIM2 CC1, CC2

Rogers.Gary
Senior II
Posted on February 17, 2016 at 00:15

Hi,

On this link there's an example piece of code:

https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a%2f%2fmy.st.com%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex_mx_stm32%2fMultiple%20PWM%20input%20capture%20on%20one%20timer&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A7...

Hoping someone could clarify a few things.

In the example posted above, it uses TIM2 over 4 channels to measure 4 signals. It is configured to use PD3,PD4,PD6,PD7.

I do not see in the documentation where those pins can be used as an alternate function on TIM2. Can you explain that please?

Secondly, if I wanted to measure at least 2 frequencies as configured in this example, do they need to be the same but differ only in phase? Can they be different frequencies - but within the range of the configuration?

I need to measure 2 different signals. For example, I'm using PA.5 on TIM2. When I run the code it works fine and measures the signal's frequency.

Following the above example, I've tried adding PA.6 in the same way. The interrupt handler is configured for both TIM_IT_CC1, and TIM_IT_CC2. But, with a signal applied to PA.6, there is nothing happening. Code is below. Can someone explain why it does not work?

//set up to capture pulses on PA5, PA6

void TIM2_Configuration(void)

{

    NVIC_InitTypeDef NVIC_InitStructure;

    GPIO_InitTypeDef GPIO_InitStructure;

    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

        

    /* TIM2 Periph clock enable */

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

    /* TIM2 GPIO clock enable */

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);    

    

    /* TIM2 pin PA5, PA6 configuration */

    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_5 | GPIO_Pin_6;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Connect TIM2 pins to AF2 */

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_TIM2);

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_TIM2);    

    /* Time base configuration */

    TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);        

    TIM_TimeBaseStructure.TIM_Prescaler = 0;

    TIM_TimeBaseStructure.TIM_Period = (uint32_t)0xFFFFFFFF;

    TIM_TimeBaseStructure.TIM_ClockDivision = 0;

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

        

    TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;

    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising | TIM_ICPolarity_Falling;

    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;

    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;

    TIM_ICInitStructure.TIM_ICFilter = 0;

    TIM_ICInit(TIM2, &TIM_ICInitStructure);

    

    TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;

    TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising | TIM_ICPolarity_Falling;    

    TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;

    TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;

    TIM_ICInitStructure.TIM_ICFilter = 0;

    TIM_ICInit(TIM2, &TIM_ICInitStructure);    

    //Set up TIM2 interrrupt

    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure);    

    

    /* TIM enable counter */

    TIM_Cmd(TIM2, ENABLE);

    /* Enable the CC2 Interrupt Request */

    TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);      

    TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);          

    

    TIM_ClearFlag(TIM2, TIM_FLAG_CC1 | TIM_FLAG_CC2);        

}

#cc2 #stm32f4 #tim2 #cc1
9 REPLIES 9
Posted on February 17, 2016 at 04:41

His target hardware was an STM32F3-DISCO with an STM32F303VC

http://www.st.com/web/en/resource/technical/document/datasheet/DM00058181.pdf

You are time stamping edges in the time domain of TIM2, the frequencies of the signals you are measuring can be different. The delta measurement allows you to determine the period in ticks of the TIM2 clock. The upper end of the frequency will be limited by the resolution/granularity of the timer, and the synchronization circuit on the input (think nyquist and aliasing).

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Rogers.Gary
Senior II
Posted on February 17, 2016 at 04:51

hmmm...I don't understand. Not sure what nyquist has to do with this. The frequencies are within a handful of Hz (as in under 20)

With that in mind, as I asked - what's wrong with the code I have posted - should it work, or am I missing something?

thanks...

Posted on February 17, 2016 at 05:30

I don't see it measuring anything, and

TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising | TIM_ICPolarity_Falling;

doesn't do what you want. You'd presumably want TIM_ICPolarity_BothEdge if you want to time stamp both the rising and falling edges.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Rogers.Gary
Senior II
Posted on February 17, 2016 at 05:44

sorry, I still do not understand what you are saying.

Maybe I didn't make it clear. All I am trying to do on CC2 is the same thing I am doing on CC1, both using TIM2.

Here is the interrupt code I have that toggles the LED on CC1. I am trying to figure out why I do not get an LED toggle on CC2. Yes, the code isn't the same as CC1, and no code to actuially do anything with the CC2 value, but right now I am just trying to get the LED to toggle, and it is not even doing that.

I can apply a signal of 500Hz to PA5, and LED4 toggles. I then remove the signal and apply it to PA6, and LED6 does not toggle. So what is it...the setup? the interrupt? I must be really missing something obvious.

//Timer 2

__IO uint32_t uhIC3ReadValue1 = 0;

__IO uint32_t uhIC3ReadValue2 = 0;

__IO uint32_t uhCaptureNumber = 0;

__IO uint32_t uwCapture = 0;

__IO float32_t uwTIM1Freq = 0;

uint32_t TIM2_INT_RATE = (168000000 / 2);

void TIM2_IRQHandler(void)

{

    if(TIM_GetITStatus(TIM2, TIM_IT_CC1) == SET)

    {

        /* Clear TIM1 Capture compare interrupt pending bit */

        TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);  

       

        if(uhCaptureNumber == 0)

        {

            /* Get the Input Capture value */

            uhIC3ReadValue1 = TIM_GetCapture1(TIM2);

            uhCaptureNumber = 1;

        }

        else if(uhCaptureNumber == 1)

        {

            /* Get the Input Capture value */

            uhIC3ReadValue2 = TIM_GetCapture1(TIM2);

          

            /* Capture computation */

            if (uhIC3ReadValue2 > uhIC3ReadValue1)

            {

                uwCapture = (uhIC3ReadValue2 - uhIC3ReadValue1);

            }

            else if (uhIC3ReadValue2 < uhIC3ReadValue1)

            {

                uwCapture = ((0xFFFF - uhIC3ReadValue1) + uhIC3ReadValue2);

            }

            else

            {

                uwCapture = 0;

            }

            /* Frequency computation */

            uwTIM1Freq = (float32_t) ((TIM2_INT_RATE/1.0) / (uwCapture/1.0));

            STM_EVAL_LEDToggle(LED4);

           uhCaptureNumber = 0;

        }

        

    }

    else if(TIM_GetITStatus(TIM2, TIM_IT_CC2) == SET)

    {

        /* Clear TIM2 Capture compare interrupt pending bit */

        TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);        

        TIM_GetCapture2(TIM2);       

        STM_EVAL_LEDToggle(LED6);        

    }

}

Posted on February 17, 2016 at 05:50

Nyquist, think about what happens if you gate a 15MHz signal through a 20MHz synchronizer.

Clearly it's not going to be a problem if the synchronizer is running several orders of magnitude above the signal being resampled, but I'm just covering my bases.
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Posted on February 17, 2016 at 05:56

It's a 32-bit timer, it doesn't wrap at 0xFFFF, and for that matter the 16-bit would wrap at 0x10000. This is broken code from the SPL examples.

Where

uint32_t a, b, delta;

delta = b - a; // for ALL uint32_t values

Where you are time-stamping 3 consecutive edges, A, B, C

Period = C - A; // in ticks of the clock

FirstHalfTime = B - A;

SecondHalfTime = C - B;

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Rogers.Gary
Senior II
Posted on February 17, 2016 at 06:19

nope, not broken at all.

the code for CC1 works fine, and measures frequencies with better than 0.5Hz resolution.

not sure what you aren't saying, but thanks.

i think I'll try to figure it out in some other way...

Posted on February 17, 2016 at 14:55

You really need to work through the math here, do it first with 16-bit unsigned math, and then 32-bit unsigned math.

/* Capture computation */
if (uhIC3ReadValue2 > uhIC3ReadValue1)
{
uwCapture = (uhIC3ReadValue2 - uhIC3ReadValue1); 
}
else if (uhIC3ReadValue2 < uhIC3ReadValue1)
{
uwCapture = ((0xFFFF - uhIC3ReadValue1) + uhIC3ReadValue2); 
}

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Rogers.Gary
Senior II
Posted on February 17, 2016 at 19:10

you referring to the 0xFFFF ? I changed it to 32 bit and it makes no difference. Everything's declared as 32 bit, so what's the problem? It's a 32 bit counter.

clive1, why don't you try the code and discover that it does work? In fact it is precise to 0.1Hz.

Anyhow, isn't this off topic? I wasn't asking for an inquisition into my frequency calculation. There is no issue with that because it does work well.

All I am asking is, how can I read 2 differing signals, very close in frequency, on 2 different pins, using a single 32 bit timer, such as TIM2?

Is that possible, or not? Is the code I posted to set up the timer close, or what's wrong with it?

Thank you for helping to answer this question (or anyone else that wants to weigh in and help)