找回密码
 立即注册
查看: 47|回复: 0

81-内部RTC时钟低功耗休眠唤醒-比较器检测电压程序,STC32G12K128实验箱演示程序,STC3

[复制链接]
  • 打卡等级:常住居民II
  • 打卡总天数:80
  • 最近打卡:2026-07-23 09:36:34
已绑定手机

231

主题

172

回帖

1081

积分

版主

积分
1081
发表于 2026-6-27 11:54:19 | 显示全部楼层 |阅读模式
81-内部RTC时钟低功耗休眠唤醒-比较器检测电压程序,STC32G12K128实验箱演示程序,STC32G8K64,STC32CL8K64
主程序main.C代码如下(汇编版本在附件中):


/*---------------------------------------------------------------------*/
/* --- Web: www.STCAI.com ---------------------------------------------*/
/* --- BBS: www.STCAIMCU.com  -----------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序            */
/*---------------------------------------------------------------------*/


/*************  本程序功能说明  **************

本例程基于STC32G为主控芯片的实验箱进行编写测试。

使用Keil C251编译器,Memory Model推荐设置XSmall模式,默认定义变量在edata,单时钟存取访问速度快。

edata建议保留1K给堆栈使用,空间不够时可将大数组、不常用变量加xdata关键字定义到xdata空间。

读写芯片内部集成的RTC模块.

电路连接参考规格书RTC章节-RTC实战线路图.

用RTC定时唤醒MCU,如1秒唤醒1次,唤醒后用比较器判断外部电压:1,正常,正常工作;2,如电压偏低,继续休眠,主时钟停止震荡,RTC继续工作.

比较器正极通过可调电阻分压后输入到P3.7口,比较器负极使用内部1.19V参考电压.

该分压电路的地用I/O(P3.5)控制,I/O设置为开漏,不比较时,对外设置为1,I/O口浮空,省电;比较时,对外输出0,就是地!

下载时, 选择时钟 24MHZ (用户可自行修改频率).

******************************************/

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

typedef     unsigned char   u8;
typedef     unsigned int    u16;
typedef     unsigned long   u32;

/****************************** 用户定义宏 ***********************************/

#define MAIN_Fosc     24000000L   //定义主时钟
#define PrintUart     2        //1:printf 使用 UART1; 2:printf 使用 UART2
#define Baudrate      115200L
#define TM            (65536 -(MAIN_Fosc/Baudrate/4))

/*****************************************************************************/


/*************  本地常量声明    **************/

u8 code ledNum[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};

/*************  本地变量声明    **************/

bit B_1s;
bit B_Alarm;        //闹钟标志
u8  ledIndex;

/*************  本地函数声明    **************/

void RTC_config(void);
void CMP_config(void);
void Ext_Vcc_Det(void);

/******************** 串口打印函数 ********************/
void UartInit(void)
{
#if(PrintUart == 1)
        SCON = (SCON & 0x3f) | 0x40;
        T1x12 = 1;          //定时器时钟1T模式
        S1BRT = 0;          //串口1选择定时器1为波特率发生器
        TL1  = TM;
        TH1  = TM>>8;
        TR1 = 1;                                //定时器1开始计时

//        SCON = (SCON & 0x3f) | 0x40;
//        T2L  = TM;
//        T2H  = TM>>8;
//        AUXR |= 0x15;   //串口1选择定时器2为波特率发生器
#else
        S2_S = 1;       //UART2 switch to: 0: P1.0 P1.1,  1: P4.6 P4.7
    S2CFG |= 0x01;  //使用串口2时,W1位必需设置为1,否则可能会产生不可预期的错误
        S2CON = (SCON & 0x3f) | 0x40;
        T2L  = TM;
        T2H  = TM>>8;
        AUXR |= 0x14;              //定时器2时钟1T模式,开始计时
#endif
}

void UartPutc(unsigned char dat)
{
#if(PrintUart == 1)
        SBUF = dat;
        while(TI == 0);
        TI = 0;
#else
        S2BUF  = dat;
        while(S2TI == 0);
        S2TI = 0;    //Clear Tx flag
#endif
}

char putchar(char c)
{
        UartPutc(c);
        return c;
}

/**********************************************/
void main(void)
{
    WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
    EAXFR = 1; //扩展寄存器(XFR)访问使能
    CKCON = 0; //提高访问XRAM速度

    P0M1 = 0x30;   P0M0 = 0x30;   //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P1M1 = 0x32;   P1M0 = 0x32;   //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
    P2M1 = 0x3c;   P2M0 = 0x3c;   //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P3M1 = 0xf0;   P3M0 = 0x70;   //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V), P3.5设置开漏输出, P3.7设置高阻输入
    P4M1 = 0x3c;   P4M0 = 0x3c;   //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
    P5M1 = 0x0c;   P5M0 = 0x0c;   //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
    P6M1 = 0xff;   P6M0 = 0xff;   //设置为漏极开路(实验箱加了上拉电阻到3.3V)
    P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口

    UartInit();
    CMP_config();
    RTC_config();
    EA = 1;     //打开总中断
   
    while(1)
    {
        if(B_1s)
        {
            B_1s = 0;
            printf("Year=20%d,Month=%d,Day=%d,Hour=%d,Minute=%d,Second=%d\r\n",YEAR,MONTH,DAY,HOUR,MIN,SEC);

            Ext_Vcc_Det();  //每秒钟检测一次外部电源,如果外部电源连接则工作,外部电源断开则进入休眠模式
        }

        if(B_Alarm)
        {
            B_Alarm = 0;
            printf("RTC Alarm!\r\n");
        }
    }
}

