发新帖我要提问
123
返回列表
打印
[其他ST产品]

STM32通用低功耗组件——PM

[复制链接]
楼主: 欢乐家园
手机看帖
扫描二维码
随时随地手机跟帖
41
欢乐家园|  楼主 | 2022-4-29 14:53 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
在空闲线程中
会调用rt_system_power_manager接口来进入低功耗模式:

使用特权

评论回复
42
欢乐家园|  楼主 | 2022-4-29 14:54 | 只看该作者
/**
* This function will enter corresponding power mode.
*/
void rt_system_power_manager(void)
{
    rt_uint8_t mode;

    if (_pm_init_flag == 0)
        return;

    /* CPU frequency scaling according to the runing mode settings */
    _pm_frequency_scaling(&_pm);

    /* Low Power Mode Processing */
    mode = _pm_select_sleep_mode(&_pm);
    _pm_change_sleep_mode(&_pm, mode);
}

使用特权

评论回复
43
欢乐家园|  楼主 | 2022-4-29 14:55 | 只看该作者
保存后,可以看到pm.c已经被添加到了工程:

然后添加PM组件的设备驱动,驱动的最新地址:pm-ports-stm32-new 分支:https://gitee.com/sunwancn/rt-thread/tree/pm-ports-stm32-new注意: 目前所使用的驱动不是最新版本,移植请到gitee下载最新pm驱动。

使用特权

评论回复
44
欢乐家园|  楼主 | 2022-4-29 14:55 | 只看该作者
从\rt-thread\bsp\stm32\libraries\HAL_Drivers,拷贝如下四个文件到工程的drivers文件夹下:

使用特权

评论回复
45
欢乐家园|  楼主 | 2022-4-29 14:56 | 只看该作者
本项目选择的是使用RTC作为STOP后的时间补偿,所以需要打开rtc设备和所使用的宏:

注: 如果没有使用RTT的自身的RTC函数的话,前面2个宏可以不要。

使用特权

评论回复
46
欢乐家园|  楼主 | 2022-4-29 14:57 | 只看该作者
应用示例:此程序主要实现开机后经过10秒后进入 STOP 模式,然后每经过5秒 SLEEP 模式和 STOP 模式互相切换,如此循环往复,同时经过一个循环后,切换 MCU 的运行频率,验证运行的稳定性。并且打开了回调和中断唤醒,在进入睡眠和唤醒后会分别熄灭和点亮LED灯,在睡眠时间可以通过外部中断唤醒:

/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date           Author       Notes
* 2018-11-06     SummerGift   first version
*/

#include
#include
#include
#include
#define LOG_TAG             'PM.test'
#define LOG_LVL             LOG_LVL_DBG
#include
/* defined the LED0 pin: PB13 */
#define LED0_PIN   GET_PIN(C, 6)
#define MCU_IRQ_WAKE_PIN   GET_PIN(C, 9)
static RTC_HandleTypeDef hrtc;
static RTC_TimeTypeDef curtime = {0};
static RTC_TimeTypeDef alarmtime = {0};
static RTC_AlarmTypeDef alarm = {0};
static struct rt_semaphore  wake_sem;
static rt_uint8_t sleep_mode = PM_SLEEP_MODE_DEEP; /* STOP 模式 */

static rt_uint8_t run_mode = PM_RUN_MODE_NORMAL_SPEED;

static rt_uint32_t get_interval(void);
static void get_rtc_time(RTC_TimeTypeDef *time);
static rt_uint8_t mode_loop(void);
static rt_uint8_t issleep = 0;
/* 中断回调函数 */
static void MCU_IRQ_WAKE(void *args)
{

   if(issleep)
  {
       rt_kprintf('MCU_IRQ_WAKE!\n');
       rt_sem_release(&wake_sem);
       issleep = 0;
  }

}
static void pm_botify(uint8_t event, uint8_t mode, void *data)
{

   if(event == RT_PM_ENTER_SLEEP && mode == PM_SLEEP_MODE_DEEP)
  {
       rt_pin_write(LED0_PIN, PIN_HIGH);
       issleep = 1;
  }
   else if (event == RT_PM_EXIT_SLEEP && mode == PM_SLEEP_MODE_DEEP )
  {
       rt_pin_write(LED0_PIN, PIN_LOW);
  }
}

