cancel
Showing results for 
Search instead for 
Did you mean: 

LPTIM1 one-shot mode does not work

AZube.2
Associate III

I am using the LPTIM1 to aquire a sensor measurement trough interruption each T period. When I set it in continous mode (reference manual says: To enable the continuous counting, the CNTSTRT bit must be set) everything works out well.

HAL_LPTIM_TimeOut_Start_IT(&hlptim1, LPTIM1_PERIOD, LPTIM1_TIMEOUT);

LPTIM1-> CR |= 0x00000005; // Enable and software trigger LPTIM1 in continuous mode

However, I want to set it in single-shot mode (reference manual says: "To enable the one-shot counting, the SNGSTRT bit must be set). So I write:

HAL_LPTIM_TimeOut_Start_IT(&hlptim1, LPTIM1_PERIOD, LPTIM1_TIMEOUT);

LPTIM1-> CR |= 0x00000003; // Enable and software trigger LPTIM1 in single-shot mode

But the counter keeps going and going as in continuous mode, same behavior. Am I doing something wrong?? I tried both with TimeOut_Start_IT and Counter_Start_IT and the behavior is the same.

1 ACCEPTED SOLUTION

Accepted Solutions

Another plausible reason as to why it starts in continuous mode, you use the following function : HAL_LPTIM_TimeOut_Start_IT()

And when you take a look at the function definition there is : __HAL_LPTIM_START_CONTINUOUS(hlptim); in it. So you might want to use : HAL_LPTIM_SetOnce_Start instead.

Read here : http://www.disca.upv.es/aperles/arm_cortex_m3/llibre/st/STM32L486xx_User_Manual/group__lptim__exported__functions__group2.html#ga58a5c04b69996ada2493b5ba943902a0

View solution in original post

5 REPLIES 5
AZube.2
Associate III
LPTIM_HandleTypeDef hlptim1;
 
/* LPTIM1 init function */
void MX_LPTIM1_Init(void)
{
  hlptim1.Instance = LPTIM1;
  hlptim1.Init.Clock.Source = LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC;
  hlptim1.Init.Clock.Prescaler = LPTIM_PRESCALER_DIV64;
  hlptim1.Init.Trigger.Source = LPTIM_TRIGSOURCE_SOFTWARE;
  hlptim1.Init.OutputPolarity = LPTIM_OUTPUTPOLARITY_HIGH;
  hlptim1.Init.UpdateMode = LPTIM_UPDATE_IMMEDIATE;
  hlptim1.Init.CounterSource = LPTIM_COUNTERSOURCE_INTERNAL;
  hlptim1.Init.Input1Source = LPTIM_INPUT1SOURCE_GPIO;
  hlptim1.Init.Input2Source = LPTIM_INPUT2SOURCE_GPIO;
  if (HAL_LPTIM_Init(&hlptim1) != HAL_OK)
  {
    Error_Handler();
  }
}
 
void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef* lptimHandle)
{
 
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
  if(lptimHandle->Instance==LPTIM1)
  {
  /** Initializes the peripherals clocks
  */
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LPTIM1;
    PeriphClkInitStruct.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_LSE;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    {
      Error_Handler();
    }
 
    /* LPTIM1 clock enable */
    __HAL_RCC_LPTIM1_CLK_ENABLE();
 
    /* LPTIM1 interrupt Init */
    HAL_NVIC_SetPriority(LPTIM1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(LPTIM1_IRQn);
  }
}
 
void HAL_LPTIM_CompareMatchCallback(LPTIM_HandleTypeDef *hlptim)
{
	#if defined (DEBUG_LPTIM1) && (DEBUG_LPTIM1 == 1)
	APP_LOG(TS_ON, VLEVEL_M, "CALLBACK ++ \r\n\r\n");
	#endif
 
	// Timeout was reached, initiate I2c state machine to acquire one measurement
	StartI2C();
}

This is the initialization code and the callback used to begin aquiring the sensor measurement. The next code is how I start the LPTIM1 timer inside the main():

int main(void)
{
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_RTC_Init();
  MX_LoRaWAN_Init();
  MX_I2C2_Init();
  MX_LPTIM1_Init();
 
  GetInitialSysInfo();
 
  HAL_Delay(50);  //This small delay is needed in order to permit the counter callback work properly (Don't know why)
 
  //This activates LPTIM1 which has an interrupt callback (0,0 -> highest priority) enabled that gets a measurement each 2s-120s (can be chosen with LPTIM1_PERIOD)
  //if (HAL_LPTIM_Counter_Start_IT(&hlptim1, 0x04AA) != HAL_OK)
  if (HAL_LPTIM_TimeOut_Start_IT(&hlptim1, LPTIM1_PERIOD, LPTIM1_TIMEOUT) != HAL_OK)
development: measure each 10s 0x13FF
  {
    Error_Handler();
  }
//  LPTIM1-> CR |= 0x00000005;  //Enable and trigger LPTIM1 in continuous mode
  LPTIM1-> CR |= 0x00000003;  //Enable and trigger LPTIM1 in ONE-SHOT mode
 
  /* Infinite loop */
  while (1)
  {
	  MainInnerLoop();   //Processes the I2C state machine
  }
}

Another question I have is why do I need to add a small delay before starting LPTIM1. If this delay was not added the callback function did not execute de code in it. However, this is not my main concern since it already works. My main concern is to start the LPTIM1 in one-shot mode!

Thanks!

AZube.2
Associate III

No one can even try to answer, please? ST employees? @Louis AUDOLY​ ?

Feels like the datasheet and the reference manual are not enough or some info is missing. Or LPTIM1 does not work properly, but I doubt this is really the reason.

Try setting up WAVE bit in the LPTIM CFGR register to activate the set once mode (Fig 2).

Also for the delay : Fig 1

0693W00000QMqezQAD.png 

0693W00000QMqdSQAT.png

Another plausible reason as to why it starts in continuous mode, you use the following function : HAL_LPTIM_TimeOut_Start_IT()

And when you take a look at the function definition there is : __HAL_LPTIM_START_CONTINUOUS(hlptim); in it. So you might want to use : HAL_LPTIM_SetOnce_Start instead.

Read here : http://www.disca.upv.es/aperles/arm_cortex_m3/llibre/st/STM32L486xx_User_Manual/group__lptim__exported__functions__group2.html#ga58a5c04b69996ada2493b5ba943902a0

AZube.2
Associate III

Thank you so much @Community member​