回首,相濡以沫 发表于 2020-8-5 16:54:52

STM32L051C8进入低功耗模式电流偏大

最近倒腾STM32L051C8的低功耗模式,看了官方给的例程跟一些大佬的代码,然后自己就开始琢磨。我这边是将stm32设置成stop mode with rtc,经测试发现,stm32第一次进入stop mode with rtc的电流是0.8-0.9ua(这跟手册上面的电流大小是相符的),但是从第二次进入stop mode with rtc电流就一直是2.6ua。附上程序

#include "main.h"
#include "led.h"

/* RTC handler declaration */
RTC_HandleTypeDef RTCHandle;

static void Stop_rtc_config(uint32_t sleep);
static void Enter_stop_rtc_mode(void);
static void System_config_before_stop(void);
static void SystemClock_Config(void);
static void SystemClockConfig_STOP(void);


int main(void)
{

                HAL_Init();
                SystemClock_Config();

//                LED_Init();
                while (1)
                {
//                        LED_ON; //点亮LED
                        HAL_Delay(3000);
                        Enter_stop_rtc_mode();//进入stop whit rtc mode
                }
}


static void Enter_stop_rtc_mode(void)
{
                //1. 配置stop之前各外设
                System_config_before_stop();

                //2.设置rtc唤醒时间(s)
                Stop_rtc_config(3);

                //3. 进入stop
                HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);

                //3.退出stop后恢复时钟
                SystemClockConfig_STOP();

                //4.恢复各外设
//                LED_Init();
}


//退出stop后重新设置时钟
//static void clock_config_after_stop(void)
static void SystemClock_Config(void)
{
                HAL_StatusTypeDef ret = HAL_OK;
                RCC_OscInitTypeDef RCC_OscInitStructure = {0};
                RCC_ClkInitTypeDef RCC_ClkInitStructure = {0};

                /* Enable Power Control clock */
                __HAL_RCC_PWR_CLK_ENABLE();

                /* The voltage scaling allows optimizing the power consumption when the device is
                   clocked below the maximum system frequency, to update the voltage scaling value
                   regarding system frequency refer to product datasheet.*/
                __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);//电压缩放降低当器件处于工作状态时的功耗

//                /* Get the Oscillators configuration according to the internal RCC registers */
//                HAL_RCC_GetOscConfig(&RCC_OscInitStructure);

                /* After wake-up from STOP reconfigure the system clock: Enable HSI and PLL */
                RCC_OscInitStructure.OscillatorType = RCC_OSCILLATORTYPE_HSI;
                RCC_OscInitStructure.HSEState = RCC_HSE_OFF;
                RCC_OscInitStructure.HSIState = RCC_HSI_ON;
                RCC_OscInitStructure.PLL.PLLState = RCC_PLL_ON;
                RCC_OscInitStructure.PLL.PLLSource = RCC_PLLSOURCE_HSI;
                RCC_OscInitStructure.PLL.PLLMUL = RCC_PLLMUL_4;
                RCC_OscInitStructure.PLL.PLLDIV = RCC_PLLDIV_2;
                RCC_OscInitStructure.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;               
                ret = HAL_RCC_OscConfig(&RCC_OscInitStructure);
                if (ret != HAL_OK) while (1);

                /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
                   clocks dividers */
                RCC_ClkInitStructure.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
                RCC_ClkInitStructure.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
                RCC_ClkInitStructure.AHBCLKDivider = RCC_SYSCLK_DIV1;
                RCC_ClkInitStructure.APB1CLKDivider = RCC_HCLK_DIV1;
                RCC_ClkInitStructure.APB2CLKDivider = RCC_HCLK_DIV1;                  
                ret = HAL_RCC_ClockConfig(&RCC_ClkInitStructure, FLASH_LATENCY_1);
                if (ret != HAL_OK) while (1);
}