int pm_test(void)
{
   hrtc.Instance = RTC;

   rt_sem_init(&wake_sem, 'wake_sem', 0, RT_IPC_FLAG_FIFO);
   rt_pm_notify_set(pm_botify,0);
   /* 按键0引脚为输入模式 */
   rt_pin_mode(MCU_IRQ_WAKE_PIN, PIN_MODE_INPUT_PULLDOWN);
   /* 绑定中断,上升沿模式,回调函数名为beep_on */
   rt_pin_attach_irq(MCU_IRQ_WAKE_PIN, PIN_IRQ_MODE_RISING, MCU_IRQ_WAKE, RT_NULL);
   /* 使能中断 */
   rt_pin_irq_enable(MCU_IRQ_WAKE_PIN, PIN_IRQ_ENABLE);

   rt_thread_mdelay(10000);


#ifdef RT_USING_PM
   /* 申请低功耗模式 */
   rt_pm_request(sleep_mode);
#endif

   get_rtc_time(&curtime);

   if (sleep_mode == PM_SLEEP_MODE_STANDBY)
  {
       /* 设置休眠,闹钟 20 秒后唤醒,简化版闹钟,只支持 1分钟内有效 */
       alarmtime.Hours = curtime.Hours;
       alarmtime.Minutes = curtime.Minutes;
       alarmtime.SubSeconds = curtime.SubSeconds;
       alarmtime.Seconds = curtime.Seconds + 20;
       if (alarmtime.Seconds >= 60)
      {
           alarmtime.Seconds -= 60;
           alarmtime.Minutes ++;
           if (alarmtime.Minutes >= 60)
               alarmtime.Minutes -= 60;
      }

       alarm.Alarm = RTC_ALARM_A;
       alarm.AlarmTime = alarmtime;
       alarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
       alarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
       alarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY | RTC_ALARMMASK_HOURS;
       alarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_NONE;
       alarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
       alarm.AlarmDateWeekDay = 0x1;

       /* 开启闹钟 */
       HAL_RTC_SetAlarm_IT(&hrtc, &alarm, RTC_FORMAT_BIN);
  }

   while (1)
  {
       /* 开始进入低功耗模式 */
       rt_sem_take(&wake_sem, rt_tick_from_millisecond(5000));

       /* 退出低功耗模式 */
       rt_kprintf('Sleep %d ms\n', get_interval());

#ifdef RT_USING_PM
       /* 申请正常模式 */
       rt_pm_request(PM_SLEEP_MODE_NONE);
#endif

       rt_thread_mdelay(5000);

       rt_kprintf('Wakeup %d ms\n', get_interval());

       /* 运行模式切换 */
       rt_pm_run_enter(mode_loop());

#ifdef RT_USING_PM
       rt_pm_release(PM_SLEEP_MODE_NONE);
#endif
  }

   return RT_EOK;
}
//MSH_CMD_EXPORT(pm_test, PM TEST);

static rt_uint32_t get_interval(void)
{
   rt_uint32_t seconds;

   rt_uint32_t last_seconds = curtime.Seconds;
   rt_uint32_t last_subseconds = curtime.SubSeconds;

   get_rtc_time(&curtime);

   if (curtime.Seconds < last_seconds)
       seconds = 60 + curtime.Seconds - last_seconds;
   else
       seconds = curtime.Seconds - last_seconds;

   return (rt_uint32_t)(seconds * 1000 + ((int32_t)last_subseconds - (int32_t)curtime.SubSeconds) * 1000 \
                        / (int32_t)(((RTC->PRER & RTC_PRER_PREDIV_S) >> RTC_PRER_PREDIV_S_Pos) + 1U));
}

static void get_rtc_time(RTC_TimeTypeDef *time)
{
   rt_uint32_t st, datetmpreg;

   HAL_RTC_GetTime(&hrtc, time, RTC_FORMAT_BIN);
   datetmpreg = RTC->DR;
   if (HAL_RCC_GetPCLK1Freq() < 32000U * 7U)
  {
       st = time->SubSeconds;
       HAL_RTC_GetTime(&hrtc, time, RTC_FORMAT_BIN);
       datetmpreg = RTC->DR;

       if (st != time->SubSeconds)
      {
           HAL_RTC_GetTime(&hrtc, time, RTC_FORMAT_BIN);
           datetmpreg = RTC->DR;
      }
  }
  (void)datetmpreg;
}

rt_uint8_t mode_loop(void)
{
   rt_uint8_t mode = 1;

   run_mode++;
   switch (run_mode)
  {
   case 0:
   case 1:
   case 2:
   case 3:
       mode = run_mode;
       break;
   case 4:
       mode = 2;
       break;
   case 5:
       mode = 1;
       break;
   case 6:
       mode = run_mode = 0;
       break;
  }

   return mode;
}

使用特权

评论回复
47
欢乐家园|  楼主 | 2022-4-29 14:58 | 只看该作者
运行效果:

使用特权

评论回复
48
foxsbig| | 2022-5-3 08:55 | 只看该作者
怎么个通用法呢

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则