这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » 国产MCU » 【CW32F030C8T6】:分享深度休眠模式开发经验

共1条 1/1 1 跳转至

【CW32F030C8T6】:分享深度休眠模式开发经验

高工
2026-09-19 16:35:48     打赏

一、概述

CW32F030 是武汉芯源半导体推出的通用高性能 32 位微控制器,基于 ARM Cortex-M0+ 内核,最高主频 48MHz,内置最大 64KB Flash 与 8KB RAM。在电源管理方面,芯片提供了两种低功耗模式:睡眠模式(Sleep)与深度休眠模式(DeepSleep),并配有上电/掉电复位(POR/BOR)和可编程低电压检测器(LVD)。低功耗设计是电池供电类产品选型与开发的核心考量,本文围绕 CW32F030 的两种低功耗模式,介绍其原理、特点、唤醒机制、典型应用与调试心得。

二、睡眠模式(Sleep)

  1. 模式特点

睡眠模式下,CPU 内核时钟停止,程序暂停执行,但外设时钟可以独立配置为运行或停止。SRAM、寄存器和外设状态全部保持,任意中断或事件(如定时器中断、外部中断、串口接收等)都可以将 CPU 立即唤醒,唤醒时间只有几个时钟周期。

进入睡眠模式只需执行 WFI(等待中断)或 WFE(等待事件)指令。该模式下功耗取决于仍在运行的外设与时钟,一般在几十到几百微安量级。

2. 适用场景

睡眠模式适合“短时间待命、快速响应”的场景,例如等待 CAN 报文、定时器事件、串口数据等,CPU 空闲但需要保持外设随时工作的场合。

三、深度休眠模式(DeepSleep)

  1. 模式特点

深度休眠是 CW32F030 真正意义上的低功耗模式。进入该模式后:CPU 停止运行;高速时钟(HSE 外部晶振、HSIOSC 内部 48MHz RC 振荡器)自动关闭;仅低速时钟和少量外设保持运行,如 RTC、独立看门狗(IWDT)、低电压检测(LVD)、GPIO、电压比较器(VC)、UART 和异步唤醒定时器(AWT)等,MCU 功耗因此大幅下降。在进入深度休眠前关闭所有外设时钟,深度休眠电流可降至 20μA 以下;不同条件下的实测值因外设保留情况和温度电压而异(有网友对比测评称典型值可低至 1.5μA 量级,条件为 3.3V、25℃)。SRAM 与寄存器内容在深度休眠下保持,GPIO 引脚电平状态也会自动保持,无需软件干预。

2. 如何进入

需要设置系统控制寄存器(SCR)中的 SLEEPDEEP 位,然后执行 WFI 或 WFE 指令进入。唤醒后相当于从停止状态恢复,需要重新初始化系统时钟树和相关外设。

3. 唤醒机制

深度休眠支持多种唤醒源:RTC 闹钟或周期唤醒(最常用,适合定时采集与定时上报);外部 IO 中断(边沿或电平触发,配合内部上拉/下拉与滤波,适合按键、门磁等事件唤醒);复位引脚 NRST;LVD 低电压检测(电压异常时唤醒处理);IWDT 独立看门狗;UART(通过 RXD 引脚 GPIO 下降沿中断实现接收唤醒);VC 电压比较器与 AWT 异步唤醒定时器等。唤醒响应时间为微秒级,远快于复位重启,但比睡眠模式略长。

4. 深度休眠下的 UART 接收唤醒

官方给出了在深度休眠下用 UART 接收数据的配置步骤:

第一步,使能 UARTx_RXD 对应引脚的 GPIO 下降沿中断;

第二步,设置 UARTx_CR1.START 为 1,选择 RXD 信号起始位判定方式为低电平;

第三步,使能 UART 接收(置 UARTx_CR1.RXEN 为 1);

第四步,进入深度休眠模式;

第五步,主机发送数据,产生 GPIO 下降沿中断唤醒 MCU;

第六步,关闭 RXD 对应引脚的 GPIO 中断功能,等待 RXD 接收完成。

软件进入深度睡眠模式

