神农鼎 发表于 2023-5-22 00:05:05

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

https://www.stcaimcu.com/data/attachment/forum/202308/05/102236kdoaxmanccjco9os.pngSTC32G内部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 PowerOn                   P6= ~ledNum;                                                   //输出低驱动                   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;                                                                     //中断方式读取比较器比较结果}



神农鼎 发表于 2023-5-22 00:08:16

有省电模式/主时钟停振时,实际需要省电的,则将TL431的供电由一个I/O供电,
睡眠前I/O输出低电平,就不会耗电。
唤醒后需要 ADC_VREF+ 正常工作,I/O输出高,TL431正常工作。
https://www.stcaimcu.com/data/attachment/forum/202305/21/235241xe1l1krev4rbuf1g.png

神农鼎 发表于 2023-5-22 00:09:41

有RTC功能的MCU,低功耗设计:
1,不用,浮空的I/O口,可以准双向口/弱上拉,或【高阻输入/并关闭数字输入】
2,RTC的 P1.6/P1.7接外部晶振的2个I/O, 【高阻输入/并关闭数字输入】
3,用做ADC输入的模拟I/O, 【高阻输入/并关闭数字输入】
3,用做比较器输入的模拟I/O, 【高阻输入/并关闭数字输入】
https://www.stcaimcu.com/data/attachment/forum/202305/21/205018ehhvkhzkyclcwhcc.png

https://www.stcaimcu.com/data/attachment/forum/202305/21/205018to3dc7g3lv7ue39l.png



神农鼎 发表于 2023-5-22 00:14:47


供电:
https://www.stcaimcu.com/data/attachment/forum/202305/22/001320ylc8dcmwmdqidixj.png

掉电检测,比较器输入口加个 0.01uF的电容 ?
电阻放到 1M ? 这样漏电少
https://www.stcaimcu.com/data/attachment/forum/202305/22/001320w9qwnwa62z6cs2z6.png

fcxqczzyjdxx 发表于 2023-5-22 09:15:08

神农鼎 发表于 2023-5-22 00:08
有掉电省电需要,则将TL431的供电由一个I/O供电,
睡眠前I/O输出低电平,就不会耗电。
唤醒后需要VREF,I/O ...

需要掉电,这个电路不好改。
电路是不是应该把 R16 和SYS-VCC连接用0R电阻连上,这样可以随手就能去掉用SYS-VCC供电。
还能给一个IO口用0R电阻连接到 R16,这样需要的时候,把电阻焊上就能使用IO口供电了。

电子DIY小家 发表于 2023-5-22 11:21:01

fcxqczzyjdxx 发表于 2023-5-22 09:15
需要掉电,这个电路不好改。
电路是不是应该把 R16 和SYS-VCC连接用0R电阻连上,这样可以随手就能去掉用SYS ...

不是挺好改的,这里直接把R16一端的SYS-VCC直接接到io口上去就好了,别的都不用动

fcxqczzyjdxx 发表于 2023-6-9 09:16:24

电子DIY小家 发表于 2023-5-22 11:21
不是挺好改的,这里直接把R16一端的SYS-VCC直接接到io口上去就好了,别的都不用动 ...



你说的是这样吗

老高 发表于 2023-7-15 10:13:02

本帖最后由 老高 于 2023-7-15 10:14 编辑

请教一下我用STC8H1K08T做RTC时钟,采用的就是实验箱电路。外设有4个输出口,2输入按键,比较器检测完全按照试验箱上电路做的。检测到掉电,后还有5mA电流,太高了。请问检测到掉电,是要将前面说的所有非必要的外设端口全部设为开漏,并输出1才是最低功耗吗?

国学芯用 发表于 2023-8-18 14:05:02

我这个单片机,外挂了32k晶振,外部引脚没有任何部件了,测试用RTC使用外挂32k晶振,能成功进入睡眠,但是进入睡眠的电流是14uA,电流这么高正常吗?

乘风飞扬 发表于 2023-8-18 16:14:28

本帖最后由 乘风飞扬 于 2023-8-18 16:16 编辑

国学芯用 发表于 2023-8-18 14:05
我这个单片机,外挂了32k晶振,外部引脚没有任何部件了,测试用RTC使用外挂32k晶振,能成功进入睡眠,但是进入睡 ...RTC时钟使用外部32K晶振时,需要将振荡脚P1.6, P1.7的数字通道关闭,否则进入休眠模式后会有额外的漏电流。


页: [1] 2
查看完整版本: STC32G内部RTC时钟低功耗,定时休眠唤醒,内部比较器监测外部电源