低功耗技術旨在減少設備電流消耗,延長電池壽命,可以有效的延長產品的使用壽命。這就需要合理分配運行時間和空閑時間,在空閑時可以通過使MCU進入低功耗模式降低系統的功耗,在需要MCU工作時喚醒MCU,低功耗定時器(LPTIM)有助于降低功耗,特別是當系統處于低功耗模式時(如 stop模式)可以在休眠模式下實現外部脈沖計數功能。通過外部輸入的觸發信號,能夠實現低功耗超時喚醒。LPTIM 具有外部時鐘計數,超時喚醒功能和 PWM 輸出等多種用途。
本文主要介紹 MM32 全新低功耗系列 MM32L013x 產品中的 LPTIM 外設模塊,它允許系統執行簡單的任務,同時功耗保持在絕對最小。
1LPTIM 簡介
LPTIM 由一個 16 位計數器組成,可以為用戶提供便捷的計數和定時功能。LPTIM 運行在 CORE 電源域,可以工作在低功耗模式下,具有低功耗的特點,當然也可以被當做一個普通的 16 位基礎定時器來使用。
2LPTIM 常見用途
脈沖計數功能
PWM 生成器
周期性地超時喚醒sleep模式、stop模式
以上所有功能應用均為普通 TIM 所不能實現的,正是由于 LPTIM 的時鐘源具有多樣性,使得其能夠在所有電源模式(standby模式除外)下保持運行狀態。
3LPTIM 主要特性
16 位遞增計數器,相當于 LPT_CNT 值由模塊時鐘驅動加一遞增最大到 65535,并且包括一個 16 位比較寄存器和目標值寄存器
3 位異步時鐘預分頻器,可以將輸入進模塊的時鐘進行多種系數的預分頻,包括:
1/2/4/8/16/32/64/128 分頻
多種內部和外部的時鐘源可選,包括:LSI/LSE/PCLK2
可以選擇不同邊沿的脈沖極性用作觸發計數,觸發源包括:LPTIM1_TRIGGER 引腳輸入觸發、COMP OUT 事件觸發
可以設定不同的 LPT_CMP 和 LPT_TARGET 值從而通過 LPTIM1_OUT 引腳輸出不同占空比的PWM 波形或者方波
可以設定不同的 LPT_TARGET 值從而進行不同時長的低功耗喚醒
可以開啟不同的中斷,包括:外部觸發、比較匹配和計數器溢出中斷,在喚醒 STOP 模式時,除了需要使能相應的中斷外,還需配置 EXTI_Line23 并且使能相關的功能
4LPTIM 功能框圖
LPTIM 的功能框圖如下,主要包括了:觸發源選擇模塊、時鐘輸入及分頻模塊、計數模塊以及比較匹配輸出單元等。
涉及到時鐘選擇的部分需要設置RCC_CFGR2[30:29],在 UM 手冊中時鐘配置寄存器2(RCC_CFGR2):
使能LPTIM時鐘需要設置RCC_APB2ENR[31]位:
涉及到 LPTIM1_TRIGGER 和 LPTIM1_OUT 引腳的功能定義情況在 DS 手冊中引腳復用及復用列表:
5LPTIM 寄存器表
由于 MM32L013x 系列產品中只有一個 LPTIM 模塊,所以在文檔和程序中也習慣稱作 LPTIM1,它的基地址為 0x40012800,所有寄存器設計為 16 位,預留出 16位保持 32 位對齊,寄存器占用情況如下:
其中 LPT_CFG 、 LPT_IE 、 LPT_CTRL 、LPT_CMP 、 LPT_TARGET 為可讀可寫操作的,LPT_IF 為可讀并且寫 1 清零操作的,LPT_CNT 為只讀操作的,具體功能描述參見 UM 對應章節內容。
6LPTIM 功能實現
6.1 帶溢出中斷的普通定時器
使能 APB2 總線上的 LPTIM 外設時鐘,用于同步
初始化配置 LPT_CFG 寄存器 MODE=0,計數器被觸發后保持運行,直到被關閉為止
初始化配置 LPT_CFG 寄存器 TMODE=00,選擇普通計數器模式
選擇外部時鐘或內部時鐘作為計數器的時鐘源
配置 LPT_IE =1,使能 LPTIM 計數器溢出中斷
配置 LPT_CTRL 寄存器 LPTEN=1,使能 LPTIM 計數器
計數器使能后有兩個周期的同步過程,同步完成后,計數器開始工作,計數達到目標之后回到 0 重新開始計數,并產生溢出中斷
按上述流程的代碼配置如下:
voidLPTIM1_Init(u16arr) { LPTIM_TimeBaseInit_TypeDefinit_struct; RCC_APB2PeriphClockCmd(RCC_APB2ENR_LPTIM1,ENABLE); LPTIM_TimeBaseStructInit(&init_struct); init_struct.ClockSource=LPTIM_PCLK_Source; init_struct.CountMode=LPTIM_CONTINUOUS_COUNT_Mode; init_struct.OutputMode=LPTIM_NORMAL_WAV_Mode; init_struct.Waveform=LPTIM_AdjustPwmOutput_Mode; init_struct.Polarity=LPTIM_Positive_Wave; init_struct.ClockDivision=LPTIM_CLK_DIV1; if(init_struct.ClockSource==LPTIM_LSE_Source){ RCC_APB1PeriphClockCmd(RCC_APB1ENR_PWR|RCC_APB1ENR_BKP,ENABLE); PWR_BackupAccessCmd(ENABLE); RCC_LSEConfig(RCC_LSE_ON); DELAY_Ms(5000); while(!RCC_GetFlagStatus(RCC_FLAG_LSERDY)); LPTIM_CLKConfig(LPTIM1,LPTIM_LSE_Source); } elseif(init_struct.ClockSource==LPTIM_LSI_Source){ RCC_APB1PeriphClockCmd(RCC_APB1ENR_PWR|RCC_APB1ENR_BKP,ENABLE); PWR_BackupAccessCmd(ENABLE); RCC_LSICmd(ENABLE); DELAY_Ms(500); while(!RCC_GetFlagStatus(RCC_FLAG_LSIRDY)); LPTIM_CLKConfig(LPTIM1,LPTIM_LSI_Source); } else{//(init_struct.ClockSource==LPTIM_PCLK_Source) LPTIM_CLKConfig(LPTIM1,LPTIM_PCLK_Source); } LPTIM_TimeBaseInit(LPTIM1,&init_struct); LPTIM_SetTarget(LPTIM1,arr); } voidLPTIMER1_IRQHandler(void) { if(LPTIM_GetITStatus(LPTIM1,LPTIF_OVIF)){ LPTIM_ClearITPendingBit(LPTIM1,LPTIF_OVIF); LED3_TOGGLE(); LED4_TOGGLE(); } } voidNVIC_Configuration(void) { NVIC_InitTypeDefNVIC_InitStruct; NVIC_InitStruct.NVIC_IRQChannel=LPTIMER1_IRQn; NVIC_InitStruct.NVIC_IRQChannelPriority=2; NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE; NVIC_Init(&NVIC_InitStruct); } s32main(void) { DELAY_Init(); LED_Init(); LPTIM1_Init(4000-1); NVIC_Configuration(); LPTIM_ITConfig(LPTIM1,LPTIE_OVIE,ENABLE); LPTIM_Cmd(LPTIM1,ENABLE); while(1) { LED1_TOGGLE(); LED2_TOGGLE(); DELAY_Ms(1000); } }
6.2 PWM 輸出
初始化中使用以上相同的步驟,需要額外配置 LPT_CFG 寄存器 PWM=1,選擇 PWM 輸出模式
再配置 LPT_CMP 和 LPT_TARGET 寄存器,設定比較值和目標值,PWM 的占空比由比較值和目標值決定,輸出在計數器值等于比較值翻轉為 1,在等于目標值時翻轉為 0
另外需要配置一組 LPTIM1_OUT 引腳用于輸出 PWM 波形,這里以 PB14 為例
代碼配置如下:
voidLPTIM_GPIO_Init(void) { GPIO_InitTypeDefGPIO_InitStruct; RCC_GPIO_ClockCmd(GPIOB,ENABLE); //setPB14asLPTIM1OutputPin GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_3); GPIO_InitStruct.GPIO_Pin=GPIO_Pin_14; GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP; GPIO_Init(GPIOB,&GPIO_InitStruct); } voidLPTIM1_Init(u16arr) { LPTIM_TimeBaseInit_TypeDefinit_struct; RCC_APB2PeriphClockCmd(RCC_APB2ENR_LPTIM1,ENABLE); LPTIM_TimeBaseStructInit(&init_struct); init_struct.ClockSource=LPTIM_PCLK_Source; init_struct.CountMode=LPTIM_CONTINUOUS_COUNT_Mode; init_struct.OutputMode=LPTIM_NORMAL_WAV_Mode; init_struct.Waveform=LPTIM_AdjustPwmOutput_Mode; init_struct.Polarity=LPTIM_Positive_Wave; init_struct.ClockDivision=LPTIM_CLK_DIV1; if(init_struct.ClockSource==LPTIM_LSE_Source){ RCC_APB1PeriphClockCmd(RCC_APB1ENR_PWR|RCC_APB1ENR_BKP,ENABLE); PWR_BackupAccessCmd(ENABLE); RCC_LSEConfig(RCC_LSE_ON); DELAY_Ms(5000); while(!RCC_GetFlagStatus(RCC_FLAG_LSERDY)); LPTIM_CLKConfig(LPTIM1,LPTIM_LSE_Source); } elseif(init_struct.ClockSource==LPTIM_LSI_Source){ RCC_APB1PeriphClockCmd(RCC_APB1ENR_PWR|RCC_APB1ENR_BKP,ENABLE); PWR_BackupAccessCmd(ENABLE); RCC_LSICmd(ENABLE); DELAY_Ms(500); while(!RCC_GetFlagStatus(RCC_FLAG_LSIRDY)); LPTIM_CLKConfig(LPTIM1,LPTIM_LSI_Source); } else{//(init_struct.ClockSource==LPTIM_PCLK_Source) LPTIM_CLKConfig(LPTIM1,LPTIM_PCLK_Source); } LPTIM_TimeBaseInit(LPTIM1,&init_struct); } s32main(void) { DELAY_Init(); LED_Init(); LPTIM1_Init(4000-1); LPTIM_SetCompare(LPTIM1,4000/2-1); LPTIM_SetTarget(LPTIM1,4000); LPTIM_GPIO_Init(); LPTIM_Cmd(LPTIM1,ENABLE); while(1) { LED1_TOGGLE(); LED2_TOGGLE(); DELAY_Ms(1000); } }
6.3 Trigger 脈沖觸發計數
初始化中使用以上相同的步驟,需要修改配置 LPT_CFG 寄存器 TMODE=01,選擇 Trigger 脈沖觸發計數模式
配置 LPT_CFG 寄存器 TRIGSEL = 0,選擇外部引腳觸發計數
配置 LPT_CFG 寄存器 TRIGCFG,選擇外部觸發信號的有效沿
用戶可以根據需求選擇是否使能濾波器,配置LPT_CFG 寄存器
根據需求是否使能外部觸發中斷位
另外需要配置一組 LPTIM1_TRIGGER 引腳用于觸發輸入,這里以 PB13 為例
代碼配置如下:
voidLPTIM_GPIO_Init(void) { GPIO_InitTypeDefGPIO_InitStruct; RCC_GPIO_ClockCmd(GPIOB,ENABLE); //setPB13asLPTIM1TriggerPin GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_3); GPIO_InitStruct.GPIO_Pin=GPIO_Pin_13; GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_Mode=GPIO_Mode_FLOATING; GPIO_Init(GPIOB,&GPIO_InitStruct); } voidLPTIM1_Init(u16arr) { LPTIM_TimeBaseInit_TypeDefinit_struct; RCC_APB2PeriphClockCmd(RCC_APB2ENR_LPTIM1,ENABLE); LPTIM_TimeBaseStructInit(&init_struct); init_struct.ClockSource=LPTIM_PCLK_Source; init_struct.CountMode=LPTIM_CONTINUOUS_COUNT_Mode; init_struct.OutputMode=LPTIM_PULSE_TRIG_Mode; init_struct.Waveform=LPTIM_AdjustPwmOutput_Mode; init_struct.Polarity=LPTIM_Positive_Wave; init_struct.ClockDivision=LPTIM_CLK_DIV1; if(init_struct.ClockSource==LPTIM_LSE_Source){ RCC_APB1PeriphClockCmd(RCC_APB1ENR_PWR|RCC_APB1ENR_BKP,ENABLE); PWR_BackupAccessCmd(ENABLE); RCC_LSEConfig(RCC_LSE_ON); DELAY_Ms(5000); while(!RCC_GetFlagStatus(RCC_FLAG_LSERDY)); LPTIM_CLKConfig(LPTIM1,LPTIM_LSE_Source); } elseif(init_struct.ClockSource==LPTIM_LSI_Source){ RCC_APB1PeriphClockCmd(RCC_APB1ENR_PWR|RCC_APB1ENR_BKP,ENABLE); PWR_BackupAccessCmd(ENABLE); RCC_LSICmd(ENABLE); DELAY_Ms(500); while(!RCC_GetFlagStatus(RCC_FLAG_LSIRDY)); LPTIM_CLKConfig(LPTIM1,LPTIM_LSI_Source); } else{//(init_struct.ClockSource==LPTIM_PCLK_Source) LPTIM_CLKConfig(LPTIM1,LPTIM_PCLK_Source); } LPTIM_TimeBaseInit(LPTIM1,&init_struct); LPTIM1->CFGR=LPTIM_ExInputUpEdge; LPTIM1->CFGR=LPTIM_External_PIN_Trig; }
6.4 1s 周期性喚醒 STOP 模式
詳細可以參見靈動微課堂 (第196講) | 使用MM32F0270 LPTIM從STOP模式喚醒(點擊跳轉)。
審核編輯:湯梓紅
-
mcu
+關注
關注
146文章
16984瀏覽量
350293 -
計數器
+關注
關注
32文章
2253瀏覽量
94351 -
MM32
+關注
關注
1文章
106瀏覽量
744
原文標題:靈動微課堂 (第235講) | MM32L013x——LPTIM的應用介紹
文章出處:【微信號:MindMotion-MMCU,微信公眾號:靈動MM32MCU】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論