//设置进入stop mode之后rtc唤醒时间(s)
static void Stop_rtc_config(uint32_t sleep)
{
                /* Disable Wakeup Counter */
                HAL_RTCEx_DeactivateWakeUpTimer(&RTCHandle);
      
                /*## Set wake up timer with interrupt */
                HAL_RTCEx_SetWakeUpTimer_IT(&RTCHandle, sleep, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);//选择1Hz时钟
}


//进入stop之前外设设置
static void System_config_before_stop(void)
{
                HAL_StatusTypeDef ret = HAL_OK;

                GPIO_InitTypeDef GPIO_InitStructure;
      
                /* Enable Ultra low power mode */
                HAL_PWREx_EnableUltraLowPower();//VREFINT 在低功耗模式下关闭

                /* Enable the fast wake up from Ultra low power mode */
                HAL_PWREx_EnableFastWakeUp();
      
                /* Select HSI as system clock source after Wake Up from Stop mode */
                __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI);

                /* Enable GPIOs clock */
                __HAL_RCC_GPIOA_CLK_ENABLE();
                __HAL_RCC_GPIOB_CLK_ENABLE();
                __HAL_RCC_GPIOC_CLK_ENABLE();
      
                /* Configure all GPIO port pins in Analog Input mode (floating input trigger OFF) */
                GPIO_InitStructure.Pin = GPIO_PIN_All;
                GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
                GPIO_InitStructure.Pull = GPIO_NOPULL;
                HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
                HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
                HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);

                /* Disable GPIOs clock */
                __HAL_RCC_GPIOA_CLK_DISABLE();
                __HAL_RCC_GPIOB_CLK_DISABLE();
                __HAL_RCC_GPIOC_CLK_DISABLE();

                /* Configure RTC 1Hz,LSE做RTC时钟*/
                RTCHandle.Instance = RTC;
                RTCHandle.Init.HourFormat = RTC_HOURFORMAT_24;
                RTCHandle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV;
                RTCHandle.Init.SynchPrediv = RTC_SYNCH_PREDIV;
                RTCHandle.Init.OutPut = RTC_OUTPUT_DISABLE;
                RTCHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
                RTCHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
                ret = HAL_RTC_Init(&RTCHandle);
                if (ret != HAL_OK) while (1);
}


/**
* @briefSystem Clock Configuration
*         The system Clock is configured as follow :
*            System Clock source            = PLL (HSI)
*            SYSCLK(Hz)                     = 32000000
*            HCLK(Hz)                     = 32000000
*            AHB Prescaler                  = 1
*            APB1 Prescaler               = 1
*            APB2 Prescaler               = 1
*            HSI Frequency(Hz)            = 16000000
*            PLL_MUL                        = 4
*            PLL_DIV                        = 2
*            Flash Latency(WS)            = 1
*            Main regulator output voltage= Scale1 mode
* @paramNone
* @retval None
*/
//void systemClockConfig(void)
static void SystemClockConfig_STOP(void)
{
                HAL_StatusTypeDef ret = HAL_OK;
                RCC_OscInitTypeDef RCC_OscInitStruct = {0};
                RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

                /* Enable Power Control clock */
                __HAL_RCC_PWR_CLK_ENABLE();

                /* The voltage scaling allows optimizing the power consumption when the device is
               clocked below the maximum system frequency, to update the voltage scaling value
               regarding system frequency refer to product datasheet.*/
                __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

                /* Get the Oscillators configuration according to the internal RCC registers */
                HAL_RCC_GetOscConfig(&RCC_OscInitStruct);               
               
                /* After wake-up from STOP reconfigure the system clock: Enable HSI and PLL */
                RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
                RCC_OscInitStruct.HSEState = RCC_HSE_OFF;
                RCC_OscInitStruct.HSIState = RCC_HSI_ON;
                RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
                RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
                RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL4;
                RCC_OscInitStruct.PLL.PLLDIV = RCC_PLL_DIV2;
                RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
                ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);
                if (ret != HAL_OK) while (1);

                /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
                clocks dividers */
                RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
                RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
                ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);
                if (ret != HAL_OK) while (1);
}




