打印
[资料分享与下载]

KL17低功耗测试 + GPIO + LPTMR

[复制链接]
1187|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Mancherstun|  楼主 | 2015-11-8 20:32 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本代码基于KSDK 1.3,可实现KL17MCU进入低功耗模式(VLPS),可通过GPIO引脚触发唤醒或定时器自动唤醒。
GPIO  PTC1 采用LLWU方式唤醒KL17。
#include "fsl_clock_manager.h"
#include "fsl_port_hal.h"
#include "fsl_pmc_hal.h"
#include "fsl_smc_hal.h"
#include "fsl_rtc_hal.h"
#include "fsl_sim_hal.h"
#include "fsl_interrupt_manager.h"
#include "fsl_lptmr_driver.h"

#include "fsl_gpio_driver.h"
#include "fsl_power_manager.h"
#include "fsl_llwu_hal.h"

#include "fsl_debug_console.h"

/* Function to initialize OSC0 base on board configuration. */
void InitOsc0(void)
{
    // OSC0 configuration.
    osc_user_config_t osc0Config =
    {
        .freq                = 32768U,
        .hgo                 = kOscGainLow,
        .range               = kOscRangeLow,
        .erefs               = kOscSrcOsc,
        .enableCapacitor2p   = false,
        .enableCapacitor4p   = false,
        .enableCapacitor8p   = false,
        .enableCapacitor16p  = false,
    };

    CLOCK_SYS_OscInit(0U, &osc0Config);
}
/* Function to initialize RTC external clock base on board configuration. */
void InitRtcOsc(void)
{

    rtc_osc_user_config_t rtcOscConfig =
    {
        .freq                = 0,
        .enableCapacitor2p   = false,
        .enableCapacitor4p   = false,
        .enableCapacitor8p   = false,
        .enableCapacitor16p  = false,
        .enableOsc           = false,
        .enableClockOutput   = false,
    };

    CLOCK_SYS_RtcOscInit(0U, &rtcOscConfig);
}
/* Configuration for enter RUN mode. Core clock = 48MHz. */
const clock_manager_user_config_t g_defaultClockConfigRun =
{
    .mcgliteConfig =
    {
        .mcglite_mode        = kMcgliteModeHirc48M,   // Work in HIRC mode.
        .irclkEnable        = false, // MCGIRCLK disable.
        .irclkEnableInStop  = false, // MCGIRCLK disable in STOP mode.
        .ircs               = kMcgliteLircSel2M, // Select LIRC_2M.
        .fcrdiv             = kMcgliteLircDivBy1,    // FCRDIV is 0.
        .lircDiv2           = kMcgliteLircDivBy1,    // LIRC_DIV2 is 0.
        .hircEnableInNotHircMode         = true,  // HIRC disable.
    },
    .simConfig =
    {
        .er32kSrc  = kClockEr32kSrcOsc0,  // ERCLK32K selection, use OSC.
        .outdiv1   = 0U,
        .outdiv4   = 1U,
    },
    .oscerConfig =
    {
        .enable       = false, // OSCERCLK disable.
        .enableInStop = false, // OSCERCLK disable in STOP mode.
    }
};

/* Initialize clock. */
void ClockInit(void)
{
    /* enable clock for PORTs */
    CLOCK_SYS_EnablePortClock(PORTA_IDX);

    /* Power mode protection initialization */
        SMC_HAL_SetProtection(SMC, kAllowPowerModeAll);

    /* Setup board clock source. */
    // Setup OSC0 if used.
    // Configure OSC0 pin mux.
    PORT_HAL_SetMuxMode(PORTA, 18, kPortPinDisabled);
    PORT_HAL_SetMuxMode(PORTA, 19, kPortPinDisabled);
    InitOsc0();

    // Setup RTC external clock if used.
#if RTC_XTAL_FREQ
    /* enable clock for PORTs */
    CLOCK_SYS_EnablePortClock(PORTC_IDX);
    // If RTC_CLKIN is connected, need to set pin mux. Another way for
    // RTC clock is set RTC_OSC_ENABLE_CONFIG to use OSC0, please check
    // reference manual for datails.
    PORT_HAL_SetMuxMode(PORTC, 1, kPortMuxAsGpio);
#endif
    InitRtcOsc();

    /* Set system clock configuration. */
    CLOCK_SYS_SetConfiguration(&g_defaultClockConfigRun);

}
void DebugConsole_Init(void)
{
        CLOCK_SYS_EnablePortClock(PORTA_IDX);
        PORT_HAL_SetMuxMode(PORTA,1u, kPortMuxAlt2);
        PORT_HAL_SetMuxMode(PORTA,2u, kPortMuxAlt2);
        CLOCK_SYS_SetLpuartSrc(0, kClockLpuartSrcIrc48M);
        DbgConsole_Init(0, 9600, kDebugConsoleLPUART);
}
/*!
* [url=home.php?mod=space&uid=247401]@brief[/url] LPTMR interrupt callback
*/
volatile uint32_t lptmrCounter=0;
void lptmr_isr_callback(void)
{
        lptmrCounter++;
        PRINTF("\n\rLPTMR0_IRQHandler No.%d\n\r\n\r", lptmrCounter);
}

