硬汉嵌入式论坛

 找回密码
 立即注册
查看: 2935|回复: 4
收起左侧

[TIMER] STM32H7的低功耗定时器LPTIM,实现芯片进入停机状态后做PWM输出

[复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107031
QQ
发表于 2018-8-24 00:22:26 | 显示全部楼层 |阅读模式
说明:

测试的官方例子:LPTIM_PWM_LSE。

使用LPTIM的好处是系统处于睡眠,停机状态可以正常工作(除了待机模式)。

这个例子选择了LSE作为LPTIM1的时钟源,输出一个占空比50%,频率327.68KHz的波形。

并且设了一个用户按键唤醒停机模式,唤醒后停止PWM输出。


波形输出:
88.png



测试代码:

此功能重点还是函数HAL_LPTIM_Init的参数配置学习。
  1. /* Private typedef -----------------------------------------------------------*/
  2. /* Private define ------------------------------------------------------------*/
  3. /* Set the Maximum value of the counter (Auto-Reload) that defines the Period */
  4. #define PeriodValue             (uint32_t) (100 - 1)

  5. /* Set the Compare value that defines the duty cycle */
  6. #define PulseValue              (uint32_t) (50 - 1)

  7. /* Private macro -------------------------------------------------------------*/
  8. /* Private variables ---------------------------------------------------------*/
  9. /* LPTIM handle declaration */
  10. LPTIM_HandleTypeDef             LptimHandle;

  11. /* Clocks structure declaration */
  12. RCC_PeriphCLKInitTypeDef        RCC_PeriphCLKInitStruct;

  13. /* Private function prototypes -----------------------------------------------*/
  14. static void SystemClock_Config(void);
  15. static HAL_StatusTypeDef LSE_ClockEnable(void);
  16. static void Error_Handler(void);
  17. static void CPU_CACHE_Enable(void);
  18. /* Private functions ---------------------------------------------------------*/

  19. /**
  20.   * @brief  Main program
  21.   * @param  None
  22.   * @retval None
  23.   */
  24. int main(void)
  25. {
  26.   /* Enable the CPU Cache */
  27.   CPU_CACHE_Enable();
  28.   
  29.   /* STM32H7xx HAL library initialization:
  30.        - Systick timer is configured by default as source of time base, but user
  31.          can eventually implement his proper time base source (a general purpose
  32.          timer for example or other time source), keeping in mind that Time base
  33.          duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
  34.          handled in milliseconds basis.
  35.        - Set NVIC Group Priority to 4
  36.        - Low Level Initialization
  37.      */
  38.   HAL_Init();

  39.   /* Configure the system clock to 400 MHz */
  40.   SystemClock_Config();

  41.   /* Configure LED2 */
  42.   BSP_LED_Init(LED2);
  43.   
  44.   /* User push-button (EXTI_Line15_10) will be used to wakeup the system from Stop mode */
  45.   BSP_PB_Init(BUTTON_USER, BUTTON_MODE_EXTI);

  46.   /* Enable the LSE Clock */
  47.   if (LSE_ClockEnable() != HAL_OK)
  48.   {
  49.     Error_Handler();
  50.   }
  51.   
  52.   /* ### - 1 - Re-target the LSE to Clock the LPTIM Counter ################# */
  53.   /* Select the LSE clock as LPTIM peripheral clock */
  54.   RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LPTIM1;
  55.   RCC_PeriphCLKInitStruct.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_LSE;  
  56.   HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct);
  57.   
  58.   
  59.   /* ### - 2 - Initialize the LPTIM peripheral ############################## */
  60.   /*
  61.    *  Instance        = LPTIM1
  62.    *  Clock Source    = APB or LowPowerOSCillator (in this example LSE is
  63.    *                    already selected from the RCC stage)
  64.    *  Counter source  = External event.
  65.    *  Clock prescaler = 1 (No division)
  66.    *  Counter Trigger = Software trigger
  67.    *  Output Polarity = High
  68.    *  Update mode     = Immediate (Registers are immediately updated after any
  69.    *                    write access)
  70.    */

  71.   LptimHandle.Instance = LPTIM1;
  72.   
  73.   LptimHandle.Init.Clock.Source    = LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC;
  74.   LptimHandle.Init.Clock.Prescaler = LPTIM_PRESCALER_DIV1;  
  75.   LptimHandle.Init.CounterSource   = LPTIM_COUNTERSOURCE_INTERNAL;
  76.   LptimHandle.Init.Trigger.Source  = LPTIM_TRIGSOURCE_SOFTWARE;
  77.   LptimHandle.Init.OutputPolarity  = LPTIM_OUTPUTPOLARITY_HIGH;
  78.   LptimHandle.Init.UpdateMode      = LPTIM_UPDATE_IMMEDIATE;
  79.   LptimHandle.Init.Input1Source    = LPTIM_INPUT1SOURCE_GPIO;
  80.   LptimHandle.Init.Input2Source    = LPTIM_INPUT2SOURCE_GPIO;
  81.   
  82.   /* Initialize LPTIM peripheral according to the passed parameters */
  83.   if (HAL_LPTIM_Init(&LptimHandle) != HAL_OK)
  84.   {
  85.     Error_Handler();
  86.   }

  87.   /* ### - 3 - Start counting in interrupt mode ############################# */
  88.   /*
  89.    *  Period = 99
  90.    *  Pulse  = 49
  91.    *  According to this configuration, the duty cycle will be equal to 50%
  92.    */
  93.   if (HAL_LPTIM_PWM_Start(&LptimHandle, PeriodValue, PulseValue) != HAL_OK)
  94.   {
  95.     Error_Handler();
  96.   }
  97.   
  98.   /* ### - 4 - Enter in Stop mode ########################################### */
  99.   HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
  100.   
  101.   /* ### - 5 - Stop counting when leaving Stop mode ########################## */
  102.   if (HAL_LPTIM_PWM_Stop(&LptimHandle) != HAL_OK)
  103.   {
  104.     Error_Handler();
  105.   }

  106.   /* Infinite Loop */
  107.   while (1)
  108.   {        
  109.   }
  110. }

  111. /**
  112.   * @brief  System Clock Configuration
  113.   *         The system Clock is configured as follow :
  114.   *            System Clock source            = PLL (HSE BYPASS)
  115.   *            SYSCLK(Hz)                     = 400000000 (CPU Clock)
  116.   *            HCLK(Hz)                       = 200000000 (AXI and AHBs Clock)
  117.   *            AHB Prescaler                  = 2
  118.   *            D1 APB3 Prescaler              = 2 (APB3 Clock  100MHz)
  119.   *            D2 APB1 Prescaler              = 2 (APB1 Clock  100MHz)
  120.   *            D2 APB2 Prescaler              = 2 (APB2 Clock  100MHz)
  121.   *            D3 APB4 Prescaler              = 2 (APB4 Clock  100MHz)
  122.   *            HSE Frequency(Hz)              = 8000000
  123.   *            PLL_M                          = 4
  124.   *            PLL_N                          = 400
  125.   *            PLL_P                          = 2
  126.   *            PLL_Q                          = 4
  127.   *            PLL_R                          = 2
  128.   *            VDD(V)                         = 3.3
  129.   *            Flash Latency(WS)              = 4
  130.   * @param  None
  131.   * @retval None
  132.   */
  133. static void SystemClock_Config(void)
  134. {
  135.   RCC_ClkInitTypeDef RCC_ClkInitStruct;
  136.   RCC_OscInitTypeDef RCC_OscInitStruct;
  137.   HAL_StatusTypeDef ret = HAL_OK;
  138.   
  139.   /*!< Supply configuration update enable */
  140.   MODIFY_REG(PWR->CR3, PWR_CR3_SCUEN, 0);

  141.   /* The voltage scaling allows optimizing the power consumption when the device is
  142.      clocked below the maximum system frequency, to update the voltage scaling value
  143.      regarding system frequency refer to product datasheet.  */
  144.   __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  145.   while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
  146.   
  147.   /* Enable HSE Oscillator and activate PLL with HSE as source */
  148.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  149.   RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
  150.   RCC_OscInitStruct.HSIState = RCC_HSI_OFF;
  151.   RCC_OscInitStruct.CSIState = RCC_CSI_OFF;
  152.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  153.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;

  154.   RCC_OscInitStruct.PLL.PLLM = 4;
  155.   RCC_OscInitStruct.PLL.PLLN = 400;
  156.   RCC_OscInitStruct.PLL.PLLP = 2;
  157.   RCC_OscInitStruct.PLL.PLLR = 2;
  158.   RCC_OscInitStruct.PLL.PLLQ = 4;

  159.   RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
  160.   RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2;
  161.   ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);
  162.   if(ret != HAL_OK)
  163.   {
  164.     Error_Handler();
  165.   }
  166.   
  167. /* Select PLL as system clock source and configure  bus clocks dividers */
  168.   RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_D1PCLK1 | RCC_CLOCKTYPE_PCLK1 | \
  169.                                  RCC_CLOCKTYPE_PCLK2  | RCC_CLOCKTYPE_D3PCLK1);

  170.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  171.   RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
  172.   RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
  173.   RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;  
  174.   RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
  175.   RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
  176.   RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
  177.   ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4);
  178.   if(ret != HAL_OK)
  179.   {
  180.     Error_Handler();
  181.   }

  182. }
  183. /**
  184.   * @brief  Enable External Low Speed Clock (LSE)
  185.   * @param  None
  186.   * @retval Status
  187.   */
  188. static HAL_StatusTypeDef LSE_ClockEnable(void)
  189. {
  190.   RCC_OscInitTypeDef RCC_OscInitStruct;
  191.   
  192.   /* Enable LSE clock */
  193.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
  194.   RCC_OscInitStruct.LSEState = RCC_LSE_ON;
  195.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  196.   return (HAL_RCC_OscConfig(&RCC_OscInitStruct));
  197. }

  198. /**
  199.   * @brief  This function is executed in case of error occurrence.
  200.   * @param  None
  201.   * @retval None
  202.   */
  203. static void Error_Handler(void)
  204. {
  205.   /* Turn LED2 on */
  206.   BSP_LED_On(LED2);
  207.   while (1)
  208.   {
  209.   }
  210. }

  211. /**
  212.   * @brief  CPU L1-Cache enable.
  213.   * @param  None
  214.   * @retval None
  215.   */
  216. static void CPU_CACHE_Enable(void)
  217. {
  218.   /* Enable I-Cache */
  219.   SCB_EnableICache();

  220.   /* Enable D-Cache */
  221.   SCB_EnableDCache();
  222. }

  223. #ifdef  USE_FULL_ASSERT

  224. /**
  225.   * @brief  Reports the name of the source file and the source line number
  226.   *         where the assert_param error has occurred.
  227.   * @param  file: pointer to the source file name
  228.   * @param  line: assert_param error line source number
  229.   * @retval None
  230.   */
  231. void assert_failed(uint8_t *file, uint32_t line)
  232. {
  233.   /* User can add his own implementation to report the file name and line number,
  234.      ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  235.   /* Infinite loop */
  236.   while (1)
  237.   {
  238.   }
  239. }
