Timer Input Capture duty cycle calculation is sometimes complementary
Hi!
I have two PWM signals coming into two MCU pins, that are two TIM4 channels. Channel 1 and Channel 2.
I initialized both Channel 1 and Channel 2 to input capture mode on Both Edges and enabled the Capture/Compare Interrupt (Not in slave master mode but free running)
I capture the value for 3 times and save it into an array and then proceed to calculate the full period as 3rd value minus the first one and the high period as 2nd value minus the first one.
The duty calculation is correct but sometimes instead of getting the correct duty cycle ( ex.70%) I get the complementary: 100% - 70% = 30%
Channel 1 Configuration:
RCC_ClocksTypeDef __RCC_CLOCK;
myPWMInputCtor(me);
RCC_GetClocksFreq(&__RCC_CLOCK);
me->clock = __RCC_CLOCK.PCLK1_Frequency * 2; //APB1
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
me->GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
me->GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
me->GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
me->GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
me->GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOD, &me->GPIO_InitStructure);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_TIM4);
TIM4_IRQHandler_ptf = TIM4_IRQ_PWM;
me->NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
me->NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
me->NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
me->NVIC_InitStructure.NVIC_IRQChannelCmd = 1;
NVIC_Init(&me->NVIC_InitStructure);
me->TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
me->TIM_TimeBaseStructure.TIM_Prescaler = 840 - 1;
me->TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
me->TIM_TimeBaseStructure.TIM_ClockDivision= TIM_CKD_DIV1;
me->TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM4, &me->TIM_TimeBaseStructure);
me->TIM_CH1_ICInitStructure.TIM_Channel = TIM_Channel_1;
me->TIM_CH1_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_BothEdge;
me->TIM_CH1_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
me->TIM_CH1_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
me->TIM_CH1_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIM4, &me->TIM_CH1_ICInitStructure);
TIM_SelectInputTrigger(TIM4, TIM_TS_TI1FP1);
// Select the slave Mode: Reset Mod
// Enable the CC1 and the update Interrupt Request
TIM_ITConfig(TIM4, TIM_IT_CC1, ENABLE);
TIM_ClearFlag(TIM4, TIM_FLAG_Update);
TIM_Cmd(TIM4, ENABLE);
Channel 2 Configuration:
RCC_ClocksTypeDef __RCC_CLOCK;
myPWMInputCtor(me);
RCC_GetClocksFreq(&__RCC_CLOCK);
me->clock = __RCC_CLOCK.PCLK1_Frequency * 2; //APB1
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
me->GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
me->GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
me->GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
me->GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
me->GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOD, &me->GPIO_InitStructure);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_TIM4);
TIM4_IRQHandler_ptf = TIM4_IRQ_PWM;
me->NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
me->NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
me->NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
me->NVIC_InitStructure.NVIC_IRQChannelCmd = 1;
NVIC_Init(&me->NVIC_InitStructure);
me->TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
me->TIM_TimeBaseStructure.TIM_Prescaler = 840 - 1;
me->TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
me->TIM_TimeBaseStructure.TIM_ClockDivision= TIM_CKD_DIV1;
me->TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM4, &me->TIM_TimeBaseStructure);
me->TIM_CH2_ICInitStructure.TIM_Channel = TIM_Channel_2;
me->TIM_CH2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_BothEdge;
me->TIM_CH2_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
me->TIM_CH2_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
me->TIM_CH2_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIM4, &me->TIM_CH2_ICInitStructure);
// Select the TIM8 Input Trigger: TI1FP1
TIM_SelectInputTrigger(TIM4, TIM_TS_TI2FP2);
// Select the slave Mode: Reset Mode
//TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Reset);
TIM_ITConfig(TIM4, TIM_IT_CC2, ENABLE);
TIM_ClearFlag(TIM4, TIM_FLAG_Update);
TIM_Cmd(TIM4, ENABLE);
duty cycle calculation:
if (TIM_GetITStatus(TIM4, TIM_IT_CC1) != RESET) {
tmyPWMInput *pPWM4_1 = &myCTRL.myHW.myPortDCfg.myPWM4_1; //PIN12
// Clear TIM8 Capture Compare1 interrupt pending bit
TIM_ClearITPendingBit(TIM4, TIM_IT_CC1);
if ( i != 3 ) ch1[i++] = TIM4->CCR1;
else if (i == 3) {
uint8_t j;
uint32_t full_period = ch1[2] - ch1[0];
uint32_t high_period = (ch1[1] - ch1[0]);
pPWM4_1->HighPeriod = high_period;
pPWM4_1->FullPeriod = full_period;
myPWMCalc(pPWM4_1);
i = 0;
}
}
if (TIM_GetITStatus(TIM4, TIM_IT_CC2) != RESET) {
tmyPWMInput *pPWM4_2 = &myCTRL.myHW.myPortDCfg.myPWM4_2; //PIN13
// Clear TIM8 Capture Compare1 interrupt pending bit
TIM_ClearITPendingBit(TIM4, TIM_IT_CC2);
if ( z != 3 ) ch2[z++] = TIM4->CCR2;
else if ( z == 3 ) {
uint32_t full_period = ch2[2] - ch2[0];
uint32_t high_period = (ch2[1] - ch2[0]);
pPWM4_2->HighPeriod = high_period;
pPWM4_2->FullPeriod = full_period;
myPWMCalc(pPWM4_2);
z = 0;
}
}
Any idea on how to workaround this? or why it does this?
