Skip to main content
Graduate II
July 2, 2024
Question

LPTIM1 CNT = ARR in half the time

  • July 2, 2024
  • 0 replies
  • 561 views

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
}

 

 

    This topic has been closed for replies.