Hello,
The code below uses the capture compare feature of TIM1 channel 2 (channel 3 is configured but not used for now) to capture both falling and rising edges on PE11 (channel 2) and PE13 (channel3), but only the rising edge detection generates an interrupt. Can you see why? Thanks.
TIM_ICInitTypeDef TIM_ICInitStructure ; GPIO_InitTypeDef GPIO_InitStructure ; NVIC_InitTypeDef NVIC_InitStructure ; // TIM1 clock enable RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE) ; // GPIOA clock enable RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE) ; // TIM1 channel 2 pin (PE.11) configuration (alternate function) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF ; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz ; GPIO_InitStructure.GPIO_OType = GPIO_OType_OD ; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(GPIOE, &GPIO_InitStructure) ; // TIM1 channel 3 pin (PE.13) configuration (alternate function) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF ; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz ; GPIO_InitStructure.GPIO_OType = GPIO_OType_OD ; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(GPIOE, &GPIO_InitStructure) ; // Connect TIM pins to AF2 GPIO_PinAFConfig(GPIOE, GPIO_PinSource11, GPIO_AF_TIM1) ; // Connect TIM pins to AF3 GPIO_PinAFConfig(GPIOE, GPIO_PinSource13, GPIO_AF_TIM1) ; // Enable the TIM1 global Interrupt NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn ; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0 ; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1 ; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE ; NVIC_Init(&NVIC_InitStructure) ; // 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 // An interrupt is generated on both rising and falling edges TIM_ICInitStructure.TIM_Channel = TIM_Channel_2 ; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_BothEdge ; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI ; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1 ; TIM_ICInitStructure.TIM_ICFilter = 0x5 ; TIM_ICInit(TIM1, &TIM_ICInitStructure) ; TIM_ICInitStructure.TIM_Channel = TIM_Channel_3 ; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_BothEdge ; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI ; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1 ; TIM_ICInitStructure.TIM_ICFilter = 0x0 ; TIM_ICInit(TIM1, &TIM_ICInitStructure) ; // assuming PCLK1 ticks at 42[MHz] -> slow down timer to 420 KHz // because TIM1 is a 16 bit counter, we can expect to be able to measure // a waveform of up to 156 milliseconds. TIM_PrescalerConfig(TIM1, 100, TIM_PSCReloadMode_Immediate) ; // TIM enable counter TIM_Cmd(TIM1, ENABLE) ; // Enable the CC2 Interrupt Request TIM_ITConfig(TIM1, TIM_IT_CC2, ENABLE) ; TIM_ITConfig(TIM1, TIM_IT_CC3, ENABLE) ;
The ISR looks like this:
void TIM1_CC_IRQHandler(void) { static unsigned int s_pending_rising_edge, s_rising_edge_capture_value, s_falling_edge_capture_value ; // Capture/Compare interrupt source ? if (TIM_GetITStatus(TIM1, TIM_IT_CC2) == SET) { // Clear TIM1 Capture compare interrupt pending bit TIM_ClearITPendingBit(TIM1, TIM_IT_CC2) ; if (s_pending_rising_edge == false) { // Falling edge detected. Get the Input Capture value s_falling_edge_capture_value = TIM_GetCapture2(TIM1) ; s_pending_rising_edge = true ; } else if (s_pending_rising_edge == true) { uint32_t l_waveform_width ; // Rising edge detected. Get the Input Capture value s_rising_edge_capture_value = TIM_GetCapture2(TIM1); // Capture computation if (s_rising_edge_capture_value > s_falling_edge_capture_value) { l_waveform_width = (s_rising_edge_capture_value - s_falling_edge_capture_value); } else if (s_rising_edge_capture_value < s_falling_edge_capture_value) { l_waveform_width = 0xFFFFFFFF - (s_rising_edge_capture_value - s_falling_edge_capture_value) ; } else { l_waveform_width = 0; } s_pending_rising_edge = false ; } } TIM_ClearFlag(TIM1, TIM_FLAG_CC2 | TIM_FLAG_CC3) ; }
I have also observed that even if I configure the system to respond to a falling edge, it only responds to a rising edge !
Very confusing. Your title is "Cannot detect rising edge".
You then say "but only the rising edge detection generates an interrupt"
And then you say "it only responds to a rising edge !"
Would you like to explain what other type of rising edge are you after?
When will students like you learn that us professionals have enough to do without trying to decrypt poorly explained problems?
The software does not detect falling edges - my bad. Can you see why? I was think of debouncing, but noise seems moderate.
I meant: The hardware filter feature does not have effect - falling edges seem to have the amount of noise, on the average.
Do you have a god complex or a superiority complex? And no, I am not a student. I regret not being to satisfy your spoon feeding needs...
At least two things concern me with this code.
a) How do the initial state of the statics impact things b) l_waveform_width = 0xFFFFFFFF - (s_rising_edge_capture_value - s_falling_edge) which has an off-by-one issue, that whole comparison logic tree can be replaced by a single line doing 32-bit math which wraps implicitly.
You're right. This is really only a very initial version of what I am going to do - currently I am trying to figure out why only rising edges are detected. I even change the switch connected to the eval board to no avail - the same thing...
In other words, if I connect my switch to channel 3
if (TIM_GetITStatus(TIM1, TIM_IT_CC3) == SET) { TIM_ClearITPendingBit(TIM1, TIM_IT_CC3) ; TIM_ClearFlag(TIM1, TIM_FLAG_CC3) ; }
This code suffers from the same issue - without static and computations of any kind...
And no, I am not a student.
Your posts suggest you should maybe consider becoming one.
it would be expected I regret not being to satisfy your spoon feeding needs...
Just read that carefully. Do you think it makes sense?
Yes I do. Please take you frustrations and inferiority complex somewhere else.
Yes I do
Oh dear. Then all I can assume is that you have not got a full command of English.
I'm not going to waste any more time on you, apart from making one last point: One of the things you must learn is that attention to detail is very important. If you can't formulate a post with accuracy, what hope have you got with the writing of reliable code?
is it so difficult to stop this war of words and concentrate on achieving the result?
For the sake of completion: This can probably be done using PWM input. It seems that STM32F4 chips cannot detect both a rising and falling edge on a CAPCOM channel.
I guess this is due to TIM1 doesn't support TIM_ICPolarity_BothEdge.
/** @defgroup TIM_Input_Capture_Polarity * @{ */ #define TIM_ICPolarity_Rising ((uint16_t)0x0000) #define TIM_ICPolarity_Falling ((uint16_t)0x0002) #define TIM_ICPolarity_BothEdge ((uint16_t)0x000A) #define IS_TIM_IC_POLARITY(POLARITY) (((POLARITY) == TIM_ICPolarity_Rising) || \ ((POLARITY) == TIM_ICPolarity_Falling)) #define IS_TIM_IC_POLARITY_LITE(POLARITY) (((POLARITY) == TIM_ICPolarity_Rising) || \ ((POLARITY) == TIM_ICPolarity_Falling)|| \ ((POLARITY) == TIM_ICPolarity_BothEdge))
/** * @brief Initializes the TIM peripheral according to the specified * parameters in the TIM_ICInitStruct. * @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral. * @param TIM_ICInitStruct: pointer to a TIM_ICInitTypeDef structure * that contains the configuration information for the specified TIM peripheral. * @retval None */ void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct) { /* Check the parameters */ assert_param(IS_TIM_CHANNEL(TIM_ICInitStruct->TIM_Channel)); assert_param(IS_TIM_IC_SELECTION(TIM_ICInitStruct->TIM_ICSelection)); assert_param(IS_TIM_IC_PRESCALER(TIM_ICInitStruct->TIM_ICPrescaler)); assert_param(IS_TIM_IC_FILTER(TIM_ICInitStruct->TIM_ICFilter)); if((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) || (TIMx == TIM4) ||(TIMx == TIM5)) { assert_param(IS_TIM_IC_POLARITY(TIM_ICInitStruct->TIM_ICPolarity)); } else { assert_param(IS_TIM_IC_POLARITY_LITE(TIM_ICInitStruct->TIM_ICPolarity)); }