最近入职了一个公司,没想到又是接到调低功耗的任务!
一、调试步骤步骤
拿到公司的板子,第一个事情是熟悉公司的硬件电路图,把板子上的芯片捋清楚,查查它们的静态工作电流,大概率会找到偷功耗的小偷,同时把这些信息整理成一个文档,表面工作尤其重要(功耗没调下来,文档先输出,显得你工作做事有逻辑!)
第二个事情:做最小系统板,开始吹芯片,把板子上原有的芯片,用热风枪吹下来(功耗也会接着下来),观察功耗,如果芯片进入了低功耗模式,大概率是能够达几十微安或者两、三百微安;
那么,芯片都进入了低功耗模式了,外围芯片都吹下来了,只剩最小系统板,剩下的功耗从哪几个地方产生,这就是考验你耐心(运气)的时候了。
Stm32进入低功耗模式,无论是sleep/standby/stop,都是10ua以下的,这个一般是依据产品设计的应用场景,选择低功耗模式使用哪个,在这里就不拓展
如果你在网上查询过,你也可以很快判断出漏电的原因大部分是io的设置,io漏电原理是因为io连接的外围器件与芯片io内部形成了回路。
按照一般设置方法,就是在芯片进入低功耗模式前,对所有的io进行设置
void sys_standby(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
PWR_WakeUpPinCmd(ENABLE);
//PWR_EnterSTANDBYMode();
sys_low_power_io_init();
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
sys_normal_io_init();
}
其中包含使用io和非使用io
使用io为了思路更清晰,分使用模块,逐个IO去设置
void sys_low_power_io_init(void)
{
//所有IO初始化
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_Init(GPIOF, &GPIO_InitStructure);
GPIO_Init(GPIOG, &GPIO_InitStructure);
// 蓝牙
// BLE_INT 上拉 PA0
// BLE_WAKE 悬空 PA1
// TD2 PA2
// RD2 PA3
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
PAout(2)=1;
PAout(3)=1;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 晶振
// PC14、PC15
// OSC_IN、OSC_OUT
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
// W25X40
// NSS有上拉:R44(已拆除),其他悬空
// NSS:PA4
// SCK:PA5
// MISO:PA6
// MOSI:PA7
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//RS485
// rw1_485悬空:PA8 下拉电阻R50
// RD1:PA10
// TD1:PA9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//LM75BD 上拉已去除 各个io悬空
// SDA PB7
// SCL PB6
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//SW烧录口
//SWDIO PA13
//SWCLK PA14
// GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);//关闭JTAG
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
其中io设置原则模拟输入/开漏输出高电平/其他都可以,唯一要保持的原则是不要让io和外围电路形成回路
二、调试方法
或许你已经参照了我的流程对io设置了一遍,但是电流发现还是没降下来
我在这里分享两个硬件调试方法
2.1 用镊子短路板子上的每一个电阻,找到短路后让整机电流异常的电阻,去除;
这个方法是用来判断外围电路没清楚干净导致的漏电情况
2.2 用杜邦线,一头接gnd/3.3V,直接在芯片的io上点,找到可以让整机电流降低的io,注意别点到芯片上的vcc/gnd
这个方法我尝试用过,但是没成功找到对应io(非IO漏电),但是也写下来,保留分享用途