2015-03-18 05:44 AM
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
2015-03-18 05:56 AM
You'll need to use ''Input Capture'', not PWM Input, which pairs channels 1 and 2 and resets the counter.
2015-03-18 06:03 AM
I was always under the impression that i'm using input capture. Obviously, that is not the case. Can you show me a little bit how to use input capture, as i don't know much about it.
2015-03-18 06:12 AM
No, you're capturing period and duty information, and resetting the timer. Input Capture just latches the current count into the compare register at the edge. There you can use all 4 channels.
ie TIM1->CCR2 = TIM2->CNT; // At rising edge STM32F4xx_DSP_StdPeriph_Lib_V1.3.0\Project\STM32F4xx_StdPeriph_Examples\TIM\TIM_InputCapture\main.c/* TIM1 configuration: Input Capture mode ---------------------
The external signal is connected to TIM1 CH2 pin (PE.11)
The Rising edge is used as active edge,
The TIM1 CCR2 is used to compute the frequency value
------------------------------------------------------------ */
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_ICInit(TIM1, &TIM_ICInitStructure);
/* TIM enable counter */
TIM_Cmd(TIM1, ENABLE);
/* Enable the CC2 Interrupt Request */
TIM_ITConfig(TIM1, TIM_IT_CC2, ENABLE);
2015-03-18 06:31 AM
when i use TIM_GetCapture2(TIM2) i get a constant value, is the code writen like tis?
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_ICInit(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);
TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);
2015-03-18 07:24 AM
No, you lose this
TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2);
TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);
TIM_SelectMasterSlaveMode(TIM2,TIM_MasterSlaveMode_Enable);
And in the interrupt you do delta measurements of the clock ticks vs the rising edges.
So you have a pair of consecutive measurements, A and B
Where delta ticks = B - A; and you determine the period/frequency from whatever you've configured your time base to be.
If you need period and duty, then you'll need to trigger on BothEdges and make three measurements. For a 50 Hz servo system you'd figure out which pair represented the 20ms/50Hz duration, and then the other pairing would provide you with the pulse width/duty of the signal.
2015-03-18 08:10 AM
Erm... how do i determine the clock ticks and rising edges, how to count the interrupt and do i still have to use TIM_GetCapture1(TIM2) to get the value?
2015-03-18 10:34 AM
If you're using channel 2
TIM_GetCapture2(TIM2); or TIM2->CCR2You save the value in two, or more, consecutive interrupts. Or record using DMAIn the BothEdges trigger you can read the pin state, and you should be able to determine which is the 1-2ms pulse, vs the 20 ms period, just by looking at the magnitude.How large the ticks are will depend on how you've configure the TIM's time base. Going to default to a maximal count (16-bit or 32-bit depending on the STM32 and TIM), and DIV1 prescaler from the APB's TIMCLK, which is nominally 2x the APB clock except for the DIV1 case.2015-03-18 09:11 PM
So, i will be using TIM_GetCapture in interrupt function and what do u mean read the pin state?
2015-03-19 12:56 AM
Yes, you read the time stamp stored in the capture register after it generates the interrupt.
You can read the state of the GPIO pin (High or Low) if that's important in the case where you're triggering on either edge and you want to know which. You can look at GPIOx->IDR, or use the API, or you can infer the mark/space from the timing, or a count of the interrupts, etc.