wjhhhhh 发表于 2024-9-7 22:27:56

请教 RTC闹钟到点能触发中断 不能退出掉电休眠

本帖最后由 wjhhhhh 于 2024-9-8 09:59 编辑

STC32G12K128 设置的闹钟,到点能触发RTC中断,不能退出掉电休眠,而外部中断0(按下连接P32按键接地)能退出掉电休眠,串口1接收到数据(RXT有低电平)也能退出掉电休眠 。   进入休眠的PCON=0x02或者DP=1 必须设置二次,否则不能休眠。 哪里没弄好?请各位指教。谢谢


#include "STC32G.h"
#include "stdio.h"
#include "intrins.h"

typedef   unsigned char   u8;
typedef   unsigned int    u16;
typedef   unsigned long   u32;
/****************************** 用户定义宏 ***********************************/
#define MAIN_Fosc   22118400L   //定义主时钟
#define Baudrate      19200L
#define TM            (65536 -(MAIN_Fosc/Baudrate/4))
/**********************************/
bit B_1s;
bit B_Alarm;      //闹钟标志
bit busy;         //串口忙,
bit huan_xing;    //唤醒
bit q_t=1;


/*****Uart1Init********************************/
void Uart1Init(void)                //19200bps@22.1184MHz
{ SCON = 0x50;                //8位数据,可变波特率
      AUXR |= 0x01;                //串口1选择定时器2为波特率发生器
      AUXR |= 0x04;                //定时器时钟1T模式
      T2L = 0xE0;                        //设置定时初始值
      T2H = 0xFE;                        //设置定时初始值
      AUXR |= 0x10;                //定时器2开始计时
      ES=1;
}
/*=======发字节 ===========*/         
void Uart1Send(u8 dat)
{   while (busy);
    busy = 1;
    SBUF = dat;
}

/***RTC初始化***********/
void RTC_config(void)
{
    INIYEAR = 21;   //Y:2021
    INIMONTH = 12;    //M:12
    INIDAY = 31;      //D:31
    INIHOUR = 23;   //H:23
    INIMIN = 59;      //M:59
    INISEC = 58;      //S:50
    INISSEC = 0;      //S/128:0

    ALAHOUR = 0;      //闹钟小时
    ALAMIN= 0;      //闹钟分钟
    ALASEC= 15;      //闹钟秒第15秒闹钟时间到
    // 第15秒闹钟时间到
    X32KCR = 0x80 + 0x40;   //启动外部32K晶振, 低增益+0x00, 高增益+0x40.
    while (!(X32KCR & 1));//等待时钟稳定
    RTCCFG = 0x01;    //选择外部32K时钟源,触发RTC寄存器初始化
    RTCIF = 0x00;   //清中断标志
   
          RTCIEN = 0x88;    //中断使能, 0x80:闹钟中断, 0x40:日中断, 0x20:小时中断, 0x10:分钟中断, 0x08:秒中断, 0x04:1/2秒中断, 0x02:1/8秒中断, 0x01:1/32秒中断
    RTCCR = 0x01;   //RTC使能   
    //RTCCFG |= 0x01;   //触发RTC寄存器初始化---20240513PDF910/875页
    while(RTCCFG & 0x01);      //等待初始化完成,需要在 "RTC使能" 之后判断.
}
/*=======延时函数大约1mS===========*/
voiddelay_ms(u16 ms)
{ u16 i;
      do
         {i = MAIN_Fosc / 6000;
                while(--i)      ;
   }while(--ms);
}