lptmr_state_t lptmrState;
lptmr_user_config_t lptmrUserConfig;
void LPTMR_Init(void)
{
        lptmrUserConfig.timerMode            = kLptmrTimerModeTimeCounter; /*! Use LPTMR in Time Counter mode */
        lptmrUserConfig.freeRunningEnable    = false; /*! When hit compare value, set counter back to zero */
        lptmrUserConfig.prescalerEnable      = false; /*! bypass prescaler */
        lptmrUserConfig.prescalerClockSource = kClockLptmrSrcLpoClk; /*! use 1kHz Low Power Clock */
        lptmrUserConfig.isInterruptEnabled   = true;

        // Initialize LPTMR
        LPTMR_DRV_Init(0U, &lptmrState, &lptmrUserConfig);

        // Set the timer period for 5 second
<b>        LPTMR_DRV_SetTimerPeriodUs(0U, 5000000);</b>

        // Specify the callback function when a LPTMR interrupt occurs
        LPTMR_DRV_InstallCallback(0U, lptmr_isr_callback);

        // Start counting
        LPTMR_DRV_Start(0U);
}
void lptmrEnableWakeUp(void)
{
        LLWU_HAL_SetInternalModuleCmd(LLWU_BASE_PTR, kLlwuWakeupModule0, true);
}

void GPIO_Init(void)
{
        //配置输入GPIO口
        gpio_input_pin_user_config_t inputPin = {
                        .pinName = GPIO_MAKE_PIN(GPIOC_IDX, 1), //PTC1
                        .config.isPullEnable = true,
                        .config.pullSelect = kPortPullUp,
                        .config.interrupt = kPortIntFallingEdge,
                };
        GPIO_DRV_InputPinInit(&inputPin);
}
void gpioEnableWakeUp(void)
{
        LLWU_HAL_ClearExternalPinWakeupFlag(LLWU_BASE_PTR, kLlwuWakeupPin6);
        //falling edge detection
        LLWU_HAL_SetExternalInputPinMode(LLWU_BASE_PTR, kLlwuExternalPinFallingEdge, kLlwuWakeupPin6);
}
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
void LPTMR0_IRQHandler(void)
{
    LPTMR_DRV_IRQHandler(0U);
}
void PORTBCDE_IRQHandler(void)
{
    PORT_HAL_ClearPortIntFlag(PORTC);
    PRINTF("\n\rPORTBCDE_IRQHandler\n\r\n\r");
}
/*
void LLWU_IRQHandler(void)
{
        if(LLWU_HAL_GetExternalPinWakeupFlag(LLWU_BASE_PTR, kLlwuWakeupPin6))
        {
                LLWU_HAL_ClearExternalPinWakeupFlag(LLWU_BASE_PTR, kLlwuWakeupPin6);
                PRINTF("\n\rLLWU_IRQHandler PTC1\n\r\n\r");
        }
    if(LLWU_HAL_GetInternalModuleWakeupFlag(LLWU_BASE_PTR, kLlwuWakeupModule0))
    {
            PRINTF("\n\rLLWU_IRQHandler LPTMR\n\r\n\r");
    }
}
*/
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
#define VLPS_mode

