Skip to main content
kahseng05
Associate II
March 18, 2015
Question

Using ch2 and ch4 as input capture

  • March 18, 2015
  • 26 replies
  • 4730 views
Posted on March 18, 2015 at 13:44

Hello,

I'd like to use channel 2 and channel 4 of TIM2 as input capture. Channel 2 work fine, but channel seems returning the timer counter. Here's the code:

GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM16, ENABLE);
/*Trigger pin configuration*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_1);
TIM_TimeBaseStructure.TIM_Prescaler = 71;
TIM_TimeBaseStructure.TIM_Period = 60000;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM16, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OC1Init(TIM16, &TIM_OCInitStructure);
TIM_CtrlPWMOutputs(TIM16, ENABLE);
TIM_Cmd(TIM16, ENABLE);
TIM_SetCompare1(TIM16, 10);
/*Echo Pin configuration */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource4, GPIO_AF_2);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_PWMIConfig(TIM2, &TIM_ICInitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11,GPIO_AF_1);
TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_PWMIConfig(TIM2, &TIM_ICInitStructure);
TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2);
TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);
TIM_SelectMasterSlaveMode(TIM2,TIM_MasterSlaveMode_Enable);
TIM_Cmd(TIM2, ENABLE);

#clive1
    This topic has been closed for replies.

    26 replies

    Tesla DeLorean
    Guru
    March 22, 2015
    Posted on March 22, 2015 at 15:54

    Ok,

    If you are timestamping the Rising Edge, then you're going to be able to measure the period, not the period+duty.

    If you are timestamping BothEdges, then you're going to need to make THREE measurements (A, B ,C). One pair of measurements in a 50 Hz (20 ms) servo example is going (C-A) is going to be ~20 ms and the other (B-A) is going to be 1~2 ms. You can read the pin state to confirm the phase of the signal.

    You could do TWO measurements and read the pin state to understand where high pulse (1-2 ms, mark) ended, or you can do a test that it's between 1-2, or less than 3 ms, because presumably the space is going to be 17 ms or more.

    Think about the points you're measuring, and the nature of the signals you're looking at.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    kahseng05
    kahseng05Author
    Associate II
    March 22, 2015
    Posted on March 22, 2015 at 17:50

    Hi, by repeating the method above, I'm able to use ultrasonic sensor 1 by 1, but when 2 ultrasonic sensors are used simultaneously, only 1 giving values. I would like to ask is there any thing I can do to solve it?

    Tesla DeLorean
    Guru
    March 22, 2015
    Posted on March 22, 2015 at 17:58

    You're interrupt handler is going to have to do a better job of selectively handling and clearing the interrupts on specific CCx sources, and how to hold state for each of the 2-4 channels you want to measure.

    Probably also want to remove the uart/printf stuff from there too, as it's going to bog everything down. Compute results in the interrupt, print them in a foreground task/loop.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    kahseng05
    kahseng05Author
    Associate II
    March 22, 2015
    Posted on March 22, 2015 at 19:08

    Sorry to ask that, how to know that the channel flag is clear. I just know how to clear the timer flag. Besides, I have no idea on what u mean by how to hold state for each of the channel.

    Tesla DeLorean
    Guru
    March 23, 2015
    Posted on March 23, 2015 at 02:37

    Hold the state information (the stuff you need to remember from call to call) in an arrayed structure, and not dozens of individually defined/named global variables.

    void TIM2_IRQHandler()
    {
    if (TIM_GetITStatus(TIM2, TIM_IT_CC1) == SET)
    {
    /* Clear TIM2 Capture compare interrupt pending bit */
    TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);
    // .. TIM_GetCapture1(TIM2);
    }
    if (TIM_GetITStatus(TIM2, TIM_IT_CC2) == SET)
    {
    /* Clear TIM2 Capture compare interrupt pending bit */
    TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
    // .. TIM_GetCapture2(TIM2);
    }
    // ..
    }

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    kahseng05
    kahseng05Author
    Associate II
    March 26, 2015
    Posted on March 26, 2015 at 18:00

    Hi, I encountered a problem that a very large and incorrect value pop out in the middle of the data I obtained even after applying your suggestion. How can I solve this problem? Thanks in advance. 

    Tesla DeLorean
    Guru
    March 26, 2015
    Posted on March 26, 2015 at 18:39

    Sanity check that the measurements for the two consecutive rising edges are ~20ms apart?

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    kahseng05
    kahseng05Author
    Associate II
    March 26, 2015
    Posted on March 26, 2015 at 19:50

    I tried to read the pin state using GPIOx->IDR, in order to know whether the consecutive rising edges is 20 ms, but it showed the values of 65535, 65487 and 65519. Is this results that I should obtain? If no, may you show me the proper method to check whether the rising edge is 20 ms apart?

    Tesla DeLorean
    Guru
    March 26, 2015
    Posted on March 26, 2015 at 20:03

    You're time stamping the edges in the timer, review the measurements, they are in ticks of the counter timebase.

    Measurements, A, B, C

    C-A should be approximately 20000 cycles at 1 MHz (1us), right? B-A some thing in the ~1000-2000 range. If the measurements look wrong, don't use them.

    For a 16-bit count, use 16-bit unsigned int's to do the math, it will wrap automatically in the desired fashion.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    kahseng05
    kahseng05Author
    Associate II
    March 28, 2015
    Posted on March 28, 2015 at 14:24

    Hi, I assigned the period of timer 2 interrupt to 0xFFFFFFFF and the prescaler 0. While in the interrupt, I put the coding below. Is it correct?

    cc[0] = TIM_GetCapture2(TIM2)/72;
    delta[0] = cc[0] - cc[1];
    cc[1] = cc[0];