void DeepSleepModeTest(void)
{
    uint8_t res = 0u;
    GPIO_InitTypeDef GPIO_InitStructure;
    PWR_InitTypeDef PWR_InitStructure;
    
    /* Configure all GPIO as analog to reduce current consumption on non used IOs */
    /* Warning : Reconfiguring all GPIO will close the connexion with the debugger */
    /* Enable GPIOs clock */
    //打开GPIO时钟
    REGBITS_SET( CW_SYSCTRL->AHBEN, SYSCTRL_AHBEN_GPIOA_Msk | SYSCTRL_AHBEN_GPIOB_Msk |\
                      SYSCTRL_AHBEN_GPIOC_Msk | SYSCTRL_AHBEN_GPIOF_Msk);
    
    GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStructure.IT = GPIO_IT_NONE;
    GPIO_InitStructure.Pins = GPIO_PIN_All;
    GPIO_Init(CW_GPIOA, &GPIO_InitStructure);
    GPIO_Init(CW_GPIOB, &GPIO_InitStructure);
    GPIO_Init(CW_GPIOC, &GPIO_InitStructure);
    GPIO_Init(CW_GPIOF, &GPIO_InitStructure);
    
    //关闭GPIO时钟
    REGBITS_CLR( CW_SYSCTRL->AHBEN, SYSCTRL_AHBEN_GPIOA_Msk | SYSCTRL_AHBEN_GPIOB_Msk |\
                      SYSCTRL_AHBEN_GPIOC_Msk | SYSCTRL_AHBEN_GPIOF_Msk);
    
    /* Configure User Button */
    BSP_PB_Init();
    
    /* Configures system clock after wake-up from DeepSleep: enable HSI and PLL with HSI as source*/
    // 唤醒后自动使用内部高速时钟(HSI)
    RCC_WAKEUPCLK_Config(RCC_SYSCTRL_WAKEUPCLKEN);
    
    /* Enter Stop Mode */
    PWR_InitStructure.PWR_Sevonpend = PWR_Sevonpend_Disable;
    PWR_InitStructure.PWR_SleepDeep = PWR_SleepDeep_Enable;
    PWR_InitStructure.PWR_SleepOnExit = PWR_SleepOnExit_Disable;
    PWR_Config(&PWR_InitStructure);
    
    //打开FLASH时钟
    REGBITS_SET( CW_SYSCTRL->AHBEN, SYSCTRL_AHBEN_FLASH_Msk);
    REGBITS_SET(CW_FLASH->CR1, FLASH_CR1_STANDBY_Msk); //打开FLASH低功耗使能控制
    //关闭FLASH时钟
    REGBITS_CLR( CW_SYSCTRL->AHBEN, SYSCTRL_AHBEN_FLASH_Msk);
}

进入睡眠模式:

void SleepModeTest(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  PWR_InitTypeDef PWR_InitStructure;

  /* Configure all GPIO as analog to reduce current consumption on non used IOs */
  /* Enable GPIOs clock */
  /* Warning : Reconfiguring all GPIO will close the connexion with the debugger */
  //打开GPIO时钟
  REGBITS_SET( CW_SYSCTRL->AHBEN, SYSCTRL_AHBEN_GPIOA_Msk | SYSCTRL_AHBEN_GPIOB_Msk |\
                      SYSCTRL_AHBEN_GPIOC_Msk | SYSCTRL_AHBEN_GPIOF_Msk);

  GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
  GPIO_InitStructure.IT = GPIO_IT_NONE;
  GPIO_InitStructure.Pins = GPIO_PIN_All;
  GPIO_Init(CW_GPIOA, &GPIO_InitStructure);
  GPIO_Init(CW_GPIOB, &GPIO_InitStructure);
  GPIO_Init(CW_GPIOC, &GPIO_InitStructure);
  GPIO_Init(CW_GPIOF, &GPIO_InitStructure);

  /* Disable GPIOs clock */
  REGBITS_CLR( CW_SYSCTRL->AHBEN, SYSCTRL_AHBEN_GPIOA_Msk | SYSCTRL_AHBEN_GPIOB_Msk |\
                      SYSCTRL_AHBEN_GPIOC_Msk | SYSCTRL_AHBEN_GPIOF_Msk);

  /* Configure User push-button as external interrupt generator */
  BSP_PB_Init();

  /*Suspend Tick increment to prevent wakeup by Systick interrupt.
    Otherwise the Systick interrupt will wake up the device within 1ms (HAL time base)*/
  SuspendTick();

  /* Request to enter SLEEP mode */
  //HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
  PWR_InitStructure.PWR_Sevonpend = PWR_Sevonpend_Disable;
  PWR_InitStructure.PWR_SleepDeep = PWR_SleepDeep_Disable;
  PWR_InitStructure.PWR_SleepOnExit = PWR_SleepOnExit_Disable;
  PWR_Config(&PWR_InitStructure);
  PWR_GotoLpmMode();

  /* Resume Tick interrupt if disabled prior to sleep mode entry*/
  ResumeTick();

  /* Initialize led */
  LED_Init();
}

总结

CW32F030 的睡眠模式适合“短待机、快响应”,深度休眠模式则是长待机低功耗产品的核心武器。用好这两种模式的关键,

一是休眠前把不必要的外设与时钟全部关掉,

二是唤醒后完整重建时钟与外设环境,

三是合理设计唤醒源并实测验证。掌握这些要点,就能在性能与功耗之间取得良好平衡。




关键词: CW32F030C8T6     深度     休眠    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]