复制代码


回复

使用道具 举报

29

主题

77

回帖

164

积分

初级会员

积分
164
发表于 2018-8-24 09:13:55 | 显示全部楼层
非低功耗定时器在外部时钟驱动下在停机模式下能工作吗
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107031
QQ
 楼主| 发表于 2018-8-24 09:26:43 | 显示全部楼层
hecudashi 发表于 2018-8-24 09:13
非低功耗定时器在外部时钟驱动下在停机模式下能工作吗

不能,他们的时钟源不能选择,是固定的APB总线时钟。
回复

使用道具 举报

29

主题

77

回帖

164

积分

初级会员

积分
164
发表于 2018-8-24 09:46:20 | 显示全部楼层
定时器有个配置时钟源为外部时钟的功能,我一直有疑惑,配置为外部时钟,内部APB总线时钟还对定时器有什么作用?如果不是一回事,配置为外部时钟时APB总线时钟的作用是什么(操作寄存器?)。看定时器框图也看不出来。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107031
QQ
 楼主| 发表于 2018-8-24 11:47:05 | 显示全部楼层
hecudashi 发表于 2018-8-24 09:46
定时器有个配置时钟源为外部时钟的功能,我一直有疑惑,配置为外部时钟,内部APB总线时钟还对定时器有什么 ...

通用定时器那个是时钟计数器采用的外部触发源,主要用捕获测量等功能。
1.png

而低功耗这个是时钟源,外设基本就是在这个时钟源下工作
QQ截图20180824114849.png
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-15 00:01 , Processed in 0.173521 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表