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) ; }
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...