打印
[其他]

【HC32L196PCTA测评】8.低功耗功能测试

[复制链接]
892|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
#申请原创# @21小跑堂  
8.低功耗功能测试
8.1运行模式
HC32L196有3个工作模式
运行模式:CPU运行,周边功能模块运行

休眠模式:CPU停止运行,周边功能模块运行

深度休眠模式:CPU停止运行,高速时钟停止运行

MCU可在运行模式下通过命令进入休眠模式或深度休眠模式,接下来简单测试一下这3个模式下的电流,将pwrtest的跳线帽拔掉,用万用表毫安档测电流,测得电流不一定准,仅供参考
运行模式,外部32M晶振只初始化LED和按键,不开中断,在按下按键前保持LED点亮来指示CPU正常工作,点击按键后熄灭

void xth_init()
{
    //当使用的时钟源HCLK大于24M:设置FLASH 读等待周期为1 cycle
    Flash_WaitCycle(FlashWaitCycle1);   
    Sysctrl_SetXTHFreq(SysctrlXthFreq24_32MHz);
    Sysctrl_XTHDriverCfg(SysctrlXtalDriver3);
    Sysctrl_SetXTHStableTime(SysctrlXthStableCycle16384);
    Sysctrl_ClkSourceEnable(SysctrlClkXTH, TRUE);
    delay1ms(10);
    Sysctrl_SysClkSwitch(SysctrlClkXTH);
}
void led_init(void)
{
    stc_gpio_cfg_t stcGpioCfg;
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);
    stcGpioCfg.enDir = GpioDirOut;
    stcGpioCfg.enPu = GpioPuDisable;
    stcGpioCfg.enPd = GpioPdEnable;
    Gpio_ClrIO(STK_LED_PORT, STK_LED_PIN);
    Gpio_Init(STK_LED_PORT, STK_LED_PIN, &stcGpioCfg);
}
void key_init(void)
{
    stc_gpio_cfg_t stcGpioCfg;
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);
    stcGpioCfg.enDir = GpioDirIn;
    stcGpioCfg.enDrv = GpioDrvL;
    stcGpioCfg.enPu = GpioPuDisable;
    stcGpioCfg.enPd = GpioPdDisable;
    Gpio_Init(STK_USER_PORT, STK_USER_PIN, &stcGpioCfg);
}
int32_t main(void)
{
    xth_init();
    //时钟分频设置
    Sysctrl_SetHCLKDiv(SysctrlHclkDiv1);
    Sysctrl_SetPCLKDiv(SysctrlPclkDiv1);
    led_init();
    key_init();
    Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,TRUE);
    while(Gpio_GetInputIO(STK_USER_PORT, STK_USER_PIN) == TRUE);
    Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,FALSE);
    while(1)
    {
    }
}
测得电流

休眠模式,其它都不变,点击按键后熄灭进入休眠模式

int32_t main(void)
{
    xth_init();
    //时钟分频设置
    Sysctrl_SetHCLKDiv(SysctrlHclkDiv1);
    Sysctrl_SetPCLKDiv(SysctrlPclkDiv1);
    led_init();
    key_init();
    Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,TRUE);
    while(Gpio_GetInputIO(STK_USER_PORT, STK_USER_PIN) == TRUE);
    Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,FALSE);
    Lpm_GotoSleep(TRUE);
    while(1)
    {
    }
}
测得电流

深度休眠模式

int32_t main(void)
{
    xth_init();
    //时钟分频设置
    Sysctrl_SetHCLKDiv(SysctrlHclkDiv1);
    Sysctrl_SetPCLKDiv(SysctrlPclkDiv1);
    led_init();
    key_init();
    Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,TRUE);
    while(Gpio_GetInputIO(STK_USER_PORT, STK_USER_PIN) == TRUE);
    Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,FALSE);
    Lpm_GotoDeepSleep(TRUE);
    while(1)
    {
    }
}
测得电流

8.2深度休眠后通过按键中断唤醒
进入休眠或深度休眠模式后,可以通过中断进行唤醒回到运行模式继续执行任务

实验一下,开启按键中断,led亮起3次后进入深度休眠,按下按键后led会亮起4次后再次进入深度休眠

