2016-07-16 12:37 PM
Hi,
I need to measure the time a PWM signal spends high. I have the input capture side of this working fine, but with IC mode set to both edges, there are occasional issues with the signal measurement. It seems like the proper way to do this is by setting the IC config to capture on a falling edge, then using the timer in slave config to reset on a rising edge. Thus, the timestamp stored in the capture compare register would be the difference in time between the two events. Like I said, I know my GPIO config IC/timer config are right, but I cannot seem to get the timer to reset on a rising signal. Any ideas on what I'm missing here? I'm using the STM32 Cube libraries. Code:void
ConfigurePwmControlIn()
{
/*
Input capture for PWM in
*/
// Enable clocks
__TIM14_CLK_ENABLE();
__GPIOB_CLK_ENABLE();
// Configure GPIO
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF0_TIM14;
// TIM14_CH1 GPIO Config
// PB1
GPIO_InitStruct.Pin = GPIO_PIN_1;
// Commit the GPIO config
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
// Configure the NVIC
// For right now, we'll leave this at a pretty high priority
HAL_NVIC_SetPriority(TIM14_IRQn, 0, 1);
// Enable TIM14's global interrupt
HAL_NVIC_EnableIRQ(TIM14_IRQn);
// Configure the timer
rcPwmInTimer.Instance = TIM14;
rcPwmInTimer.Init.Period = 0xFFFF;
rcPwmInTimer.Init.Prescaler = 12;
rcPwmInTimer.Init.ClockDivision = 0;
rcPwmInTimer.Init.CounterMode = TIM_COUNTERMODE_UP;
rcPwmInTimer.Init.RepetitionCounter = 0;
// Commit the timer config
HAL_TIM_IC_Init(&rcPwmInTimer);
// Configure the input capture channel
rcPwmInIC.ICPolarity = TIM_ICPOLARITY_FALLING;
rcPwmInIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
rcPwmInIC.ICPrescaler = TIM_ICPSC_DIV1;
rcPwmInIC.ICFilter = 0;
// Commit the input capture config
HAL_TIM_IC_ConfigChannel(&rcPwmInTimer, &rcPwmInIC, TIM_CHANNEL_1);
// Setup external triggering
TIM_SlaveConfigTypeDef TIM_SlaveConfig;
TIM_SlaveConfig.InputTrigger = TIM_TS_TI1FP1;
TIM_SlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET;
TIM_SlaveConfig.TriggerPrescaler = TIM_TRIGGERPRESCALER_DIV1;
TIM_SlaveConfig.TriggerPolarity = TIM_CLOCKPOLARITY_RISING;
TIM_SlaveConfig.TriggerFilter = 0;
// Commit the trigger configuration
HAL_TIM_SlaveConfigSynchronization(&rcPwmInTimer, &TIM_SlaveConfig);
// Now start input capture
HAL_TIM_IC_Start_IT(&rcPwmInTimer, TIM_CHANNEL_1);
}
extern
''C''
void
TIM14_IRQHandler()
{
// Determine where this interrupt came from
if
(__HAL_TIM_GET_IT_SOURCE(&rcPwmInTimer, TIM_IT_CC1)!=RESET)
{
// Clear the flag
__HAL_TIM_CLEAR_IT(&rcPwmInTimer, TIM_IT_CC1);
// Get the captured value
PwmInCaptureData.LastCapture = HAL_TIM_ReadCapturedValue(&rcPwmInTimer, TIM_CHANNEL_1);
// Immeditly clear the timer
//__HAL_TIM_SetCounter(&rcPwmInTimer, 0);
}
}
Thanks!
#stm32 #no-hablo-hal #pwm-input-capture
2016-07-16 03:54 PM
PWM Input mode uses two channels capturing opposite edges of the same signal, and resetting every cycle (slave reset), so one channel holds the high duty and the other holds the period.
I've provide SPL code for this several times, but for HAL/Cube you'd need to find someone else who advocates for it.2016-07-18 02:28 PM
Hi,
In the package, you can refer to this example STM32Cube_FW_F0_V1.6.0\Projects\STM32F072B-Discovery\Examples\TIM\TIM_PWMInputRegards