打印

GD32 之低功耗下的唤醒问题

[复制链接]
1346|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
drer|  楼主 | 2021-6-5 18:31 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

GD32 省电模式有三种如下


使用特权

评论回复
沙发
drer|  楼主 | 2021-6-5 18:32 | 只看该作者

之前用过的EFM32 有4中低功耗模式(对比下来就知道EFM32在功耗方面是多么领先)


使用特权

评论回复
板凳
drer|  楼主 | 2021-6-5 18:34 | 只看该作者
本帖最后由 drer 于 2021-6-5 18:41 编辑

目前的场景是要循环的读取温度sensor的数据,每隔一定的时间读取一次,并且在整个设备运行期间,要及时的响应按键的长按和短按,首先想到的就是deep sleep模式了。

OK,尝试一下,循环读取

循环读取我采用timer的方式,每隔2s读一次,设定好timer,读取温度之后进入deep sleep 模式

这样可行吗?

通过timer唤醒处于deep sleep模式下的设备?

低功耗模式先看时钟,哪个时钟?

你要用哪个外设唤醒系统,就看那个外设的时钟。注意这里的外设不仅指的是MCU的外设,而且也指的是Cortex M的外设。

deep sleep 模式的介绍:



深度睡眠模式下1.2V域中的所有时钟全部关闭。

timer用的时钟是怎么样的呢?是从哪里来的呢?

看下clock tree





看TIMER的时钟是由CLK_SYS通过AHB和APB2系统分频倍频来的。

所有如果系统时钟,或者AHB,APB时钟关掉的话,timer肯定无法工作的。


使用特权

评论回复
地板
drer|  楼主 | 2021-6-5 18:35 | 只看该作者
本帖最后由 drer 于 2021-6-5 18:40 编辑

那么前面说到的deep sleep 模式下1.2V 电源域中时钟全部关闭,1.2V电源域中有哪些部分呢?



1.2V电源域包括Cortex-M4 AHB ,APB 等部分。

也就是说deep sleep模式下这些clock都是关闭的,timer根本就起不来。所以想用timer来唤醒deep sleep,

送你两个字, 呵(休)呵(想)



那用什么可以唤醒处于deep sleep模式的设备呢?

除了SPEC中说的EXTI还有什么RTC可以吗?你看RTC是在备份域中,用的时钟是LXTAL.deep sleep好像并没有影响到RTC这部分。


使用特权

评论回复
5
drer|  楼主 | 2021-6-5 18:42 | 只看该作者

DeepSleep 状态下能否用RTC来唤醒呢?

先来看一个问题,

前面介绍说,DeepSleep模式下只能

EXTI的中断或者事件来唤醒


使用特权

评论回复
6
drer|  楼主 | 2021-6-5 18:43 | 只看该作者
问题来了,为什么只能通过EXTI的中断或者事件来唤醒?

EXTI何方神圣?

就是个中断控制器,Cortex M内核 集成了这个东西,哦,不,Cortex M 集成了叫NVIC的东西 (嵌套式矢量型中断控制器)。

而EXTI主要是处理来自于IO管脚(0~15)的16个中断(PA0~PA15,PB0~PB15.....)

除此之外,好像EXTI有多余的脚,不用白不用(是否是因为有多余的脚才引出的下文是我YY的)

EXTI还接收来自LVD,RTC闹钟,USBFSFS的中断。

注意了,敲下黑板,是RTC闹钟,不是特么的RTC秒中断。

再敲下黑板,RTC闹钟接在EXTI中断线上,啥,想想我之前利用按键尝试可以在deep sleep模式下唤醒,而且spec也说了,可以通过EXTI来唤醒deep sleep。那这次就可以用RTC的闹钟中断来唤醒deep sleep喽?



搞一搞,搞一搞。

首先设能RTC闹钟中断

其次初始化RTC闹钟对应在EXTI上的中断

然后设置RTC闹钟

最后等待中断

