打印
[范例教程]

【M0】 MG32F02A 学习笔记⑬ 低功耗模式

[复制链接]
1285|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
noctor|  楼主 | 2018-10-19 13:21 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 noctor 于 2018-10-19 13:24 编辑
    上回我们说到了MG32F02A的IWDT的使用。帖子详情:https://bbs.21ic.com/icview-2566570-1-1.html

      这回我们来说一下EXIC和低功耗模式的使用吧。
      首先,介绍一下, MG32F02A支持两种掉电模式:SLEEP、STOP两种,其区别在数据手册里面都有:

      此外,两种掉电模式的功耗肯定也是有区别的:

      那么,要怎么进入SLEEP和STOP这两种掉电模式?很简单,就是直接在你想进入低功耗模式时候执行这段代码:
__WFI();//当然你也可以执行__WFE();

     WFI与WFE的区别就是WFI是等待中断,WFE是等待事件,不过经过我多次测试,表示没啥区别,就直接WFI完事儿了。
      刚刚的代码是用来进入低功耗模式的,执行代码后,MCU就会进入SLEEP模式,那么,STOP模式又怎么进入呢?
      
      CPU寄存器的DEEP SLEEP位置1就可以了,然鹅,并没有找到相关的驱动函数能置位,但是我倒是找到了置位用的宏定义,于是,我去翻内存映射:

      就是你了,SCR寄存器!!
      于是,仿照着例程代码中的置位方法,就有了以下代码:
SCB->SCR  = (SCB_SCR_SLEEPDEEP_Msk);    //把这句加在__WFI();前面就是进入STOP了
     试试看吧,这样就可以进入STOP模式了。
沙发
noctor|  楼主 | 2018-10-19 13:21 | 只看该作者
二楼附个代码

#include "MG32x02z_DRV.H"
#include "MG32x02z_ADC_DRV.h"
#include "MG32x02z_PW_DRV.h"
#include <stdio.h>

typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;

void CSC_Init (void)
{
        CSC_PLL_TyprDef CSC_PLL_CFG;
   
       
    UnProtectModuleReg(MEMprotect);             // Setting flash wait state
    MEM_SetFlashWaitState(MEM_FWAIT_ONE);        // 50MHz> Sysclk >=25MHz
    ProtectModuleReg(MEMprotect);

  UnProtectModuleReg(CSCprotect);
        CSC_CK_APB_Divider_Select(APB_DIV_1);        // Modify CK_APB divider        APB=CK_MAIN/1
        CSC_CK_AHB_Divider_Select(AHB_DIV_1);        // Modify CK_AHB divider        AHB=APB/1

       
        /* CK_HS selection */
        CSC_IHRCO_Select(IHRCO_12MHz);                        // IHRCO Sel 12MHz
        CSC_IHRCO_Cmd(ENABLE);
        while(CSC_GetSingleFlagStatus(CSC_IHRCOF) == DRV_Normal);
        CSC_ClearFlag(CSC_IHRCOF);
        CSC_CK_HS_Select(HS_CK_IHRCO);                        // CK_HS select IHRCO


        /* PLL */
        /**********************************************************/
        CSC_PLL_CFG.InputDivider=PLLI_DIV_2;        // 12M/2=6M
        CSC_PLL_CFG.Multiplication=PLLIx16;                // 6M*16=96M
        CSC_PLL_CFG.OutputDivider=PLLO_DIV_2;        // PLLO=96M/2=48M
        CSC_PLL_Config(&CSC_PLL_CFG);
        CSC_PLL_Cmd(ENABLE);
        while(CSC_GetSingleFlagStatus(CSC_PLLF) == DRV_Normal);
        CSC_ClearFlag(CSC_PLLF);
        /**********************************************************/

       
        /* CK_MAIN */
        CSC_CK_MAIN_Select(MAIN_CK_HS);       


        /* Configure ICKO function */
               
        /* Configure peripheral clock */
        CSC_PeriphOnModeClock_Config(CSC_ON_PortE,ENABLE);

  ProtectModuleReg(CSCprotect);
   
}

int main()
{
        int i,j;
        double x,y;
        PIN_InitTypeDef PINX_InitStruct;
        CSC_Init();
        PINX_InitStruct.PINX_Mode                                 = PINX_Mode_PushPull_O;          // Pin select digital input mode
        PINX_InitStruct.PINX_PUResistant                 = PINX_PUResistant_Enable;  // Enable pull up resistor
        PINX_InitStruct.PINX_Speed                                   = PINX_Speed_Low;                         
        PINX_InitStruct.PINX_OUTDrive                         = PINX_OUTDrive_Level0;         // Pin output driver full strength.
        PINX_InitStruct.PINX_FilterDivider                   = PINX_FilterDivider_Bypass;// Pin input deglitch filter clock divider bypass
        PINX_InitStruct.PINX_Inverse                         = PINX_Inverse_Disable;         // Pin input data not inverse
        PINX_InitStruct.PINX_Alternate_Function = 0;                                                 // Pin AFS = 0
  GPIO_PinMode_Config(PINE(15),&PINX_InitStruct);                                          // D6 setup at PE15
        i=0;
        j=0;
        while(1)
        {
                i++;
                if(i>=500000){
                        i=0;
                        PE15=~PE15;
                        j++;
                        if(j>10)
                        {
                          PE15=1;                               
                                SCB->SCR  = (SCB_SCR_SLEEPDEEP_Msk);  //into stop
                                __WFI();             //This is the command of cmsis_arm.cc.  __WFI();is wait for interrupt while __WFE();is wait for event();
                                j=0;
                        }         
                }
        }
}

使用特权

评论回复
板凳
344864311| | 2018-10-19 16:40 | 只看该作者
感觉操作寄存器确实挺简单的,赞一个。

使用特权

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

本版积分规则

26

主题

82

帖子

3

粉丝