void key_init(void)
{
    stc_gpio_cfg_t stcGpioCfg;
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);
    stcGpioCfg.enDir = GpioDirIn;
    stcGpioCfg.enDrv = GpioDrvL;
    stcGpioCfg.enPu = GpioPuDisable;
    stcGpioCfg.enPd = GpioPdDisable;
    Gpio_Init(STK_USER_PORT, STK_USER_PIN, &stcGpioCfg);
    Gpio_EnableIrq(STK_USER_PORT, STK_USER_PIN, GpioIrqFalling);
    EnableNvic(PORTA_IRQn, IrqLevel3, TRUE);
}
void PortA_IRQHandler(void)
{
    if(TRUE == Gpio_GetIrqStatus(STK_USER_PORT, STK_USER_PIN))
    {         
        Gpio_ClearIrq(STK_USER_PORT, STK_USER_PIN);      
    }
}
int32_t main(void)
{
    xth_init();
    //时钟分频设置
    Sysctrl_SetHCLKDiv(SysctrlHclkDiv1);
    Sysctrl_SetPCLKDiv(SysctrlPclkDiv1);
    led_init();
    key_init();
    while(1)
    {
        Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,TRUE);
        delay1ms(200);
        Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,FALSE);
        delay1ms(200);
        Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,TRUE);
        delay1ms(200);
        Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,FALSE);
        delay1ms(200);
        Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,TRUE);
        delay1ms(200);
        Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,FALSE);
        delay1ms(200);
        Lpm_GotoDeepSleep(FALSE); //中断处理完成后不自动进入休眠模式
        Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,TRUE);
        delay1ms(500);
        Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,FALSE);
        delay1ms(500);
    }
}
休眠代码后面那段代码是用来验证退出休眠后是从头开始运行还是从进入休眠的位置继续向后运行,运行结果

可以看到退出休眠后是从进入休眠的位置继续向后运行的
8.3深度休眠后通过低功耗定时器中断唤醒
LPTimer是异步16位定时/计数器,在系统时钟关闭后仍然可以通过内部低速RC或者外部低速晶体振荡计时/计数。通过中断在低功耗模式下唤醒系统
初始化LPTimer,设定触发时间为1秒

void lptimer_init()
{
    stc_lptim_cfg_t    stcLptCfg;
    DDL_ZERO_STRUCT(stcLptCfg);
    ///< 使能LPTIM0 外设时钟
    Sysctrl_ClkSourceEnable(SysctrlClkXTL,TRUE);
    Sysctrl_SetPeripheralGate(SysctrlPeripheralLpTim0, TRUE);
    stcLptCfg.enPrs    = LptimPrsDiv256;
    stcLptCfg.enGate   = LptimGateLow;
    stcLptCfg.enGatep  = LptimGatePLow;
    stcLptCfg.enTcksel = LptimXtl;
    stcLptCfg.enTogen  = LptimTogEnLow;
    stcLptCfg.enCt     = LptimTimerFun;         
    stcLptCfg.enMd     = LptimMode2;            //工作模式为模式2:自动重载16位计数器/定时器
    stcLptCfg.u16Arr   = 0x10000 - 128;         //预装载寄存器值
    Lptim_Init(M0P_LPTIMER0, &stcLptCfg);

    Lptim_ClrItStatus(M0P_LPTIMER0);   //清除中断标志位
    Lptim_ConfIt(M0P_LPTIMER0, TRUE);  //允许LPTIMER中断
    EnableNvic(LPTIM_0_1_IRQn, IrqLevel3, TRUE);
   
    Lptim_Cmd(M0P_LPTIMER0, TRUE);
}
void LpTim0_IRQHandler(void)
{
    if (TRUE == Lptim_GetItStatus(M0P_LPTIMER0))
    {
        Lptim_ClrItStatus(M0P_LPTIMER0);//清除LPTimer的中断标志位
    }
}
int32_t main(void)
{
    xth_init();
    //时钟分频设置
    Sysctrl_SetHCLKDiv(SysctrlHclkDiv1);
    Sysctrl_SetPCLKDiv(SysctrlPclkDiv1);
    led_init();
    key_init();
        lptimer_init();
    while(1)
    {
        Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,TRUE);
        delay1ms(200);
        Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,FALSE);
        delay1ms(200);
        Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,TRUE);
        delay1ms(200);
        Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,FALSE);
        delay1ms(200);
        Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,TRUE);
        delay1ms(200);
        Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,FALSE);
        delay1ms(200);
        Lpm_GotoDeepSleep(FALSE); //中断处理完成后不自动进入休眠模式
    }
}
运行效果

8.4LPUART测试
低功耗同步异步接收器(LPUART)也是是一种UART,LPUART包含所有必要的硬件支持,使在最小功耗下可以进行异步串行通信
使用PA00和PA01,初始化LPUART