看了一些资料也没能搞清楚这多的电流是从哪里来的,有大佬知道吗:'(

废鱼 发表于 2020-8-5 20:25:31

估计是某些IO口的配置问题,建议楼主在进入休眠时,将IO全部设置为输入拉低。不过有的也需要看实际电路连接的情况,比如外设是连接一个上拉电阻时,输入下拉反而会耗电更多。要根据实际电路的情况,进行调整。

回首,相濡以沫 发表于 2020-8-5 22:35:18

安 发表于 2020-8-5 20:25
估计是某些IO口的配置问题,建议楼主在进入休眠时,将IO全部设置为输入拉低。不过有的也需要看实际电路连接 ...

好的,我按照这个思路再检查检查

Tcreat 发表于 2020-8-6 08:32:23

进入STOP之前 保留需要唤醒的设置外 被开启的外设要关闭IO根据休眠后的IO引脚状态设置   比如如果是通过MCU供电电源上拉的,这样引脚得设置为输出高电平,设置为输入模式就不合适了,类推~~

回首,相濡以沫 发表于 2020-8-6 18:23:51

折腾了一天终于解决了,是跟唤醒之后的系统时钟设置有关系。问题解决完之后把工程整理了一下,发出来给大家分享。实际测的stop mode with rtc电流在0.9uA,手册上面是1uA,但我是3.3V供电的,才导致有差异,不过还能接受。程序里面包含按键触发的外部中断部分(下降沿触发),分别是PB3、PB4、PB5、PB8

陌路夕颜 发表于 2020-8-7 09:17:33

进入低功耗需要关闭用不到的外设时钟,关闭大晶振,IO要根据外部电路进行设置,没有用到的IO最好设置成输入上拉。

回首,相濡以沫 发表于 2020-8-7 16:30:31

陌路夕颜 发表于 2020-8-7 09:17
进入低功耗需要关闭用不到的外设时钟,关闭大晶振,IO要根据外部电路进行设置,没有用到的IO最好设置成输入 ...

没有用到的IO口设置成模拟输入是不是更好,官方的例程上面也是设置成模拟输入。因为模拟输入阻抗是很大的,可以看成与外部电路断开。不知道我这解释对不对:lol

Tcreat 发表于 2020-8-7 17:29:49

回首,相濡以沫 发表于 2020-8-7 16:30
没有用到的IO口设置成模拟输入是不是更好,官方的例程上面也是设置成模拟输入。因为模拟输入阻抗是很大的 ...

没用到引脚 设置输入模式基本都差不多

陌路夕颜 发表于 2020-8-7 22:45:50

回首,相濡以沫 发表于 2020-8-7 16:30
没有用到的IO口设置成模拟输入是不是更好,官方的例程上面也是设置成模拟输入。因为模拟输入阻抗是很大的 ...

上拉输入有确定的电平,模拟输入阻抗大,更容易捕获外部干扰

回首,相濡以沫 发表于 2020-8-11 10:53:16

陌路夕颜 发表于 2020-8-7 22:45
上拉输入有确定的电平,模拟输入阻抗大,更容易捕获外部干扰

设置为上拉输入难道不会造成额外的功率损耗吗?在外部干扰小的情况下,是不是模拟输入更加可行?:lol

陌路夕颜 发表于 2020-8-11 12:11:33

回首,相濡以沫 发表于 2020-8-11 10:53
设置为上拉输入难道不会造成额外的功率损耗吗?在外部干扰小的情况下,是不是模拟输入更加可行? ...

不会,这是CC2540的手册上写的

butterflyspring 发表于 2020-8-12 16:51:39

陌路夕颜 发表于 2020-8-11 12:11
不会,这是CC2540的手册上写的

虽然都是MCU产品,不同厂家的设计是不同的,工艺也不同。所以相关的例程配置也会不同。
页: [1]
查看完整版本: STM32L051C8进入低功耗模式电流偏大