int main(void)
{

    /* Write your code here */

        if(PMC_HAL_GetAckIsolation(PMC_BASE_PTR) != 0)
        {
                PMC_HAL_ClearAckIsolation(PMC_BASE_PTR);
        }

        ClockInit();

        DebugConsole_Init();

        LPTMR_Init();
        GPIO_Init();

/*
        // Enables LLWU interrupt
        INT_SYS_EnableIRQ(LLWU_IRQn);
<font color="#ff0000"><b>        lptmrEnableWakeUp();          //LPTMR 模块实现5秒定时,超时将产生中断并唤醒MCU。</b></font>
<b><font color="#ff0000">        gpioEnableWakeUp();</font></b>
*/

    /* First, setup an smc_power_mode_config_t variable to be passed to the SMC
    * HAL function
    */

#ifdef VLPS_mode
         smc_power_mode_config_t smc_power_config =
         {
                         .powerModeName = <b>kPowerModeVlps</b>, // Set the desired power mode
         };
#endif

    /* This for loop should be replaced. By default this loop allows a single stepping. */
    while (1) {
#ifdef VLPS_mode
            PRINTF("\n\rEnter Into Low Power\n\r\n\r");
                /* Now call the SMC HAL SetMode function to move to the desired power mode. */
                if (SMC_HAL_SetMode(SMC, &smc_power_config) != kSmcHalSuccess) PRINTF("\n\rFail\n\r\n\r");
#endif
    }
    /* Never leave main */
    return 0;
}
////////////////////////////////////////////////////////////////////////////////
// EOF
////////////////////////////////////////////////////////////////////////////////


相关帖子

沙发
Mancherstun|  楼主 | 2015-11-8 20:34 | 只看该作者
代码分析:
1,LPTMR唤醒MCU的原理

    KL系列的MCU中的LPTMR模块在任何功耗模式下都可以工作,使用前应先配置时钟和模式
ptmrUserConfig.timerMode            = kLptmrTimerModeTimeCounter; /*! Use LPTMR in Time Counter mode */
        lptmrUserConfig.freeRunningEnable    = false; /*! When hit compare value, set counter back to zero */
        lptmrUserConfig.prescalerEnable      = false; /*! bypass prescaler */
        lptmrUserConfig.prescalerClockSource = kClockLptmrSrcLpoClk; /*! use 1kHz Low Power Clock */
        lptmrUserConfig.isInterruptEnabled   = true;

设置定时时间
// Set the timer period for 5 second
        LPTMR_DRV_SetTimerPeriodUs(0U, 5000000);

设置定时器回调函数
// Specify the callback function when a LPTMR interrupt occurs

        LPTMR_DRV_InstallCallback(0U, lptmr_isr_callback);

使用特权

评论回复
板凳
Mancherstun|  楼主 | 2015-11-8 20:36 | 只看该作者
使能LPTMR模块的中断作为唤醒源
void lptmrEnableWakeUp(void)
       {
              LLWU_HAL_SetInternalModuleCmd(LLWU_BASE_PTR, kLlwuWakeupModule0, true);
       }

启动定时器
LPTMR_DRV_Start(0U);

使用特权

评论回复
地板
Mancherstun|  楼主 | 2015-11-8 20:36 | 只看该作者
2,GPIO触发唤醒

    配置GPIO PTC1作为输入口,且脉冲触发方式(上升沿或下降沿)
void GPIO_Init(void)
        {
                //配置输入GPIO口
                gpio_input_pin_user_config_t inputPin = {
                                .pinName = GPIO_MAKE_PIN(GPIOC_IDX, 1), //PTC1
                                .config.isPullEnable = true,
                                .config.pullSelect = kPortPullUp,
                                .config.interrupt = kPortIntFallingEdge,
                        };
                GPIO_DRV_InputPinInit(&inputPin);
        }

使能该引脚作为唤醒源
void gpioEnableWakeUp(void)
        {
                LLWU_HAL_ClearExternalPinWakeupFlag(LLWU_BASE_PTR, kLlwuWakeupPin6);
                //falling edge detection
                LLWU_HAL_SetExternalInputPinMode(LLWU_BASE_PTR, kLlwuExternalPinFallingEdge, kLlwuWakeupPin6);
        }

使用特权

评论回复
5
FSL_TICS_ZJJ| | 2015-11-9 10:50 | 只看该作者
感谢楼主的资料分享!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

35

主题

294

帖子

2

粉丝