上一章:STM32L0系列之【串口收发】
STM32L0系列有个LPTIM定时器,即lowpowertimer,低功耗定时器
可以看到可供LPTIM使用时钟源分为如下:
内部时钟源:LSE,LSI,HSI或APB时钟
外部时钟源:LPTIM输入的外部时钟源
ps:如果以LSE,LSI或外部时钟为时钟源时,能够从停止模式唤醒设备。
本文记录使用LSI为时钟源使用LPTIM
/**
* @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);
/**
* @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();
}
}
void LPTIM1_IRQHandler(void)
{
HAL_LPTIM_IRQHandler(&hlptim1);
}
启用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);
}
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);
}
下一章: