找回密码
 立即注册
查看: 777|回复: 4

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

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:457
  • 最近打卡:2025-05-03 11:39:19

15

主题

58

回帖

2107

积分

金牌会员

积分
2107
发表于 2024-9-7 22:27:56 | 显示全部楼层 |阅读模式
本帖最后由 wjhhhhh 于 2024-9-8 09:59 编辑

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

RTC0906.rar (2.49 KB, 下载次数: 54)
#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===========*/
void  delay_ms(u16 ms)
{ u16 i;
        do
         {i = MAIN_Fosc / 6000;  
                while(--i)        ;
   }while(--ms);
}



//掉电休眠前设置I/O口
void  S_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 掉电34  uA
                 //-----------------------
                         //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; //只要有中断发生就退出掉电?
    }
}



回复

使用道具 举报 送花

  • 打卡等级:常住居民I
  • 打卡总天数:68
  • 最近打卡:2024-09-14 12:02:46

11

主题

75

回帖

3568

积分

荣誉版主

积分
3568
QQ
发表于 2024-9-9 03:36:46 | 显示全部楼层

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

RTC222.jpg RTC777.jpg

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

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



3、if(SEC == 8)的意思是:秒到了每分钟第8秒的时候,即每1分钟进一次if,不是每8秒
所以BB BB 年 月 日...串口会打印60次,第一次是8秒,后面是60秒休眠一次
aaa.jpg
4、if(B_Alarm)不是每15秒中断一次,是每天 00:00:15,即凌晨0点0分15秒,闹钟中断一次,
所以串口打印一天,只会看到一次AA AA AA AA
bbbbbb.jpg

RTC444.jpg

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

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


测试代码: RTC0906.zip (44.73 KB, 下载次数: 51)

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:323
  • 最近打卡:2025-05-03 21:23:29
已绑定手机

21

主题

487

回帖

1045

积分

金牌会员

积分
1045
发表于 2024-9-9 08:34:14 | 显示全部楼层
还是逻辑关系不清晰严谨造成的,我也跟着学习了一下
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:425
  • 最近打卡:2025-05-04 00:16:27
已绑定手机

19

主题

3191

回帖

4930

积分

论坛元老

积分
4930
发表于 2024-9-9 08:41:49 来自手机 | 显示全部楼层
这个不错,如果要精确还是要外部晶振。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:457
  • 最近打卡:2025-05-03 11:39:19

15

主题

58

回帖

2107

积分

金牌会员

积分
2107
发表于 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串口下载/通讯
      还有哪里没弄对?请指教。谢谢
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-4 04:10 , Processed in 0.135973 second(s), 79 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表