//掉电休眠前设置I/O口
voidS_sleep(void)
{                           Uart1Send(0x8C);Uart1Send(0x8C);
                                 delay_ms(10);
       P0M1 = 0x00;   P0M0 = 0x00;
                         P1M1 = 0x00;   P1M0 = 0x00;
                         P2M1 = 0x00;   P2M0 = 0x00;
                         P3M1 = 0x00;   P3M0 = 0x00;
                         P4M1 = 0x00;   P4M0 = 0x00;
                         P5M1 = 0x00;   P5M0 = 0x00;
                         P6M1 = 0x00;   P6M0 = 0x00;
                         P7M1 = 0x00;   P7M0 = 0x00;                        
                         P0=0xFF;P1=0xFF;P2=0xFF;P3=0xFF;
                         P4=0xFF;P5=0xFF;P6=0xFF;P7=0xFF;      
                         //      基本成功全部IO口双向 8.4 mA 掉电1.85uA
                         //2024.9.4 VCC=4V 全部IO口高阻 8.26mA 掉电34uA
               //-----------------------
                         //P0=0x00;P1=0x00;P2=0x00;P3=0x00; //不能退出掉电?
                         //P4=0x00;P5=0x00;P6=0x00;P7=0x00;      
                         //                全部IO口双向 8.4 mA 掉电2.0xuA
                         //2024.9.4 VCC=4V 全部IO口高阻 8.26mA 掉电37uA
                         P0IE = 0x00;//关闭所有I/0口的数字通道
                         P1IE = 0x00;
                         P2IE = 0x00;
                         //P3IE = 0x00;      
       P3IE |= 0x84;//P3数字通道需要唤醒脚P32(INT0调试用)?
                         P4IE = 0x00;
                         P5IE = 0x00;
                         P6IE = 0x00;
                         P7IE = 0x00;         
                  //PD=1;//掉电休眠 PD=1或PCON=0x02都可以,都必须两次 !?
                        //PD=1;//2024.9.6w这里必须两次!?前后都加多个nop都不行
                         PCON=0x02;
                         PCON=0x02;
}
/***不能漏掉汇编那一段!!********************************/
void main(void)
{   WTST = 0;//设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    EAXFR = 1; //扩展寄存器(XFR)访问使能
    CKCON = 0; //提高访问XRAM速度

    P0M1 = 0x00;   P0M0 = 0x00;//设置为准双向口
    P1M1 = 0x00;   P1M0 = 0x00;
    P2M1 = 0x00;   P2M0 = 0x00;
    P3M1 = 0x00;   P3M0 = 0x00;
    P4M1 = 0x00;   P4M0 = 0x00;
    P5M1 = 0x00;   P5M0 = 0x00;
    P6M1 = 0x00;   P6M0 = 0x00;
    P7M1 = 0x00;   P7M0 = 0x00;   

          Uart1Init();
    RTC_config();
                IT0=1;   //IT0下降沿中断
                EX0=1;   //使能IT0 中断
                P27=0;   // 标记
                P21=0;
    EA = 1;   //打开总中断
                Uart1Send(0x1A);Uart1Send(0x2A);Uart1Send(0x3A);Uart1Send(0x4A);
    while(1)
    {
               if(huan_xing==1)      
                  {P0M1 = 0x00;   P0M0 = 0x00;
                         P1M1 = 0x00;   P1M0 = 0x00;
                         P2M1 = 0x00;   P2M0 = 0x00;
                         P3M1 = 0x00;   P3M0 = 0x00;
                         P4M1 = 0x00;   P4M0 = 0x00;
                         P5M1 = 0x00;   P5M0 = 0x00;
                         P6M1 = 0x00;   P6M0 = 0x00;
                         P7M1 = 0x00;   P7M0 = 0x00;
                        P0IE = 0xFF;//使能所有I/0口的数字通道
      P1IE = 0xFF;
      P2IE = 0xFF;
      P3IE = 0xFF;
      P4IE = 0xFF;
      P5IE = 0xFF;
      P6IE = 0xFF;
      P7IE = 0xFF;         
                        }   
   if(B_1s)
      {B_1s = 0;
                            Uart1Send(0xBB);Uart1Send(0xBB);
                           Uart1Send(YEAR);Uart1Send(MONTH);Uart1Send(DAY);
                            Uart1Send(HOUR);Uart1Send(MIN);Uart1Send(SEC);
      if(q_t==1){P20=0;P27=1;}
                  else      {P20=1;P27=0;}
                              if(SEC==8) //第八秒开始掉电休眠
                                 {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();      
                           
                                        S_sleep();
                                 
                                        _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();      
         }
                        }
               if(B_Alarm)
      {B_Alarm = 0;
            Uart1Send(0xAA);Uart1Send(0xAA);Uart1Send(0xAA);Uart1Send(0xAA);
      }
               if(P35==0)//按下 P35键 进入掉电休眠
               {huan_xing=0;
                                 Uart1Send(0x1C);Uart1Send(0x1C);
                                 delay_ms(10);
                        S_sleep();
   }
    }
}
/***P32 外部中断0   中断退出掉电 ****interrupt 0************************************ */
void EX_0_interr() interrupt 0
{huan_xing=1;
      
}