OK,哇,可以了。终于产生中断了。。。。终于唤醒deep sleep了。。。。

呵呵呵,YY中



使用特权

评论回复
7
drer|  楼主 | 2021-6-5 18:44 | 只看该作者
关于RTC的设置

还是官方的例子,里面有设置RTC闹钟中断使能的,自己找找,只要眼球和眼角膜还在,可以看得到的

void rtc_configuration(void)
{
    /* enable PMU and BKPI clocks */
    rcu_periph_clock_enable(RCU_BKPI);
    rcu_periph_clock_enable(RCU_PMU);
    /* allow access to BKP domain */
    pmu_backup_write_enable();

    /* reset backup domain */
    bkp_deinit();

    /* enable LXTAL */
    rcu_osci_on(RCU_LXTAL);
    /* wait till LXTAL is ready */
    rcu_osci_stab_wait(RCU_LXTAL);

    /* select RCU_LXTAL as RTC clock source */
    rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);

    /* enable RTC Clock */
    rcu_periph_clock_enable(RCU_RTC);

    /* wait for RTC registers synchronization */
    rtc_register_sync_wait();

    /* wait until last write operation on RTC registers has finished */
    rtc_lwoff_wait();

    /* enable the RTC second and alarm interrupt*/
    rtc_interrupt_enable(RTC_INT_SECOND);
    rtc_interrupt_enable(RTC_INT_ALARM);
    /* wait until last write operation on RTC registers has finished */
    rtc_lwoff_wait();

    /* set RTC prescaler: set RTC period to 1s */
    rtc_prescaler_set(32767);

    /* wait until last write operation on RTC registers has finished */
    rtc_lwoff_wait();
}


使用特权

评论回复
8
drer|  楼主 | 2021-6-5 18:45 | 只看该作者
初始化RTC闹钟对应在EXTI上的中断

/*
; 57:RTC Alarm
*/
void rtc_alarm_exti_init(void)
{

    /* enable and set EXTI interrupt to the lowest priority */
    nvic_irq_enable(RTC_ALARM_IRQn, 2U, 0U);
    /* configure EXTI line */
    exti_init(EXTI_17, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
    exti_interrupt_flag_clear(EXTI_17);
       
        //exti_interrupt_enable(EXTI_17);
}


使用特权

评论回复
9
drer|  楼主 | 2021-6-5 18:46 | 只看该作者
设置闹钟 10s "闹" 一下

#define DELAY_SECOND 10
void set_rtc_alarm(void)
{
                uint32_t current_counter = 0, max_counter = 0, alarm_counter = 0, year = 0;;

                current_counter = rtc_counter_get();
                year = (current_counter >> 25) + MIN_YEAR;
                max_counter = IS_LEAP_YEAR(year) ? (366 * 24 * 3600) : (365 * 24 * 3600);

                /* calculate the alarm_counter = current_counter + 10 second */
                if(((current_counter & 0x01FFFFFF) + DELAY_SECOND) < max_counter){
                        alarm_counter = current_counter + DELAY_SECOND;
                }else{
                        year++;
                        if(year > MAX_YEAR){
                                year = MIN_YEAR;
                        }
                       
                        alarm_counter = ((year - MIN_YEAR) << 25) + (((current_counter & 0x01FFFFFF) + 10) - max_counter);
                }
               
                /* set the alarm_counter */
                rtc_lwoff_wait();
                rtc_alarm_config(alarm_counter);
                rtc_lwoff_wait();

}


使用特权

评论回复
10
drer|  楼主 | 2021-6-5 18:47 | 只看该作者
简单的测试程序

        while(1){
       

                set_rtc_alarm();

                dw_deep_sleep_mode();

                printf("next...\n");
        }
每次闹钟时间到了之后,需要重新设置一下alarm ----set_rtc_alarm()



OK 结束!


使用特权

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

本版积分规则

60

主题

3315

帖子

4

粉丝