newlined 发表于 2026-3-11 10:54:10

关于掉电状态下,RTC唤醒的功耗问题。

大家好,我正在做一个东西,MCU是32G12K128,遇到到外部电源掉电后,电路板跑时钟的问题,期望电路板的外电没有后,电路板进入掉电状态,MCU由纽扣电池供电,功耗尽可能的小,仅维持MCU的RTC运行,RTC每隔1秒唤醒MCU,通过比较器检测外电,检测到外电后,MCU退出掉电状态,没有则继续进入掉电状态,RTC的纽扣供电及比较器部分参考手册的电路图,如下:

程序主要部分在“例程81-内部RTC时钟低功耗休眠唤醒-比较器检测电压程序”上修改而成:
相关的函数如下:


void      Port_Mode(void)                //外部电源正常时的端口设置 空闲口置为高阻
{ P0M0 = 0xe0; P0M1 = 0x1f;                                                                                 
P1M0 = 0x00; P1M1 = 0xfc;                                                                                 
P2M0 = 0xb9; P2M1 = 0x46;
P3M0 = 0x20; P3M1 = 0xd4;
P4M0 = 0x1e; P4M1 = 0x61;
P5M0 = 0x02; P5M1 = 0xe0;
P6M0 = 0x27; P6M1 = 0xc0;
P7M0 = 0x0e; P7M1 = 0x81;
      P0=0xE0;                                                                        //11100000;                              
      P1=0x03;                                                                        //00000011;                        
      P2=0x01;                                                                        //00000001;                              
      P3=0x0b;                                                                        //00001011;
      P4=0x80;                                                                        //10000000;
      P5=0x1F;                                                                        //00011111;
      P6=0x39;                                                                        //00111001;
      P7=0x70;                                                                        //01110000;
}

void      PD_Port_Mode(void)                        //掉电状态后端口设置 除P1.6、P1.7均设为开漏
{                                    
P0M0 = 0xff; P0M1 = 0xff;   
P1M0 = 0x3f; P1M1 = 0xff;   
P2M0 = 0xff; P2M1 = 0xff;   
P3M0 = 0xff; P3M1 = 0xff;   
P4M0 = 0xff; P4M1 = 0xff;   
P5M0 = 0xff; P5M1 = 0xff;   
P6M0 = 0xff; P6M1 = 0xff;   
P7M0 = 0xff; P7M1 = 0xff;   
                                                                                                //所有端口关闭数字输入
      P0IE = 0x00;         P1IE = 0x00;                     
      P2IE = 0x00;      P3IE = 0x00;                        
      P4IE = 0x00;      P5IE = 0x00;                        
      P6IE = 0x00;      P7IE = 0x00;               
                                                                                                //所有端口初值赋为1      
      P0=0xff;      P1=0xff;                                       
      P2=0xff;      P3=0xff;                                          
      P4=0xff;      P5=0xff;                                       
      P6=0xff;      P7=0xff;                                                         
}

//========================================================================
// 函数: void RTC_config(void)
// 描述: RTC初始化函数。
// 参数: 无.
// 返回: 无.
// 版本: V1.0, 2020-6-10
//========================================================================
void RTC_config(void)                //RTC初始化
{      INIYEAR         = 26;             //Y:2026
      INIMONTH = 01;            //M:01
      INIDAY         = 01;            //D:63
      INIHOUR         = 00;             //H:15
      INIMIN         = 00;            //M:46
      INISEC         = 00;            //S:50
      INISSEC         = 00;            //S/128:0
      
      X32KCR = 0x80 + 0x40;   //启动外部32K晶振, 低增益+0x00, 高增益+0x40.
      while (!(X32KCR & 1));    //等待时钟稳定
      RTCCFG = 0x01;               //选择外部32K时钟源,触发RTC寄存器初始化

      RTCIF = 0x00;                           //清中断标志
      RTCIEN = 0x08;                            //中断使能, 0x08:秒中断,
      RTCCR = 0x01;                           //RTC使能
      while(RTCCFG & 0x01);      //等待初始化完成,需要在 "RTC使能" 之后判断.
      //设置RTC时间需要32768Hz的1个周期时间,大约30.5us. 由于同步, 所以实际等待时间是0~30.5us.
      //如果不等待设置完成就睡眠, 则RTC会由于设置没完成, 停止计数, 唤醒后才继续完成设置并继续计数.
}