//========================================================================
// 函数: void Ext_Vcc_Det(void)
// 描述: 外部电源检测函数。
// 参数: 无.
// 返回: 无.
// 版本: V1.0, 2022-10-10
//========================================================================
void Ext_Vcc_Det(void)
{
    P35 = 0;        //比较时,对外输出0,做比较电路的地线
    CMPEN = 1;     //使能比较器模块
    _nop_();
    _nop_();
    _nop_();
    if(CMPRES)     //判断是否CMP+电平高于CMP-,外部电源连接
    {
        P40 = 0;                //LED Power On
        P6 = ~ledNum[ledIndex];        //输出低驱动
        ledIndex++;
        if(ledIndex > 7)
        {
            ledIndex = 0;
        }
    }
    else
    {
        CMPEN = 0;      //关闭比较器模块
        P35 = 1;        //不比较时,对外设置为1,I/O口浮空,省电
        P40 = 1;                //LED Power Off
        _nop_();
        _nop_();
        PCON = 0x02;  //STC32G 芯片使用内部32K时钟,休眠无法唤醒
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
    }
}

//========================================================================
// 函数: void CMP_config(void)
// 描述: 比较器初始化函数。
// 参数: 无.
// 返回: 无.
// 版本: V1.0, 2022-10-10
//========================================================================
void CMP_config(void)
{
    CMPEXCFG = 0x00;
//  CMPEXCFG |= 0x40;                           //比较器DC迟滞输入选择,0:0mV; 0x40:10mV; 0x80:20mV; 0xc0:30mV

//  CMPEXCFG &= ~0x04;                          //P3.6为CMP-输入脚
    CMPEXCFG |= 0x04;                           //内部1.19V参考电压为CMP-输入脚

    CMPEXCFG &= ~0x03;                          //P3.7为CMP+输入脚
//  CMPEXCFG |= 0x01;                           //P5.0为CMP+输入脚
//  CMPEXCFG |= 0x02;                           //P5.1为CMP+输入脚
//  CMPEXCFG |= 0x03;                           //ADC输入脚为CMP+输入脚


    CMPCR2 = 0x00;
    INVCMPO = 0;                                //比较器正向输出
//  INVCMPO = 1;                                //比较器反向输出
    DISFLT = 0;                                 //使能0.1us滤波
//  DISFLT = 1;                                 //禁止0.1us滤波
    CMPCR2 &= ~0x3f;                            //比较器结果直接输出
//  CMPCR2 |= 0x10;                             //比较器结果经过16个去抖时钟后输出

    CMPCR1 = 0x00;
    PIE = 0;                                    //禁止比较器上升沿中断
//  PIE = 1;                                    //使能比较器上升沿中断
    NIE = 0;                                    //禁止比较器下降沿中断
//  NIE = 1;                                    //使能比较器下降沿中断

    CMPOE = 0;                                  //禁止比较器输出
//  CMPOE = 1;                                  //使能比较器输出

    CMPO_S = 0;                                 //选择P3.4作为比较器输出脚
//  CMPO_S = 1;                                 //选择P4.1作为比较器输出脚
    CMPEN = 1;                                  //使能比较器模块
}

//========================================================================
// 函数: void RTC_config(void)
// 描述: RTC初始化函数。
// 参数: 无.
// 返回: 无.
// 版本: V1.0, 2022-10-10
//========================================================================
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 = 50;      //S:50
    INISSEC = 0;      //S/128:0

    ALAHOUR = 0;        //闹钟小时
    ALAMIN  = 0;        //闹钟分钟
    ALASEC  = 0;        //闹钟秒
    ALASSEC = 0;        //闹钟1/128秒

    //STC32G 芯片使用内部32K时钟,休眠无法唤醒
//    IRC32KCR = 0x80;   //启动内部32K晶振.
//    while (!(IRC32KCR & 1));  //等待时钟稳定
//    RTCCFG = 0x03;    //选择内部32K时钟源,触发RTC寄存器初始化

    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使能

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

/******************** RTC中断函数 *********************/
void RTC_Isr() interrupt 13
{
        if(RTCIF & 0x80)    //闹钟中断
        {
//                P01 = !P01;
                RTCIF &= ~0x80;
                B_Alarm = 1;
        }

        if(RTCIF & 0x08)    //秒中断
        {
//                P00 = !P00;
                RTCIF &= ~0x08;
                B_1s = 1;
        }
}

/*****************************************************************************/
//如果开启了比较器中断就需要编写对应的中断函数
void CMP_Isr() interrupt 21
{
    CMPIF = 0;                        //清中断标志
//  P10 = CMPRES;                     //中断方式读取比较器比较结果
}



81-内部RTC时钟低功耗休眠唤醒-比较器检测电压程序.zip

12.94 KB, 下载次数: 3

回复

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2026-7-23 13:30 , Processed in 0.067193 second(s), 45 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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