void lpuart_io_init()
{
    stc_gpio_cfg_t stcGpioCfg;
    DDL_ZERO_STRUCT(stcGpioCfg);                            ///< 结构体变量初始值置零
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE);  ///< 使能GPIO时钟   
    ///<TX
    stcGpioCfg.enDir =  GpioDirOut;
    Gpio_Init(GpioPortA,GpioPin0,&stcGpioCfg);
    Gpio_SetAfMode(GpioPortA,GpioPin0,GpioAf2); //配置PA00为LPUART1_TX
    //<RX
    stcGpioCfg.enDir =  GpioDirIn;
    Gpio_Init(GpioPortA,GpioPin1,&stcGpioCfg);
    Gpio_SetAfMode(GpioPortA,GpioPin1,GpioAf2); //配置PA01为LPUART1_RX
}
void lpuart_init()
{
    stc_lpuart_cfg_t  stcCfg;
    DDL_ZERO_STRUCT(stcCfg);                        ///< 结构体变量初始值置零
    ///<外设模块时钟使能
    Sysctrl_ClkSourceEnable(SysctrlClkXTL,TRUE);
    Sysctrl_SetPeripheralGate(SysctrlPeripheralLpUart1,TRUE);  
    ///<LPUART 初始化
    stcCfg.enStopBit = LPUart1bit;                   ///<1停止位   
    stcCfg.stcBaud.enSclkSel = LPUartMskXtl;         ///<传输时钟源
    stcCfg.stcBaud.u32Sclk = 32768;                  ///<XTL时钟频率 32768Hz
    stcCfg.stcBaud.enSclkDiv = LPUartMsk4Or8Div;     ///<采样分频
    stcCfg.stcBaud.u32Baud = 8192;                   ///<波特率 32768/4
    stcCfg.enRunMode = LPUartMskMode1;               ///<工作模式
    LPUart_Init(M0P_LPUART1, &stcCfg);
     
    ///<LPUART 中断使能
    LPUart_ClrStatus(M0P_LPUART1,LPUartRC);         ///<清接收中断请求
    LPUart_EnableIrq(M0P_LPUART1,LPUartRxIrq);      ///<使能接收中断
    LPUart_EnableIrq(M0P_LPUART1,LPUartTxIrq);    ///<使能发送中断
    EnableNvic(LPUART1_IRQn,IrqLevel3,TRUE);        ///<系统中断使能
}
中断处理
uint8_t lpuart_buffer[20];
uint8_t lpuart_rxlen = 0;
uint8_t lpuart_rxindex = 0;
uint8_t lpuart_txindex = 0;
void LpUart1_IRQHandler(void)
{
    if(LPUart_GetStatus(M0P_LPUART1, LPUartRC))       ///接收数据中断
    {
        LPUart_ClrStatus(M0P_LPUART1, LPUartRC);      ///<清接收中断请求
        lpuart_buffer[lpuart_rxindex++] = LPUart_ReceiveData(M0P_LPUART1);   ///读取数据
        if(lpuart_rxindex > 19)
            lpuart_rxindex = 0;
        if(lpuart_rxlen == 0)
        {
            lpuart_rxlen = 1;
            LPUart_SendDataIt(M0P_LPUART1, lpuart_buffer[lpuart_txindex++]);
            if(lpuart_txindex > 19)
                lpuart_txindex = 0;
        }  
        else
        {
            lpuart_rxlen+=1;
        }
    }
    if(LPUart_GetStatus(M0P_LPUART1, LPUartTC))       ///发送数据中断
    {
        LPUart_ClrStatus(M0P_LPUART1, LPUartTC);      ///<清发送中断请求
        lpuart_rxlen -= 1;
        if(lpuart_rxlen > 0)
        {
            LPUart_SendDataIt(M0P_LPUART1, lpuart_buffer[lpuart_txindex++]);
            if(lpuart_txindex > 19)
                lpuart_txindex = 0;
        }
    }
}
主循环中设置中断唤醒后处理完中断自动进入深度休眠,这样LED亮起3次后就会一直保持熄灭状态
int32_t main(void)
{
    xth_init();
    //时钟分频设置
    Sysctrl_SetHCLKDiv(SysctrlHclkDiv1);
    Sysctrl_SetPCLKDiv(SysctrlPclkDiv1);
   
    led_init();
    key_init();
    lpuart_io_init();
    lpuart_init();
    while(1)
    {
        Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,TRUE);
        delay1ms(200);
        Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,FALSE);
        delay1ms(200);
        Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,TRUE);
        delay1ms(200);
        Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,FALSE);
        delay1ms(200);
        Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,TRUE);
        delay1ms(200);
        Gpio_WriteOutputIO(STK_LED_PORT, STK_LED_PIN,FALSE);
        delay1ms(200);
        Lpm_GotoDeepSleep(TRUE); //中断处理后自动进入深度休眠
    }
}
测试效果,在接收和发送时LED不会亮起

使用特权

评论回复
沙发
chenjunt| | 2023-8-27 10:42 | 只看该作者
测得电流不一定准

使用特权

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

本版积分规则

145

主题

695

帖子

6

粉丝