cancel
Showing results for 
Search instead for 
Did you mean: 

LPTIM1 CNT = ARR in half the time

JustSomeGuy
Associate III

I am making this code which, on an interrupt, is supposed to wake the system from STOP mode, put it into low powered run mode, and run LPTIM1 for 1 minute before triggering a flag and going back into STOP mode. I have PSC as 128 and ARR as 60962, so Fout = Fosc / ((PSC + 1) * (ARR + 1)) = 0.1667 Hz, which is 59.99 seconds period. however, in my program, the HAL function HAL_LPTIM_AutoReloadMatchCallback() gets called after exactly 30 seconds. why is that? did i set up something wrong? Relevant code:

LPTIM1 setup and ISR callback:

 

static void MX_LPTIM1_Init(void)
{

  /* USER CODE BEGIN LPTIM1_Init 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_DIV128;
  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;
  if (HAL_LPTIM_Init(&hlptim1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN LPTIM1_Init 2 */
  __HAL_LPTIM_AUTORELOAD_SET(&hlptim1, 60962);
  //hlptim1.Instance->ARR = 1016;
  /* USER CODE END LPTIM1_Init 2 */

}

//this function is called when the LP timer's CNT register = ARR
void HAL_LPTIM_AutoReloadMatchCallback(LPTIM_HandleTypeDef *hlptim)
{
	HAL_GPIO_WritePin(GPIO_PULSE_PORT, GPIO_PULSE_PIN, GPIO_PIN_SET); //turn on the blue LED
	//HAL_GPIO_TogglePin(GPIO_PULSE_PORT, GPIO_PULSE_PIN); //turn off the LED when the timer is finished
	RxTimerDone = 1;
}

//this function is called on every external interrupt. In this case,
//when the user PB is pressed on the dev board.
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin == GPIO_PIN_2) 	//if the input pin matches what it is supposed to be.
	{
		  pulseCount++;			//increment the number of pulses to send
		  HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_6);
	}
}

 

 

Clock config (Fosc = 131.072 kHz)

 

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
  RCC_OscInitStruct.MSIState = RCC_MSI_ON;
  RCC_OscInitStruct.MSICalibrationValue = 0;
  RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_1;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPTIM1;
  PeriphClkInit.LptimClockSelection = RCC_LPTIM1CLKSOURCE_PCLK;

  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

 

and main():

 

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SPI1_Init();
  MX_LPTIM1_Init();
  /* USER CODE BEGIN 2 */
  HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  //lp timer -> 1 minute period for lora pulses
	  //TIM2 -> pulse output
	  //
	  if((pulseCount > 0) && (processStarted == 0))
	  {
		  SystemClock_Config();//STOP mode turns off all system clocks; this command resets them
		  enter_LPRun();       //enter low power mode
		  HAL_LPTIM_PWM_Start_IT(&hlptim1, LPTIMER_PERIOD, LPTIMER_PULSE); //begin the timer for the pulse output in interrupt mode

		  processStarted = 1;
	  }

	  if(pulseCount <= 0 && (processStarted == 1) && (RxTimerDone == 1))
	  {
		  RxTimerDone = 0;
		  HAL_LPTIM_PWM_Stop_IT(&hlptim1);		//stop the LP timer
		  processStarted = 0; 					//clear the flag bit to indicate that process is not ongoing
		  __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); 	//this bit has to be cleared before entering stop mode
		  HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); //enter STOP mode
	  }
	  //HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);

  }
  /* USER CODE END 3 */
}

 

enter_LPRun():

void enter_LPRun(void)
{
    /* 1. Each digital IP clock must be enabled or disabled by using the
                   RCC_APBxENR and RCC_AHBENR registers */
    RCC->APB1ENR |= RCC_APB1ENR_PWREN;
    RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
    /* 2. The frequency of the system clock must be decreased to not exceed the
          frequency of f_MSI range1. */
    // Reinitialize peripherals dependent on clock speed

    //no peripherals to initialize

    /* 3. The regulator is forced in low-power mode by software
          (LPRUN and LPSDSR bits set ) */
    PWR->CR &= ~PWR_CR_LPRUN; // Be sure LPRUN is cleared!

    PWR->CR |= PWR_CR_LPSDSR; // must be set before LPRUN
    PWR->CR |= PWR_CR_LPRUN; // enter low power run mode
}

 

 

0 REPLIES 0