1.LPTIM介绍
STM32L0系列有个LPTIM定时器,即lowpowertimer,低功耗定时器
可以看到可供LPTIM使用时钟源分为如下:
内部时钟源:LSE,LSI,HSI或APB时钟
外部时钟源:LPTIM输入的外部时钟源
ps:如果以LSE,LSI或外部时钟为时钟源时,能够从停止模式唤醒设备。
本文记录使用LSI为时钟源使用LPTIM
2.配置时钟源并且启动
- /**
- * @brief System Clock Configuration
- * @retval None
- */
- 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 CPU, AHB and APB busses clocks
- */
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_MSI;
- RCC_OscInitStruct.LSIState = RCC_LSI_ON;
- RCC_OscInitStruct.MSIState = RCC_MSI_ON;
- RCC_OscInitStruct.MSICalibrationValue = 0;
- RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
- if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
- {
- Error_Handler();
- }
- /** Initializes the CPU, AHB and APB busses 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_RTC|RCC_PERIPHCLK_LPTIM1;
- PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
- PeriphClkInit.LptimClockSelection = RCC_LPTIM1CLKSOURCE_LSI;
- if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
- {
- Error_Handler();
- }
- }
复制代码
以上是完整的时钟配置函数,使用LPTIM最主要的配置由如下构成:
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI;
- RCC_OscInitStruct.LSIState = RCC_LSI_ON;
- HAL_RCC_OscConfig(&RCC_OscInitStruct);
- PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPTIM1;
- PeriphClkInit.LptimClockSelection = RCC_LPTIM1CLKSOURCE_LSI;
- HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
复制代码
3.初始化配置LPTIM
- /**
- * @brief LPTIM1 Initialization Function
- * @param None
- * @retval None
- */
- void MX_LPTIM1_Init(void) //0.037Mhz (1+period / 0.037(37000)) = 1s period=36999
- {
- hlptim1.Instance = LPTIM1;
- hlptim1.Init.Clock.Source = LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC;
- hlptim1.Init.Clock.Prescaler = LPTIM_PRESCALER_DIV1;
- 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();
- }
- }
复制代码
4.LPTIM中断处理函数
- void LPTIM1_IRQHandler(void)
- {
- HAL_LPTIM_IRQHandler(&hlptim1);
- }
复制代码
5.启用LPTIM,中断触发回调函数
启用LPTIM分为多种方式:如脉冲,PWM,计数等。
具体可参考HAL_LPTIM_IRQHandler函数的实现。
- /**
- * @brief Handle LPTIM interrupt request.
- * @param hlptim LPTIM handle
- * @retval None
- */
- void HAL_LPTIM_IRQHandler(LPTIM_HandleTypeDef *hlptim)
- {
- /* Compare match interrupt */
- if (__HAL_LPTIM_GET_FLAG(hlptim, LPTIM_FLAG_CMPM) != RESET)
- {
- if (__HAL_LPTIM_GET_IT_SOURCE(hlptim, LPTIM_IT_CMPM) != RESET)
- {
- /* Clear Compare match flag */
- __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPM);
- /* Compare match Callback */
- #if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1)
- hlptim->CompareMatchCallback(hlptim);
- #else
- HAL_LPTIM_CompareMatchCallback(hlptim);
- #endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */
- }
- }
- /* Autoreload match interrupt */
- if (__HAL_LPTIM_GET_FLAG(hlptim, LPTIM_FLAG_ARRM) != RESET)
- {
- if (__HAL_LPTIM_GET_IT_SOURCE(hlptim, LPTIM_IT_ARRM) != RESET)
- {
- /* Clear Autoreload match flag */
- __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARRM);
- /* Autoreload match Callback */
- #if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1)
- hlptim->AutoReloadMatchCallback(hlptim);
- #else
- HAL_LPTIM_AutoReloadMatchCallback(hlptim);
- #endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */
- }
- }
- /* Trigger detected interrupt */
- if (__HAL_LPTIM_GET_FLAG(hlptim, LPTIM_FLAG_EXTTRIG) != RESET)
- {
- if (__HAL_LPTIM_GET_IT_SOURCE(hlptim, LPTIM_IT_EXTTRIG) != RESET)
- {
- /* Clear Trigger detected flag */
- __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_EXTTRIG);
- /* Trigger detected callback */
- #if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1)
- hlptim->TriggerCallback(hlptim);
- #else
- HAL_LPTIM_TriggerCallback(hlptim);
- #endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */
- }
- }
- /* Compare write interrupt */
- if (__HAL_LPTIM_GET_FLAG(hlptim, LPTIM_FLAG_CMPOK) != RESET)
- {
- if (__HAL_LPTIM_GET_IT_SOURCE(hlptim, LPTIM_IT_CMPOK) != RESET)
- {
- /* Clear Compare write flag */
- __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_CMPOK);
- /* Compare write Callback */
- #if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1)
- hlptim->CompareWriteCallback(hlptim);
- #else
- HAL_LPTIM_CompareWriteCallback(hlptim);
- #endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */
- }
- }
- /* Autoreload write interrupt */
- if (__HAL_LPTIM_GET_FLAG(hlptim, LPTIM_FLAG_ARROK) != RESET)
- {
- if (__HAL_LPTIM_GET_IT_SOURCE(hlptim, LPTIM_IT_ARROK) != RESET)
- {
- /* Clear Autoreload write flag */
- __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_ARROK);
- /* Autoreload write Callback */
- #if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1)
- hlptim->AutoReloadWriteCallback(hlptim);
- #else
- HAL_LPTIM_AutoReloadWriteCallback(hlptim);
- #endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */
- }
- }
- /* Direction counter changed from Down to Up interrupt */
- if (__HAL_LPTIM_GET_FLAG(hlptim, LPTIM_FLAG_UP) != RESET)
- {
- if (__HAL_LPTIM_GET_IT_SOURCE(hlptim, LPTIM_IT_UP) != RESET)
- {
- /* Clear Direction counter changed from Down to Up flag */
- __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_UP);
- /* Direction counter changed from Down to Up Callback */
- #if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1)
- hlptim->DirectionUpCallback(hlptim);
- #else
- HAL_LPTIM_DirectionUpCallback(hlptim);
- #endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */
- }
- }
- /* Direction counter changed from Up to Down interrupt */
- if (__HAL_LPTIM_GET_FLAG(hlptim, LPTIM_FLAG_DOWN) != RESET)
- {
- if (__HAL_LPTIM_GET_IT_SOURCE(hlptim, LPTIM_IT_DOWN) != RESET)
- {
- /* Clear Direction counter changed from Up to Down flag */
- __HAL_LPTIM_CLEAR_FLAG(hlptim, LPTIM_FLAG_DOWN);
- /* Direction counter changed from Up to Down Callback */
- #if (USE_HAL_LPTIM_REGISTER_CALLBACKS == 1)
- hlptim->DirectionDownCallback(hlptim);
- #else
- HAL_LPTIM_DirectionDownCallback(hlptim);
- #endif /* USE_HAL_LPTIM_REGISTER_CALLBACKS */
- }
- }
- }
复制代码
这里示例TimeOut的方式回调。
开启LPTIM定时器需要调用 HAL_LPTIM_TimeOut_Start_IT
- //HAL_LPTIM_TimeOut_Start_IT <=> HAL_LPTIM_CompareMatchCallback
- void HAL_LPTIM_CompareMatchCallback(LPTIM_HandleTypeDef *hlptim)
- {
- HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8);
- }
复制代码
6.main.c 主函数
- int main(void)
- {
- HAL_Init();
- /* Configure the system clock */
- SystemClock_Config();
- MX_LPTIM1_Init();
- //(1+period / 0.037(37000)) = 1s period=36999 1s触发一次
- HAL_LPTIM_TimeOut_Start_IT(&hlptim1,36999,1000);
- while(1){
- HAL_Delay(1000);
- }
复制代码
|