乐此不疲 发表于 2024-1-25 16:30:06

请教RTC中断能否唤醒主时钟停振/省电模式?【已解决】

本帖最后由 乐此不疲 于 2024-1-25 21:10 编辑

如题!数据手册中掉电唤醒方式中并没有录入RTC中断唤醒方式,我在使用时也就没有考虑这个方案,今天翻看帖子看到有说RTC中断可以唤醒,详见:RTC中断可以唤醒[主时钟停振/省电模式]https://www.stcaimcu.com/forum.php?mod=viewthread&tid=3759(出处: 国芯论坛-STC全球32位8051爱好者互助交流社区))
于是我就用开天斧实验板试了一下,测试代码如下(3.3V供电、RTC使用外部晶振):
//----------------------------------------------------------------
void RTC_config(void)
{
    X32KCR = 0xc0; //启动外部 32K 晶振

    while (!(X32KCR & 0x01)); //等待时钟稳定

    RTCCFG &= ~0x02; //选择外部 32K 作为 RTC 时钟源
    INIYEAR = 21; //Y:2023
    INIMONTH = 12; //M:11
    INIDAY = 31; //D:16
    INIHOUR = 23; //H:8
    INIMIN = 59; //M:15
    INISEC = 50; //S:50
    INISSEC = 0; //S/128:0
    RTCCFG |= 0x01; //触发 RTC 寄存器初始化
    RTCIF = 0; //清中断标志
      RTCIEN =0x10;      //使能 RTC 分中断
    //RTCIEN = 0x10;      //使能 RTC 秒中断
    RTCCR = 0x01; // RTC 使能
}
//----全部I/O准双向工作模式-----------------------
void set_IO()
{
    P1M0 = 0x00;
    P1M1 = 0x00;
    P2M0 = 0x00;
    P2M1 = 0x00;
    P3M0 = 0x00;
    P3M1 = 0x00;
    P4M0 = 0x00;
    P4M1 = 0x00;
    P5M0 = 0x00;
    P5M1 = 0x00;
    P6M0 = 0x00;
    P6M1 = 0x00;
    P7M0 = 0x00;
    P7M1 = 0x00;
}
//----I/O数字输入通道开/管控制---------------------
void Digital_input_SW(u8 n)
{
    if(n == 1) //全部关闭
    {
      P1IE = 0x00;
      P2IE = 0x00;
      P3IE = 0x00;
      P4IE = 0x00;
      P5IE = 0x00;
      P6IE = 0x00;
      P7IE = 0x00;
    }

    if(n == 2) //开启
    {
      P3IE = 0xef; //P34开启数字输入(BUSY)
    }
}
//----------------------------------------------
void main(void)
{

    P_SW2 |= 0x80; //使能 XFR 访问
    set_IO();

    RTC_config();
    UartInit();
    IT0 = 1;//使能INT0下降沿中断
    EX0 = 1;//使能INT0中断
    EA = 1;
    Digital_input_SW(1);//关闭所有I/O的数字输入

    led = 1;

//printf("RTC Test Programme!\r\n"); //UART 发送一个字符串
    while (1)
    {
      PCON = 0x02;//MCU 进入掉电模式
      NOP15();

//掉电唤醒后串口发送数据
      if(B1S_Flag)
      {
            B1S_Flag = 0;
            printf("Year=20%bd ", YEAR);
            printf("Month=%bd ", MONTH);
            printf("Day=%bd ", DAY);
            printf("Hour=%bd ", HOUR);
            printf("Minute=%bd ", MIN);
            printf("Second=%bd ", SEC);
            printf("\r\n");
      }

    }
}

//----------------------------------------------------------------
void RTC_Isr() interrupt 36
{
    if(RTCIF & 0x10) //判断是否秒中断
    {
      RTCIF &= ~0x10; //清中断标志0x08
      B1S_Flag = 1;
      led = ~led;
    }
}



我的测试方法是,在程序正常运行的情况下RTC每分钟中断控制P25端的led闪烁,同时串口发送时间到串口助手窗口,测试结果完全正常。
但如果加入启动休眠的控制PCON = 0x02;这行代码后,无论是下载完成或者重新上电后程序都不能运行,不亮灯、不发送数据。

接下来我加入了P32引脚的外部中断程序,此后,在休眠状态下如果首先按下P32的按键触发一次掉电唤醒则接下来程序就会自主运行起来了,灯可以闪烁、可见到串口发送的数据了,此后如果保持供电就会维持RTC中断的唤醒模式不再需要P32的参与了。

综上,貌似这个RTC中断唤醒模式需要外部中断来启动一下才能进入状态,这似乎不太靠谱,我不知道是我的测试方法有毛病还我的测试代码有问题,请各位指点一下。

我是想做一个真正省电的日历牌,MCU每天24小时只在凌晨启动工作一次,运行一分钟刷新EPD显示器,一直在摸索实现方法但总是没能实现真正的低功耗稳定运行。诚心请梁工或其他工程师能点拨一下,,先谢了!

神农鼎 发表于 2024-1-25 18:16:12

RTC中断能否唤醒主时钟停振/省电模式
==可以,见 STC8H实验箱程序

深圳国芯人工智能有限公司-实验箱 (stcai.com)

神农鼎 发表于 2024-1-25 18:18:18


第51个演示程序

乐此不疲 发表于 2024-1-25 21:16:37

神农鼎 发表于 2024-1-25 18:18
第51个演示程序
多谢,已经可以实现掉电唤醒了,我原本就是以你指出的这个程序为蓝本去除了低电压判断部分代码后进行测试的,惭愧的是作业没有抄全,RTC初始化代码的最后一行的等待这句没抄上,就出现了上述的奇怪现象,测试的问题找到了,目标功能的实现也指日可待了,快乐中{:lol:}

乐此不疲 发表于 2024-1-25 21:22:03

本帖最后由 乐此不疲 于 2024-1-25 21:23 编辑

问题解决了,是测试的例程代码没抄全,少了最后一句的等待初始化完成语句,导致RTC初始化不完全,加上这句就一切正常了,也请用到这些的新手注重这个问题!


    X32KCR = 0x80 + 0x40;   //启动外部32K晶振, 低增益+0x00, 高增益+0x40.
    while (!(X32KCR & 1));//等待时钟稳定
    RTCCFG = 0x01;    //选择外部32K时钟源,触发RTC寄存器初始化


    RTCIF = 0x00;   //清中断标志
    RTCIEN = 0x08;    //中断使能, 0x80:闹钟中断, 0x40:日中断, 0x20:小时中断, 0x10:分钟中断, 0x08:秒中断, 0x04:1/2秒中断, 0x02:1/8秒中断, 0x01:1/32秒中断
    RTCCR = 0x01;   //RTC使能


   while(RTCCFG & 0x01);        //等待初始化完成,需要在 "RTC使能" 之后判断.

页: [1]
查看完整版本: 请教RTC中断能否唤醒主时钟停振/省电模式?【已解决】