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; //中断方式读取比较器比较结果}
有省电模式/主时钟停振时,实际需要省电的,则将TL431的供电由一个I/O供电,
睡眠前I/O输出低电平,就不会耗电。
唤醒后需要 ADC_VREF+ 正常工作,I/O输出高,TL431正常工作。
https://www.stcaimcu.com/data/attachment/forum/202305/21/235241xe1l1krev4rbuf1g.png
有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
供电:
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
神农鼎 发表于 2023-5-22 00:08
有掉电省电需要,则将TL431的供电由一个I/O供电,
睡眠前I/O输出低电平,就不会耗电。
唤醒后需要VREF,I/O ...
需要掉电,这个电路不好改。
电路是不是应该把 R16 和SYS-VCC连接用0R电阻连上,这样可以随手就能去掉用SYS-VCC供电。
还能给一个IO口用0R电阻连接到 R16,这样需要的时候,把电阻焊上就能使用IO口供电了。 fcxqczzyjdxx 发表于 2023-5-22 09:15
需要掉电,这个电路不好改。
电路是不是应该把 R16 和SYS-VCC连接用0R电阻连上,这样可以随手就能去掉用SYS ...
不是挺好改的,这里直接把R16一端的SYS-VCC直接接到io口上去就好了,别的都不用动 电子DIY小家 发表于 2023-5-22 11:21
不是挺好改的,这里直接把R16一端的SYS-VCC直接接到io口上去就好了,别的都不用动 ...
你说的是这样吗
本帖最后由 老高 于 2023-7-15 10:14 编辑
请教一下我用STC8H1K08T做RTC时钟,采用的就是实验箱电路。外设有4个输出口,2输入按键,比较器检测完全按照试验箱上电路做的。检测到掉电,后还有5mA电流,太高了。请问检测到掉电,是要将前面说的所有非必要的外设端口全部设为开漏,并输出1才是最低功耗吗? 我这个单片机,外挂了32k晶振,外部引脚没有任何部件了,测试用RTC使用外挂32k晶振,能成功进入睡眠,但是进入睡眠的电流是14uA,电流这么高正常吗? 本帖最后由 乘风飞扬 于 2023-8-18 16:16 编辑
国学芯用 发表于 2023-8-18 14:05
我这个单片机,外挂了32k晶振,外部引脚没有任何部件了,测试用RTC使用外挂32k晶振,能成功进入睡眠,但是进入睡 ...RTC时钟使用外部32K晶振时,需要将振荡脚P1.6, P1.7的数字通道关闭,否则进入休眠模式后会有额外的漏电流。
页:
[1]
2