2024-07-18 07:38 AM
Hi,
I basically have two PWM signals going into two pin that are set to be TIM4_CH1 and TIM4_CH2.
I setup both channels in slave mode and enabled the input capture mode on Rising mode.
When I enable only channel 1 and the code below get executed I retrieve the correct CCR1 values and consecutively I calculate the correct duty cycle.
Problem: When I enable both channels I get the same CCR1 and CCR2 value, all the time, so the duty cycle is always 100%
Input capture mode on "Both_Edges" mode work strangely because instead of getting the rising and falling edge captures consecutively I get them randomly: sometimes I just get the falling, sometimes only the rising and most of the time random pattern ( ex. rising, rising, falling, rising). So I opted to switch edge detection mode everytime I capture the value.
void TIM4_IRQ_PWM(void)
{
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 ( is_rising_ch1 )
{
pPWM4_1->FullPeriod = TIM_GetCapture1(TIM4);
TIM_CH1_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_CH1_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
TIM_CH1_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_CH1_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_CH1_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIM4, &TIM_CH1_ICInitStructure);
is_rising_ch1 = 0;
}
else
{
pPWM4_1->HighPeriod = TIM_GetCapture1(TIM4);
TIM_CH1_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_CH1_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_CH1_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_CH1_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_CH1_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIM4, &TIM_CH1_ICInitStructure);
is_rising_ch1 = 1;
}
//To prevent division by 0 on duty cycle calculation
if ( pPWM4_1->FullPeriod != 0 )
myPWMCalc(pPWM4_1);
}
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 ( is_rising_ch2 )
{
pPWM4_2->FullPeriod = TIM_GetCapture2(TIM4);
TIM_CH2_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_CH2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
TIM_CH2_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_CH2_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_CH2_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIM4, &TIM_CH2_ICInitStructure);
is_rising_ch2 = 0;
}
else
{
pPWM4_2->HighPeriod = TIM_GetCapture2(TIM4);
TIM_CH2_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_CH2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_CH2_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_CH2_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_CH2_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIM4, &TIM_CH2_ICInitStructure);
is_rising_ch2 = 1;
}
//To prevent division by 0 on duty cycle calculation
if ( pPWM4_2->FullPeriod != 0 )
myPWMCalc(pPWM4_2);
}
}
2024-07-18 11:30 AM
Related/duplicate:
Reading two PWM signals using only two channels. - STMicroelectronics Community
2024-07-19 01:46 AM
Hardware:
Library: Standard Peripheral Library ( I have to use this one )
What I did:
Problem: When Enabling only CH1 the captured values are different and the calculated Duty Cycle is correct, but as soon as I enable the CH2 as well the CCR1 and CCR2 I get to read are the same for all captures ( I basically read only the rising edge)
Pin 12 Configuration Code:
void myPWM4_Config_1(tmyPWMInput *me)
{
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_PWMIConfig(TIM4, &me->TIM_CH1_ICInitStructure);
// Select the TIM4Input Trigger: TI1FP1
TIM_SelectInputTrigger(TIM4, TIM_TS_TI1FP1);
// Select the slave Mode: Reset Mode
TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Reset);
TIM_SelectMasterSlaveMode(TIM4, TIM_MasterSlaveMode_Enable);
// Enables TIM4 peripheral Preload register on ARR.
TIM_ARRPreloadConfig(TIM4, ENABLE);
// Configures the TIM8 Update Request Interrupt source (SETS the CR1->URS bit)
//TIM_UpdateRequestConfig(TIM4, TIM_UpdateSource_Regular);
// 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);
}
Pin 13 Configuration Code:
void myPWM4_Config_2(tmyPWMInput *me)
{
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);
//TIM_PWMIConfig(TIM4, &me->TIM_CH2_ICInitStructure);
// Select the TIM4Input Trigger: TI2FP2
TIM_SelectInputTrigger(TIM4, TIM_TS_TI2FP2);
// Select the slave Mode: Reset Mode
TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Reset);
TIM_SelectMasterSlaveMode(TIM4, TIM_MasterSlaveMode_Enable);
// Enables TIM4peripheral Preload register on ARR.
TIM_ARRPreloadConfig(TIM4, ENABLE);
// Configures the TIM8 Update Request Interrupt source (SETS the CR1->URS bit)
TIM_UpdateRequestConfig(TIM4, TIM_UpdateSource_Regular);
// Enable the CC1 and the update Interrupt Request
TIM_ITConfig(TIM4, TIM_IT_CC2, ENABLE);
TIM_ClearFlag(TIM4, TIM_FLAG_Update);
TIM_Cmd(TIM4, ENABLE);
}
Hardware:
Library: Standard Peripheral Library ( I have to use this one )
What I did:
Problem: When Enabling only CH1 the captured values are different and the calculated Duty Cycle is correct, but as soon as I enable the CH2 as well the CCR1 and CCR2 I get to read are the same for all captures ( I basically read only the rising edge)
Pin 12 Configuration Code:
void myPWM4_Config_1(tmyPWMInput *me) { 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_PWMIConfig(TIM4, &me->TIM_CH1_ICInitStructure); // Select the TIM4Input Trigger: TI1FP1 TIM_SelectInputTrigger(TIM4, TIM_TS_TI1FP1); // Select the slave Mode: Reset Mode TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Reset); TIM_SelectMasterSlaveMode(TIM4, TIM_MasterSlaveMode_Enable); // Enables TIM4 peripheral Preload register on ARR. TIM_ARRPreloadConfig(TIM4, ENABLE); // Configures the TIM8 Update Request Interrupt source (SETS the CR1->URS bit) //TIM_UpdateRequestConfig(TIM4, TIM_UpdateSource_Regular); // 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); }
Pin 13 Configuration Code:
void myPWM4_Config_2(tmyPWMInput *me) { 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); //TIM_PWMIConfig(TIM4, &me->TIM_CH2_ICInitStructure); // Select the TIM4Input Trigger: TI2FP2 TIM_SelectInputTrigger(TIM4, TIM_TS_TI2FP2); // Select the slave Mode: Reset Mode TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Reset); TIM_SelectMasterSlaveMode(TIM4, TIM_MasterSlaveMode_Enable); // Enables TIM4peripheral Preload register on ARR. TIM_ARRPreloadConfig(TIM4, ENABLE); // Configures the TIM8 Update Request Interrupt source (SETS the CR1->URS bit) TIM_UpdateRequestConfig(TIM4, TIM_UpdateSource_Regular); // Enable the CC1 and the update Interrupt Request TIM_ITConfig(TIM4, TIM_IT_CC2, ENABLE); TIM_ClearFlag(TIM4, TIM_FLAG_Update); TIM_Cmd(TIM4, ENABLE); }
IRQ Code:
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 ( is_rising_ch1 )
{
pPWM4_1->FullPeriod = TIM_GetCapture1(TIM4);
TIM_CH1_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_CH1_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
TIM_CH1_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_CH1_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_CH1_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIM4, &TIM_CH1_ICInitStructure);
is_rising_ch1 = 0;
}
else
{
pPWM4_1->HighPeriod = TIM_GetCapture1(TIM4);
TIM_CH1_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_CH1_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_CH1_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_CH1_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_CH1_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIM4, &TIM_CH1_ICInitStructure);
is_rising_ch1 = 1;
}
//To prevent division by 0 on duty cycle calculation
if ( pPWM4_1->FullPeriod != 0 )
myPWMCalc(pPWM4_1);
}
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 ( is_rising_ch2 )
{
pPWM4_2->FullPeriod = TIM_GetCapture2(TIM4);
TIM_CH2_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_CH2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
TIM_CH2_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_CH2_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_CH2_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIM4, &TIM_CH2_ICInitStructure);
is_rising_ch2 = 0;
}
else
{
pPWM4_2->HighPeriod = TIM_GetCapture2(TIM4);
TIM_CH2_ICInitStructure.TIM_Channel = TIM_Channel_2;
TIM_CH2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_CH2_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_CH2_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_CH2_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIM4, &TIM_CH2_ICInitStructure);
is_rising_ch2 = 1;
}
//To prevent division by 0 on duty cycle calculation
if ( pPWM4_2->FullPeriod != 0 )
myPWMCalc(pPWM4_2);
}