打印
[活动]

代码分析 系统睡眠模式并唤醒

[复制链接]
181|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
丙丁先生|  楼主 | 2024-10-10 10:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
//系统睡眠模式并唤醒演示:GPIOA_6和GPIOA_5作为唤醒源,共6种睡眠等级
#include "CH57x_common.h" // 引入CH57x系列单片机的通用头文件

void DebugInit(void)               
{
    GPIOA_SetBits(GPIO_Pin_9); // 设置GPIOA的第9位为高电平
    GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA); // 配置GPIOA的第9位为推挽输出,输出电流为5mA
    UART1_DefInit(); // 初始化UART1串口
}

int main()
{
    DelayMs(2); // 延时2毫秒
    SetSysClock( CLK_SOURCE_HSE_32MHz ); // 设置外部32MHz晶振作为系统时钟
    GPIOA_ModeCfg( GPIO_Pin_All, GPIO_ModeIN_PU ); // 配置GPIOA的所有引脚为上拉输入模式
    GPIOB_ModeCfg( GPIO_Pin_All, GPIO_ModeIN_PU ); // 配置GPIOB的所有引脚为上拉输入模式

    /* 配置串口调试 */   
    DebugInit(); // 调用DebugInit函数进行调试初始化
    PRINT( "Start @ChipID=%02x
", R8_CHIP_ID ); // 打印芯片ID
    DelayMs(200); // 延时200毫秒

#if 1   
    /* 配置唤醒源为 GPIO - PA6&PA5 */
    GPIOA_ModeCfg( GPIO_Pin_6|GPIO_Pin_5, GPIO_ModeIN_PU ); // 配置GPIOA的第6和第5位为上拉输入模式
    GPIOA_ITModeCfg( GPIO_Pin_6|GPIO_Pin_5, GPIO_ITMode_FallEdge ); // 配置GPIOA的第6和第5位下降沿触发中断
    NVIC_EnableIRQ( GPIO_IRQn ); // 使能GPIO中断
    PWR_PeriphWakeUpCfg( ENABLE, RB_SLP_GPIO_WAKE ); // 使能GPIO唤醒功能
#endif   

#if 1
    PRINT( "IDLE mode sleep \n");   
    DelayMs(1);
    LowPower_Idle(); // 进入IDLE低功耗模式
    PRINT( "wake.. \n");
    DelayMs(500); // 延时500毫秒
#endif   

#if 1
    PRINT( "Halt_1 mode sleep \n");   
    DelayMs(1);
    LowPower_Halt_1(); // 进入Halt_1低功耗模式
/*
使用HSI/5=6.4M睡眠,唤醒时间大概需要 2048Tsys≈330us
HSE起振一般不超过1.2ms(500us-1200us),所以切换到外部HSE,需要 1.2ms-330us 这个时间可以保证HSE足够稳定,一般用于蓝牙
DelayUs()函数时基于32M时钟的书写,此时主频为6.4M,所以 DelayUs((1200-330)/5)   
*/
    if(!(R8_HFCK_PWR_CTRL&RB_CLK_XT32M_PON)) {     // 是否HSE上电
        PWR_UnitModCfg( ENABLE, UNIT_SYS_HSE );   // HSE上电
        DelayUs((1200)/5);
    }
    else if(!(R16_CLK_SYS_CFG&RB_CLK_OSC32M_XT)){   // 是否选择 HSI/5 做时钟源
        DelayUs((1200-330)/5);
    }
    HSECFG_Current( HSE_RCur_100 );     // 降为额定电流(低功耗函数中提升了HSE偏置电流)
    DelayUs(5/5);                       // 等待稳定 1-5us
    SetSysClock( CLK_SOURCE_HSE_32MHz );
    PRINT( "wake.. \n");
    DelayMs(500);   
#endif   

#if 1
    PRINT( "Halt_2 mode sleep \n");   
    DelayMs(1);
    LowPower_Halt_2(); // 进入Halt_2低功耗模式
/*
使用HSI/5=6.4M睡眠,唤醒时间大概需要 2048Tsys≈330us
HSE起振一般不超过1.2ms(500us-1200us),所以切换到外部HSE,需要 1.2ms-330us 这个时间可以保证HSE足够稳定,一般用于蓝牙
DelayUs()函数时基于32M时钟的书写,此时主频为6.4M,所以 DelayUs((1200-330)/5)   
*/
    if(!(R8_HFCK_PWR_CTRL&RB_CLK_XT32M_PON)) {     // 是否HSE上电
        PWR_UnitModCfg( ENABLE, UNIT_SYS_HSE );   // HSE上电
        DelayUs((1200)/5);
    }
    else if(!(R16_CLK_SYS_CFG&RB_CLK_OSC32M_XT)){   // 是否选择 HSI/5 做时钟源
        DelayUs((1200-330)/5);
    }
    HSECFG_Current( HSE_RCur_100 );     // 降为额定电流(低功耗函数中提升了HSE偏置电流)
    DelayUs(5/5);                       // 等待稳定 1-5us
    SetSysClock( CLK_SOURCE_HSE_32MHz );
    PRINT( "wake.. \n");
    DelayMs(500);   
#endif   

#if 1
    PRINT( "sleep mode sleep \n");   
    DelayMs(1);
    LowPower_Sleep( RB_PWR_RAM14K|RB_PWR_RAM2K );       //只保留14+2K SRAM 供电
/*
使用HSI/5=6.4M睡眠,唤醒时间大概需要 2048Tsys≈330us
HSE起振一般不超过1.2ms(500us-1200us),所以切换到外部HSE,需要 1.2ms-330us 这个时间可以保证HSE足够稳定,一般用于蓝牙
DelayUs()函数时基于32M时钟的书写,此时主频为6.4M,所以 DelayUs((1200-330)/5)   
*/
    if(!(R8_HFCK_PWR_CTRL&RB_CLK_XT32M_PON)) {     // 是否HSE上电
        PWR_UnitModCfg( ENABLE, UNIT_SYS_HSE );   // HSE上电
        DelayUs((1200)/5);
    }
    else if(!(R16_CLK_SYS_CFG&RB_CLK_OSC32M_XT)){   // 是否选择 HSI/5 做时钟源
        DelayUs((1200-330)/5);
    }
    HSECFG_Current( HSE_RCur_100 );     // 降为额定电流(低功耗函数中提升了HSE偏置电流)
    DelayUs(5/5);                       // 等待稳定 1-5us
    SetSysClock( CLK_SOURCE_HSE_32MHz );
    PRINT( "wake.. \n");      
    DelayMs(500);
#endif

#if 1
    PRINT( "shut down mode sleep \n");   
    DelayMs(1);
    LowPower_Shutdown( NULL );                          //全部断电,唤醒后复位
/*
   此模式唤醒后会执行复位,所以下面代码不会运行,
   注意要确保系统睡下去再唤醒才是唤醒复位,否则有可能变成IDLE等级唤醒
*/
/*
使用HSI/5=6.4M睡眠,唤醒时间大概需要 2048Tsys≈330us
HSE起振一般不超过1.2ms(500us-1200us),所以切换到外部HSE,需要 1.2ms-330us 这个时间可以保证HSE足够稳定,一般用于蓝牙
DelayUs()函数时基于32M时钟的书写,此时主频为6.4M,所以 DelayUs((1200-330)/5)   
*/
    if(!(R8_HFCK_PWR_CTRL&RB_CLK_XT32M_PON)) {     // 是否HSE上电
        PWR_UnitModCfg( ENABLE, UNIT_SYS_HSE );   // HSE上电
        DelayUs((1200)/5);
    }
    else if(!(R16_CLK_SYS_CFG&RB_CLK_OSC32M_XT)){   // 是否选择 HSI/5 做时钟源
        DelayUs((1200-330)/5);
    }
    HSECFG_Current( HSE_RCur_100 );     // 降为额定电流(低功耗函数中提升了HSE偏置电流)
    DelayUs(5/5);                       // 等待稳定 1-5us
    SetSysClock( CLK_SOURCE_HSE_32MHz );
    PRINT( "wake.. \n");
    DelayMs(500);
#endif

    while(1);   
}

void GPIO_IRQHandler(void)
{
    GPIOA_ClearITFlagBit( GPIO_Pin_6|GPIO_Pin_5 ); // 清除GPIOA的第6和第5位的中断标志位
}


使用特权

评论回复

相关帖子

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

本版积分规则

541

主题

1852

帖子

5

粉丝