/******************** RTC中断函数 *********************/
void RTC_Isr() interrupt 13
{
      if(RTCIF & 0x80)    //闹钟中断    休眠开源 播放立体声音乐
      {
                RTCIF &= ~0x80;
                B_Alarm = 1;
}
      if(RTCIF & 0x08)    //秒中断
      {
                RTCIF &= ~0x08;
                B_1s = 1;
      }
}
/*******interrupt 4*********************************** */
void Uart1Isr() interrupt 4
{if (TI)               
    {   TI = 0;            
      busy = 0;
    }
   if (RI)
    {RI = 0;
                        huan_xing=1; //只要有中断发生就退出掉电?
    }
}



布丁橘长 发表于 2024-9-9 03:36:46


首先休眠语句只需要写一次,写两句就是程序不对的根源

然后代码有两处小问题,这么写感觉也没错,但逻辑上感觉有点不对
第一处,X32KCR=0xc0是启动外部32K晶振,
等待外部晶振稳定后,让RTC选择外部晶振,需要RTCCFG 的B1位清零(RTCCFG &= ~0x02 ) 但这个时候不需要初始化RTC(不需要RTCCFG = 0x01),应该在 "RTC使能" 之后,再等待初始化完成
第二处,就是RTCCFG的B0位置1(RTCCFG = 0x01),初始化RTC,写入年月日等信息,在RTC使能语句后,再初始化感觉会更合理



代码整体没什么问题,可能你对程序效果有什么误解,下面分析下代码效果:
1、进入主函数后,各种初始化,串口打印:1A 2A 3A 4A,然后进入while(1)循环



2、每1秒RTC中断一次,串口打印 BB BB 年 月 日 时 分 秒




3、if(SEC == 8)的意思是:秒到了每分钟第8秒的时候,即每1分钟进一次if,不是每8秒
所以BB BB 年 月 日...串口会打印60次,第一次是8秒,后面是60秒休眠一次

4、if(B_Alarm)不是每15秒中断一次,是每天 00:00:15,即凌晨0点0分15秒,闹钟中断一次,
所以串口打印一天,只会看到一次AA AA AA AA




5、串口打印看到的8C 8C就是进入休眠时刻打印的数据,但RTC每1秒唤醒一次,感觉就完全没有进休眠


6、按P35进入休眠,休眠前打印1C 1C ,1秒后RTC唤醒,继续打印BB BB 年 月 日....



测试代码:

llyymm 发表于 2024-9-9 08:34:14

还是逻辑关系不清晰严谨造成的,我也跟着学习了一下{:4_245:}

soma 发表于 2024-9-9 08:41:49

这个不错,如果要精确还是要外部晶振。

wjhhhhh 发表于 2024-9-9 17:24:27

本帖最后由 wjhhhhh 于 2024-9-9 17:27 编辑

感谢“布丁局长”耐心细致解答指教。
下载附件再试 还有不解:
1.PCON=0x02语句只写一次仍然不能进入休眠。
2.不启用RTC秒中断, 设置在00时00分08秒进入休眠设置闹钟00时00分15秒触发中断退出休眠,实际运行08秒能进入休眠15秒不能退出; 在到达15秒前、后按P32外部触发或串口触发都能退出休眠。
   使用"屠龙刀"核心板, STC32G12K128芯片, 去掉P20~P26发光管; USB--CH340转TTL串口下载/通讯
      还有哪里没弄对?请指教。谢谢
页: [1]
查看完整版本: 请教 RTC闹钟到点能触发中断 不能退出掉电休眠