LPTIM encoder mode counting issue with LL Drivers on STM32L476RG Nucleo
I am currently working on a project using a sensor that sends quadrature encoded data. I have it wired so that the data is connected to comp1 and comp2 which in turn is read by the LPTIM1. LPTIM1 is set to encoder mode, but for some reason I for the life of me can't figure out why it won't count. If I use HAL drives instead everything works fine as I would expect. HAL_LPTIM_Encoder_Start_IT() is the function that seems to make all the difference and I cannot replicate what its doing with the LL drivers.
Mx Setup
Below is the working code for HAL drivers with what the registers look like for comparison.
LPTIM_HandleTypeDef hlptim1;
/* LPTIM1 init function */
void MX_LPTIM1_Init(void)
{
/* USER CODE BEGIN LPTIM1_Init 0 */
// uint32_t count = 0;
/* USER CODE END LPTIM1_Init 0 */
/* USER CODE BEGIN LPTIM1_Init 1 */
/* USER CODE END LPTIM1_Init 1 */
hlptim1.Instance = LPTIM1;
hlptim1.Init.Clock.Source = LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC;
hlptim1.Init.Clock.Prescaler = LPTIM_PRESCALER_DIV1;
hlptim1.Init.UltraLowPowerClock.Polarity = LPTIM_CLOCKPOLARITY_RISING_FALLING;
hlptim1.Init.UltraLowPowerClock.SampleTime = LPTIM_CLOCKSAMPLETIME_4TRANSITIONS;
hlptim1.Init.Trigger.Source = LPTIM_TRIGSOURCE_SOFTWARE;
hlptim1.Init.OutputPolarity = LPTIM_OUTPUTPOLARITY_HIGH;
hlptim1.Init.UpdateMode = LPTIM_UPDATE_IMMEDIATE;
hlptim1.Init.CounterSource = LPTIM_COUNTERSOURCE_EXTERNAL;
hlptim1.Init.Input1Source = LPTIM_INPUT1SOURCE_COMP1;
hlptim1.Init.Input2Source = LPTIM_INPUT2SOURCE_COMP2;
if (HAL_LPTIM_Init(&hlptim1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN LPTIM1_Init 2 */
/* Reset all interrupt flags for start up */
hlptim1.Instance->ICR = 0x7F;
HAL_LPTIM_Encoder_Start_IT(&hlptim1, 0x50);
hlptim1.Instance->IER &= ~(LPTIM_IT_UP | LPTIM_IT_DOWN);
/* USER CODE END LPTIM1_Init 2 */
}
LL Code and Register compare:
void MX_LPTIM1_Init(void)
{
/* USER CODE BEGIN LPTIM1_Init 0 */
// uint32_t count = 0;
/* USER CODE END LPTIM1_Init 0 */
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM1_CLKSOURCE_PCLK1);
/* Peripheral clock enable */
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_LPTIM1);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
/**LPTIM1 GPIO Configuration
PC1 ------> LPTIM1_OUT
*/
GPIO_InitStruct.Pin = LL_GPIO_PIN_1;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_1;
LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* LPTIM1 interrupt Init */
NVIC_SetPriority(LPTIM1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
NVIC_EnableIRQ(LPTIM1_IRQn);
/* USER CODE BEGIN LPTIM1_Init 1 */
/* USER CODE END LPTIM1_Init 1 */
LL_LPTIM_SetClockSource(LPTIM1, LL_LPTIM_CLK_SOURCE_INTERNAL);
LL_LPTIM_SetPrescaler(LPTIM1, LL_LPTIM_PRESCALER_DIV1);
LL_LPTIM_SetPolarity(LPTIM1, LL_LPTIM_OUTPUT_POLARITY_REGULAR);
LL_LPTIM_SetUpdateMode(LPTIM1, LL_LPTIM_UPDATE_MODE_IMMEDIATE);
LL_LPTIM_SetCounterMode(LPTIM1, LL_LPTIM_COUNTER_MODE_EXTERNAL);
LL_LPTIM_ConfigClock(LPTIM1, LL_LPTIM_CLK_FILTER_4, LL_LPTIM_CLK_POLARITY_RISING_FALLING);
LL_LPTIM_TrigSw(LPTIM1);
LL_LPTIM_SetInput1Src(LPTIM1, LL_LPTIM_INPUT1_SRC_COMP1);
LL_LPTIM_SetInput2Src(LPTIM1, LL_LPTIM_INPUT2_SRC_COMP2);
/* USER CODE BEGIN LPTIM1_Init 2 */
/* Reset all interrupt flags for start up */
// hlptim1.Instance->ICR = 0x7F;
// HAL_LPTIM_Encoder_Start_IT(&hlptim1, 0x50);
// hlptim1.Instance->IER &= ~(LPTIM_IT_UP | LPTIM_IT_DOWN);
LL_LPTIM_EnableIT_ARRM(LPTIM1);
LL_LPTIM_Enable(LPTIM1);
LL_LPTIM_SetAutoReload(LPTIM1, 32768UL);
LL_LPTIM_StartCounter(LPTIM1, LL_LPTIM_OPERATING_MODE_CONTINUOUS);
LL_LPTIM_EnableEncoderMode(LPTIM1);
/* USER CODE END LPTIM1_Init 2 */
}
The interesting thing is, I was able to get it to count in LL if using only Rising edge or only Falling edge but it was very inaccurate.
