硬件工程师做的测试自制最小系统,系统 供电3V
测试目标:
使用原厂的例程,修改GPIO配置后的代码
按键进入深度睡眠状态,
再次按键,唤醒,点亮LED灯2秒。
测试过程:
测试第一次发现,深度睡眠后电流,3V时高达260 uA
找了一圈问题,各个引脚检查,发现引脚状态不正常的KEY2,断开相应的连接。
重新测试后,下降到90 uA
再次排查非GPIO口,将AVCC_USB/AVSS_USB断开,
再次测试,电流下降到36 uA
找不到问题点。再检查 特殊功能IO口,发现BOOT0的电压不正常,不是0,也不是VDD,而是中间的一个值,断开BOOT0连接,电流测试为2.2 uA
但BOOT0是不能悬浮的,检查 程序发现,引脚被配置为输入上拉,将引脚改为输入下拉。
再次测试,电流为2.2uA
致此,低功耗的功耗验证完成。
这里,总结一下问题点:
- 不连接AVCC_USB/AVSS_USB。
- 外部电路的配置不合理。
- PORTF的对应BOOT0的引脚配置错误。
附源码如下:
#include gpio.h
#include lpm.h
static void App_LedInit(void);
static void App_UserKeyInit(void);
static void App_LowPowerModeGpioSet(void);
static void _UserKeyWait(void);
int32_t main(void)
{
///< 配置Demo板上所有不使用的IO为高阻输入,避免端口漏电
App_LowPowerModeGpioSet();
///< LED 端口初始化
App_LedInit(); //初始化LED,并点亮
///< ===============================================
///< ============ 警告,警告,警告!!!============
///< ===============================================
///< 本样例程序会进入深度休眠模式,因此以下两行代码起防护作用(防止进入深度
///< 休眠后芯片调试功能不能再次使用),
///< 在使用本样例时,禁止在没有唤醒机制的情况下删除以下两行代码。
delay1ms(2000);
_UserKeyWait(); ///< 等待按键按下后进入休眠模式
Gpio_SetIO(EVB_LEDR_PORT, EVB_LEDR_PIN); //关闭LED灯
///< 打开并配置按键端口为下降沿中断
Gpio_EnableIrq(EVB_KEY1_PORT, EVB_KEY1_PIN, GpioIrqFalling);
EnableNvic(PORTA_IRQn, IrqLevel3, TRUE);
///< 进入低功耗模式——深度休眠(使能唤醒后退出中断自动休眠特性)
Lpm_GotoDeepSleep(TRUE);
while(1)
{
;
}
}
///< PortC 中断服务函数
void PortA_IRQHandler(void)
{
if(TRUE == Gpio_GetIrqStatus(EVB_KEY1_PORT, EVB_KEY1_PIN))
{
///< LED点亮
Gpio_ClrIO(EVB_LEDR_PORT, EVB_LEDR_PIN);
delay1ms(2000);
///< LED关闭
Gpio_SetIO(EVB_LEDR_PORT, EVB_LEDR_PIN);
Gpio_ClearIrq(EVB_KEY1_PORT, EVB_KEY1_PIN);
}
}
static void _UserKeyWait(void)
{
while(1)
{
///< 检测电平(USER按键是否按下(低电平))
if(FALSE == Gpio_GetInputIO(EVB_KEY1_PORT, EVB_KEY1_PIN))
{
break;
}
else
{
continue;
}
}
}
static void App_LowPowerModeGpioSet(void)
{
///< 打开GPIO外设时钟门控
Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);
//swd as gpio
Sysctrl_SetFunc(SysctrlSWDUseIOEn, TRUE);
///< 配置为数字端口
M0P_GPIO->PAADS = 0;
M0P_GPIO->PBADS = 0;
M0P_GPIO->PCADS = 0;
M0P_GPIO->PDADS = 0;
M0P_GPIO->PEADS = 0;
M0P_GPIO->PFADS = 0;
///< 配置全为上拉使能
M0P_GPIO->PAPU = 0XFFFF;
M0P_GPIO->PBPU = 0XFFFF;
M0P_GPIO->PCPU = 0XFFFF;
M0P_GPIO->PDPU = 0XFFFF;
M0P_GPIO->PEPU = 0XFFFF;
M0P_GPIO->PFPD = 0XFFFF; //PORTF改为下拉
///< 配置为端口输入(除LED端口外)
M0P_GPIO->PADIR = 0XFFFF;
M0P_GPIO->PBDIR = 0XFFFF;
M0P_GPIO->PCDIR = 0XFFFF;
M0P_GPIO->PDDIR = 0XFFFF;
M0P_GPIO->PEDIR = 0XFFFF;
M0P_GPIO->PFDIR = 0XFFFF;
}
static void App_UserKeyInit(void)
{
stc_gpio_cfg_t stcGpioCfg;
///< 打开GPIO外设时钟门控
Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);
///< 端口方向配置->输入
stcGpioCfg.enDir = GpioDirIn;
///< 端口驱动能力配置->高驱动能力
stcGpioCfg.enDrv = GpioDrvL;
///< 端口上下拉配置->无
stcGpioCfg.enPu = GpioPuEnable;
stcGpioCfg.enPd = GpioPdDisable;
///< 端口开漏输出配置->开漏输出关闭
stcGpioCfg.enOD = GpioOdDisable;
///< 端口输入/输出值寄存器总线控制模式配置->AHB
stcGpioCfg.enCtrlMode = GpioAHB;
///< GPIO IO USER KEY初始化
Gpio_Init(EVB_KEY1_PORT, EVB_KEY1_PIN, &stcGpioCfg);
}
static void App_LedInit(void)
{
stc_gpio_cfg_t stcGpioCfg;
///< 打开GPIO外设时钟门控
Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);
///< 端口方向配置->输出(其它参数与以上(输入)配置参数一致)
stcGpioCfg.enDir = GpioDirOut;
< 端口上下拉配置->无
stcGpioCfg.enPu = GpioPuDisable;
stcGpioCfg.enPd = GpioPdDisable;
///< GPIO IO LED端口初始化
Gpio_Init(EVB_LEDR_PORT, EVB_LEDR_PIN, &stcGpioCfg);
///< LED关闭
Gpio_ClrIO(EVB_LEDR_PORT, EVB_LEDR_PIN);
}
void Lpm_GotoDeepSleep(boolean_t bOnExit)
{
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
SCB->SCR |= 1u
__WFI();
}