Issue with reading pulse widths in input capture mode using two timers.
Dear All,
Board: Nucleo - H745ZI-Q
What am I trying to do ?
I am trying to measure pulse width of an signal using input capture mode of timer 2 channel 1. Then multiply that width by two and wait for that much time and generate an output pulse using output compare mode of timer 2 channel 2. Also, I use timer 3 channel 1 in input capture mode to measure pulse width of another signal. The second signal pulse width should start sequentially, only after pulse measurement of timer2 channel1.
What have I done?
I configure the GPIOs for Timer 2 channel 1 and Channel 2,that is pins PA0, PB3.
I configure the timer2 and timer 3 with ARR = 0xFFFF, PSC = 0x9, thus effective timer clock is 20MHz.
I configure the timer 2 channel 1 as input capture mode
I configure timer 2 channel 2 as output compare mode, mode "0001", upon match PB3 should go high.
I enable interrupt for timer 2 channel 1.
I configure the tim 3 ch 1 as input capture mode(PA6)
Code
Timer 2 config;
void readingPWTimer2()
{
RCC -> APB1LENR |= RCC_APB1LENR_TIM2EN;
TIM2->CR1 &= ~(TIM_CR1_DIR | TIM_CR1_CMS); /* Select the up counter mode */
TIM2->CR1 &= ~TIM_CR1_CKD;
TIM2->ARR = 0xFFFF; /* Set the Autoreload value */
TIM2->PSC = 0xC8 - 1; /* Set the Prescaler value, 1MHz*/
TIM2->EGR |= TIM_EGR_UG;
TIM2->SMCR = RESET;
//For Channel 1
/* Set the TIM2 timer channel 1 as input */
TIM2->CCMR1 |= TIM_CCMR1_CC1S_0;
//Sensitive to falling edge only
TIM2->CCER |= (TIM_CCER_CC1P) ;
TIM2->CCER |= TIM_CCER_CC1E;
TIM2->SR = ~TIM_SR_CC1IF;
// Enable the hardware capture compare interrupt for channel 1.
TIM2->DIER |= TIM_DIER_CC1IE;
TIM2->EGR |= TIM_EGR_UG;
//For channel 2
TIM2->SR = ~TIM_SR_CC2IF;
TIM2->CCMR1 |= TIM_CCMR1_OC2FE;
//Update event generation
TIM2->EGR |= TIM_EGR_UG;
TIM2->CCER |= TIM_CCER_CC2E;
TIM2->CR1 |= TIM_CR1_CEN; /* Enable the TIM peripheral */
//Enabling Interrupt..
NVIC_SetPriority(TIM2_IRQn, 0x05);
NVIC_EnableIRQ(TIM2_IRQn);
return;
}Timer 3 config:
void readingPWTimer3()
{
RCC -> APB1LENR |= RCC_APB1LENR_TIM3EN;
TIM3->CR1 &= ~(TIM_CR1_DIR | TIM_CR1_CMS);
TIM3->CR1 &= ~TIM_CR1_CKD;
TIM3->ARR = 0xFFFF;
TIM3->PSC = 0xC8 - 1;
TIM3->EGR |= TIM_EGR_UG;
TIM3->SMCR = RESET;
//For Channel 1
TIM3->CCMR1 |= TIM_CCMR1_CC1S_0;
//Sensitive to falling edge only
TIM3->CCER |= (TIM_CCER_CC1P);
//TIM3->CCER |= TIM_CCER_CC1E;
/* Clear the Capture event flag for channel 1 */
TIM3->SR = ~TIM_SR_CC1IF;
//TIM3->DIER |= TIM_DIER_CC1IE;
//// Generate update evnent so that all constants can be loaded
TIM3->EGR |= TIM_EGR_UG;
//For channel 2
TIM3->SR = ~TIM_SR_CC2IF;
TIM3->CCMR1 |= TIM_CCMR1_OC2FE;
//Update event generation
TIM3->EGR |= TIM_EGR_UG;
TIM3->CCER |= TIM_CCER_CC2E;
TIM3->CR1 |= TIM_CR1_CEN;
NVIC_SetPriority(TIM3_IRQn, 0x05);
NVIC_EnableIRQ(TIM3_IRQn);
return;
}IRQ Handler Tim2
void TIM2_IRQHandler(void)
{
if((TIM2->SR & TIM_SR_CC1IF))
Timer2CaptureCompare_CallbackCh1();
}
void Timer2CaptureCompare_CallbackCh1(void)
{
TIM2->SR &= ~(TIM_SR_CC1IF);
if( timer2Ch1Is_Falling_Captured == 0)
{
TIM2->EGR |= TIM_EGR_UG;
//set polarity to rising edge only
TIM2->CCER &= ~(TIM_CCER_CC1P) ;
timer2Ch1Is_Falling_Captured = 1;
}
else if(timer2Ch1Is_Falling_Captured == 1)
{
timer2Ch1IC = TIM2->CCR1 ;
TIM2->CCR2 = (2*timer2Ch1IC);
TIM2->CCMR1 |= (TIM_CCMR1_OC2M_0);
TIM2->CCER &= ~TIM_CCER_CC1E;
//TIM2->DIER &= ~TIM_DIER_CC1IE;
TIM3->CCER |= TIM_CCER_CC1E;
TIM3->SR = ~TIM_SR_CC1IF;
TIM3->DIER |= TIM_DIER_CC1IE;
TIM3->EGR |= TIM_EGR_UG;
TIM2->EGR |= TIM_EGR_UG;
} IRQ Handler Tim 3:
void TIM3_IRQHandler(void)
{
if((TIM3->SR & TIM_SR_CC1IF))
Timer3CaptureCompare_CallbackCh1();
}
void Timer3CaptureCompare_CallbackCh1(void)
{
TIM3->SR &= ~(TIM_SR_CC1IF);
if( timer3Ch1Is_Falling_Captured == 0)
{
TIM3->EGR |= TIM_EGR_UG;
//set polarity to rising edge only
TIM3->CCER &= ~(TIM_CCER_CC1P) ;
timer3Ch1Is_Falling_Captured = 1;
}
else if(timer3Ch1Is_Falling_Captured == 1)
{
timer3Ch1IC = TIM3->CCR1 ;
TIM3->CCR2 = (2*timer3Ch1IC);
TIM3->CCMR1 |= (TIM_CCMR1_OC2M_0);
TIM3->CCER &= ~TIM_CCER_CC1E;
//TIM3->DIER &= ~TIM_DIER_CC1IE;
TIM3->EGR |= TIM_EGR_UG;
}
}Issue: The pulse width read by tim2 ch 1 in variable timer2Ch1IC is correct and as expected but pulse width read by tim3 ch1 in variable timer3Ch1IC is not correct, its gives unexpectedly large value. Interesting thing is that if I user tim 2 ch 4 instead of tim3 ch 1 to measure pulse width of second signal, then its comes absolutely correct as expected.
Possible Approaches: Timer 3 ch1 may be getting interrupted by tim 2 ch 1 because of noise at its input pin.
For this I make priority of both the timer same but it does not help.
Also I try and disable interrupt for tim 2 ch1 after its job is done, but that does not help either.
I am missing something here.
Kindly help.
Thank you.
