这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » STC32G内部RTC时钟低功耗,定时休眠唤醒,内部比较器监测外部电源

共4条 1/1 1 跳转至

STC32G内部RTC时钟低功耗,定时休眠唤醒,内部比较器监测外部电源

菜鸟
2023-05-31 08:44:42     打赏

STC32G内部RTC时钟低功耗,定时休眠唤醒,内部比较器监测外部电源
===RTC定时唤醒-比较器检测外部电压,正常恢复正常工作
===RTC定时唤醒-比较器检测外部电压,偏低继续主时钟停振,省电休眠

 /************* 本程序功能说明 **************
本例程基于STC8H8K64U为主控芯片的实验箱9进行编写测试,STC8H系列带RTC模块的芯片可通用参考.
读写芯片内部集成的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 "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;
         AUXR|= 0x40;                                                                             //定时器时钟1T模式
         AUXR&= 0xFE;                                                                          //串口1选择定时器1为波特率发生器
         TL1= TM;
         TH1= TM>>8;
         TR1= 1;                                                                                        //定时器1开始计时
//       SCON = (SCON & 0x3f) | 0x40;
//       T2L = TM;
//       T2H = TM>>8;
//       AUXR |= 0x15;                                                                              //串口1选择定时器2为波特率发生器
#else
         P_SW2|= 1;                                                                                 //UART2    switch to: 0: P1.0 P1.1, 1: P4.6 P4.7
         S2CON&= ~(1<<7);                                                                    //8位数据, 1位起始位, 1位停止位, 无校验
         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((S2CON& 2) == 0);
         S2CON&= ~2;                                                                             //Clear Tx flag
#endif
}
char putchar(char c)
{
         UartPutc(c);
         returnc;
}
/**********************************************/
void main(void)
{
         WTST= 0;
         CKCON= 0;
         EAXFR= 1;
         P0M1= 0x00;   P0M0 = 0x00;                                                 //设置为准双向口
         P1M1= 0x00;   P1M0 = 0x00;                                                 //设置为准双向口
         P2M1= 0x00;   P2M0 = 0x00;                                                 //设置为准双向口
         P3M1= 0xa0;   P3M0 = 0x20;                                                 //设置为准双向口
// P3.5设置开漏输出, P3.7设置高阻输入
         P4M1= 0x00;   P4M0 = 0x00;                                                 //设置为准双向口
         P5M1= 0x00;   P5M0 = 0x00;                                                 //设置为准双向口
         P6M1= 0x00;   P6M0 = 0x00;                                                 //设置为准双向口
         P7M1= 0x00;   P7M0 = 0x00;                                                 //设置为准双向口
         UartInit();
         CMP_config();
         RTC_config();
         EA= 1;                                                                                          //打开总中断
         while(1)
         {
                   if(B_1s)
                   {
                            B_1s= 0;
                            printf("Year=20%bd,Month=%bd,Day=%bd,Hour=%bd,Minute=%bd,Second=%bd\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,做比较电路的地线
         CMPCR1|= 0x80;                                                                        //使能比较器模块
         _nop_();
         _nop_();
         _nop_();
         if(CMPCR1& 0x01)                                                                    //判断是否CMP+电平高于CMP-,外部电源连接
         {
                   P40= 0;                                                                               //LED Power  On
                   P6= ~ledNum[ledIndex];                                                   //输出低驱动
                   ledIndex++;
                   if(ledIndex > 7)
                   {
                            ledIndex= 0;
                   }
         }
         else
         {
                  CMPCR1 &= ~0x80;                                                          //关闭比较器模块
                   P35= 1;                                                                                //不比较时,对外设置为1,I/O口浮空,省电
                   P40= 1;                                                                               //LED Power Off
                   _nop_();
                   _nop_();
                   PCON= 0x02;                                                                     //STC8H8K64U B版本芯片使用内部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;
         CMPCR2&= ~0x80;                                                                    //比较器正向输出
//       CMPCR2 |= 0x80;                                                                        //比较器反向输出
         CMPCR2&= ~0x40;                                                                    //使能0.1us滤波
//       CMPCR2 |= 0x40;                                                                        //禁止0.1us滤波
         CMPCR2&= ~0x3f;                                                                    //比较器结果直接输出
//       CMPCR2 |= 0x10;                                                                        //比较器结果经过16个去抖时钟后输出
         CMPCR1= 0x00;
//       CMPCR1 |= 0x30;                                                                        //使能比较器边沿中断
//       CMPCR1 &= ~0x20;                                                                    //禁止比较器上升沿中断
//       CMPCR1 |= 0x20;                                                                        //使能比较器上升沿中断
//       CMPCR1 &= ~0x10;                                                                    //禁止比较器下降沿中断
//       CMPCR1 |= 0x10;                                                                        //使能比较器下降沿中断
         CMPCR1&= ~0x02;                                                                    //禁止比较器输出
//       CMPCR1 |= 0x02;                                                                        //使能比较器输出
         P_SW2&= ~0x08;                                                                       //选择P3.4作为比较器输出脚
//       P_SW2 |= 0x08;                                                                            //选择P4.1作为比较器输出脚
         CMPCR1|= 0x80;                                                                        //使能比较器模块
}
//========================================================================
// 函数: 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秒
//STC8H8K64U B版本芯片使用内部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
{
         CMPCR1&= ~0x40;                                                                             //清中断标志
//       P10 = CMPCR1 & 0x01;                                                                       //中断方式读取比较器比较结果
}



关键词: STC     低功耗     RTC    

菜鸟
2023-05-31 08:50:24     打赏
2楼

有省电模式/主时钟停振时,实际需要省电的,则将TL431的供电由一个I/O供电,
睡眠前I/O输出低电平,就不会耗电。
唤醒后需要 ADC_VREF+ 正常工作,I/O输出高,TL431正常工作。

111.png


菜鸟
2023-05-31 08:51:24     打赏
3楼

有RTC功能的MCU,  低功耗设计:
1,不用,浮空的I/O口,可以准双向口/弱上拉,或【高阻输入/并关闭数字输入】
2,RTC的 P1.6/P1.7接外部晶振的2个I/O, 【高阻输入/并关闭数字输入】
3,  用做ADC输入的模拟I/O, 【高阻输入/并关闭数字输入】

3,  用做比较器输入的模拟I/O, 【高阻输入/并关闭数字输入】




菜鸟
2023-05-31 08:52:25     打赏
4楼

供电:

444.png掉电检测,比较器输入口加个 0.01uF的电容 ?
电阻放到 1M ? 这样漏电少

555.png


共4条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]