/******************** RTC中断函数 *********************/
void RTC_Isr() interrupt 36
{      if(RTCIF & 0x08)                                          //秒中断
      {      RTCIF &= ~0x08;                              //清秒中断
                B_1s = 1;
                //P3M0 = 0x5f; P3M1 = 0xdf;            //P3.5准双向
               P3M0 = 0x7f; P3M1 = 0xdf;               //P3.5推挽
                _nop_();_nop_();_nop_();
                _nop_();_nop_();_nop_();
                _nop_();_nop_();_nop_();
                CMPEN = 1;                                     //使能比较器模块      
      }
}

//========================================================================
// 函数: void CMP_config(void)
// 描述: 比较器初始化函数。
// 参数: 无.
// 返回: 无.
// 版本: V1.0, 2020-6-10
//========================================================================

void CMP_config(void)                //比较器初始化函数
{ CMPEXCFG = 0x00;
CMPEXCFG |=0xc0;            //比较器DC迟滞输入选择,0xc0:30mV
CMPEXCFG |= 0x04;      //内部1.19V参考电压为CMP-输入脚
CMPEXCFG &= ~0x03;    //P3.7为CMP+输入脚
CMPCR2 = 0x00;            
INVCMPO = 0;          //比较器正向输出
DISFLT = 0;             //使能0.1us滤波
CMPCR2 |= 0x10;      //比较器结果经过16个去抖时钟后输出
CMPCR1 = 0x00;      
CMPIF = 0;            //清中断标志
                                                                                                
PIE = 1;                //开比较器上升沿中断
NIE = 1;               //开比较器下降沿中断
CMPOE = 0;            //禁止比较器输出
CMPO_S = 0;         //选择P3.4作为比较器输出脚
CMPEN = 1;            //使能比较器模块
}                                 

/******************* 比较器中断函数 ********************/
void CMP_Isr() interrupt 21
{   CMPIF = 0;                  //清中断标志
    if(CMPRES)                      //有外部电源供电
    {      Port_Mode();            //退出掉电状态端口设置
    }                           
    else                              //无外部电源供电      
    {      CMPEN = 0;             //关比较器模块                        
      PD_Port_Mode();                              //掉电状态端口设置
      PD=1;                                                //进掉电状态
      _nop_();_nop_();_nop_();
      _nop_();_nop_();_nop_();
      _nop_();_nop_();_nop_();
    }
}
程序运行时,在主循环之前,执行Port_Mode();RTC_config()      ;CMP_config()。               
现在的情况是在电路板插着纽扣电池的状态下,外部电源掉电后,电路板可以进入掉电状态,掉电状态下,用万用表测纽扣的工作电流在2uA左右,符合要求,现在有2个疑问:
1、在电路板没有外部电源的情况下,插上纽扣电池,这种情况下,MCU应该马上进入掉电状态,但是貌似没有,此时测的纽扣电池的工作电流在7mA左右,只有加上外部电源,再断掉外部电源,MCU才进入掉电状态,纽扣的工作电流才降下来。
2、RTC秒中断中,唤醒MCU后,P3.5必须设置为强推挽,才可以,如果设为开漏或准双向,掉电状态下,测纽扣的工作电流在7mA左右,MCU貌似也没有进入掉电状态。
请大家看看问题出在哪里?尤其第一个问题,生产线上,调试人员有可能会在调试完电路板,断电后,统一插纽扣电池,造成MCU进不了掉电状态,放空电池,谢谢。

lcwswust 发表于 2026-3-11 15:35:46

由于在开启比较器中断前清除了标志,如果比较器输出不变,它就不再产生中断,所以如果一开始就是电池供电它也不中断,
建议初始化完成后令CMPIF =1;看能不能触发中断。
如果不想用中断,也可以在初始化之后采用查询方式,查询比较器输出再作处理。

newlined 发表于 2026-3-11 15:38:48

lcwswust 发表于 2026-3-11 15:35
由于在开启比较器中断前清除了标志,如果比较器输出不变,它就不再产生中断,所以如果一开始就是电池供电它 ...

好的,谢谢您,我试下。

newlined 发表于 2026-3-11 16:06:56

lcwswust 发表于 2026-3-11 15:35
由于在开启比较器中断前清除了标志,如果比较器输出不变,它就不再产生中断,所以如果一开始就是电池供电它 ...

我刚去试了一下,确实是这样,问题解决,非常感谢{:baoquan:}。
页: [1]
查看完整版本: 关于掉电状态下,RTC唤醒的功耗问题。