一、引言
1. 背景介绍:随着集成电路技术的飞速发展,MCU的功耗问题逐渐成为设计和应用中必须考虑的关键因素。低功耗设计对于提高电路可靠性、降低成本以及延长电池寿命具有至关重要的作用。
2. 目的和意义:本文档主要是以华芯微特SWM341/SWM34S系列芯片,介绍从软件层面降低MCU功耗的方法分享。
二、功耗影响因素
功耗影响因素:供电电压、时钟频率、外设数目以及运行模式等
三、降低功耗方法
1. 控制子模块电路电源:
可以通过GPIO对采样电源进行控制,如SDRAM在不使用时,可以断开SDRAM电源降低功耗。
2. 控制内部外设:
把不需要使用的外设时钟全部关闭,需要时开启。例如,在固件分debug和release版本时,release版本屏蔽串口调试输出,关闭串口时钟。
3. 控制时钟频率:
时钟频率是影响功耗的关键因素,同等时间内,时钟越快,功耗越高。
根据实际工作情况调整时钟频率,如低速工作时适当降低CPU的时钟频率。
4. 控制IO状态:
未用到和悬空的IO,配置为高阻态或模拟输入。凡是对接其他子模块电路的IO需要关注子模块的IO状态进行对应调整,避免存在电压差。
5. 降低唤醒频率:
如通过SPI读取子模块的数据时,可开启子模块的FIFO,由轮询读取改为中断触发读取,提高MCU休眠时间,读取数据更高效。
6. 深层待机模式:
CPU内核及所有时钟源关闭,关闭RAM及LDO等所有外围电路的电源,仅IO管脚(或部分IO管脚)持续供电。
由IO管脚或重置(Reset)管脚唤醒CPU,这种模式具有更低的静态电流,但RAM的数据会丢失。
7. 优化程序代码:
通过优化程序代码,减少不必要的功耗和数据传输。
例如,减少CPU的唤醒次数、降低数据传输的频率和数据量。
五、低功耗应用案例---SWM34SME
SWM341系列有SLEEP和STOP两种低功耗模式。SLEEP模式下,所有外设关闭,Core工作在32KHz,SRAM和FLASH不掉电。STOP模式除BACKUP寄存器外,所有模块停止工作。以GPIO唤醒睡眠为例:
l SWM34SME的SDRAM电源可硬件设计为GPIO控制,先关闭SDRAM电源,减少SDRAM静态功耗。其它系列SWM34S的SDRAM电源会SDRAM相关的IO设置成浮空模式,防止IO漏电。
l 关闭所有外设,其中USB模块需要格外关注,USB PHY供电的情况下会有3mA左右的电流消耗,需要手动关闭, USB工作时钟为外部12MH晶振,关闭之前,需要打开外部12M,关闭后加一点延时,关闭完成后关闭外部晶振。
l 主时钟切换到内部20MHz。
l l 设置任一GPIO唤醒。
l l l 配置进入低功耗模式。
SLEEP模式下,Core时钟自动切换到32KHz,Core此时是工作的,SDRAM没有掉电
STOP模式下,除BACKUP有电之外,包括核在内的其它模块都不工作。
SLEEP模式:
int main(void)
{
uint32_t i;
for(i = 0; i < SystemCoreClock; i++) __NOP(); //防止无法更新程序
SystemInit();
//打开外部12MHz,外部晶振为USB的工作时钟源,关闭USB PHY 之前需要打开
PORT_Init(PORTA, PIN3, PORTA_PIN3_XTAL_IN, 0);
PORT_Init(PORTA, PIN4, PORTA_PIN4_XTAL_OUT, 0);
SYS->XTALCR |= (1 << SYS_XTALCR_ON_Pos) | (15 << SYS_XTALCR_DRV_Pos) | (1 << SYS_XTALCR_DET_Pos);
//等待外振起振
SysTick_Delayus(6000);
TurnOffUSBPower();
//等待USB关闭
SysTick_Delayus(10000);
GPIO_CLR();//设置所有GPIO为浮空状态
SYS->LRCCR |= (1 << SYS_LRCCR_ON_Pos); //开启32K低频振荡器
//开启PN10引脚低电平唤
GPIO_Init(GPIOA, PIN10, 0, 1, 0, 0);
SYS->PAWKEN |= (1 << PIN10);
while(1==1)
{
__disable_irq();
switchTo20MHz(); //休眠前,切换到 20MHz
SYS->PLLCR|=(1<< SYS_PLLCR_OFF_Pos);//关闭PLL
SYS->XTALCR=0; //关闭外部时钟
SYS->PAWKSR = (1 << PIN10); //清除唤醒标志
SYS->SLEEP |= (1 << SYS_SLEEP_SLEEP_Pos); //进入睡眠模式
while((SYS->PAWKSR & (1 << PIN10)) == 0); //等待唤醒条件
switchToPLL(0); //唤醒后,切换到 PLL
__enable_irq();
//切换到 PLL等待一下,看功耗变化
for(i = 0; i < SystemCoreClock/20; i++) __NOP();
}
}
STOP模式:
int main(void)
{
uint32_t i;
//调试阶段建议加延时,防止配置有误造成的死机
for(i=0; i<systemcoreclock; i++)<="" span="">
{
__NOP();
}
SystemInit();
//打开外部12MHz,外部晶振为USB的工作时钟源,关闭USB PHY 之前需要打开
PORT_Init(PORTA, PIN3, PORTA_PIN3_XTAL_IN, 0);
PORT_Init(PORTA, PIN4, PORTA_PIN4_XTAL_OUT, 0);
SYS->XTALCR |= (1 << SYS_XTALCR_ON_Pos) | (15 << SYS_XTALCR_DRV_Pos) | (1 << SYS_XTALCR_DET_Pos);
//等待外振起振
SysTick_Delayus(6000);
TurnOffUSBPower();
//等待USB关闭
SysTick_Delayus(10000);
//BACKUP寄存器值不会唤醒复位
SYS->BACKUP[0] += 1;
GPIO_CLR();//设置所有GPIO为浮空状态
//开启PA10引脚低电平唤醒
GPIO_Init(GPIOA, PIN10, 0, 1, 0, 0);
SYS->PAWKEN |= (1 << PIN10);
while(1==1)
{
for(i = 0; i < SystemCoreClock/4; i++) __NOP();
switchTo20MHz(); //休眠前,切换到 20MHz
SYS->PLLCR|=(1<< SYS_PLLCR_OFF_Pos);//关闭PLL
SYS->PAWKSR = (1 << PIN10); //清除唤醒标志
SYS->SLEEP |= (1 << SYS_SLEEP_STOP_Pos); //进入STOP模式
}
}
void TurnOffUSBPower(void)
{
SYS->USBCR |= 0x07;
SYS->CLKEN0 |= (0x01 << 24);
USBD->DEVCR = (USBD_SPEED_FS << USBD_DEVCR_SPEED_Pos);
USBH->PORTSR |=(1<<2);
SYS->USBPHYCR &= ~SYS_USBPHYCR_PLLEN_Msk;
SYS->USBPHYCR &= ~SYS_USBPHYCR_OPMODE_Msk;
SYS->USBPHYCR |= ( 1 << SYS_USBPHYCR_OPMODE_Pos);
}
void GPIO_CLR(void)
{
//配置所有GPIO为浮空状态
PORT_Init(PORTA, 0, 0, 0);
//…….
PORT_Init(PORTN, 15 , 0, 0);
}
注释:以上两种低功耗模式,工作在3.3V电压下,系统时钟选择PLL100MHz,PLL时钟源为内部20MHz,条件下测试, SLEEP模式下,功耗小600uA,STOP模式,功耗小于1uA。