67-内部RTC时钟低功耗休眠唤醒-比较器检测电压程序,STC32G144K246实验箱演示程序
67-内部RTC时钟低功耗休眠唤醒-比较器检测电压程序,STC32G144K246实验箱演示程序主程序main.C代码如下(汇编版本在附件中):
/*---------------------------------------------------------------------*/
/* --- Web: www.STCAI.com ---------------------------------------------*/
/* --- BBS: www.STCAIMCU.com-----------------------------------------*/
/*---------------------------------------------------------------------*/
/*************本程序功能说明**************
本例程基于STC32G144K246为主控芯片的实验箱进行编写测试。
使用Keil C251编译器,Memory Model推荐设置XSmall模式,默认定义变量在edata,单时钟存取访问速度快。
edata建议保留1K给堆栈使用,空间不够时可将大数组、不常用变量加xdata关键字定义到xdata空间。
读写芯片内部集成的RTC模块.
电路连接参考规格书RTC章节-RTC实战线路图.
用RTC定时唤醒MCU,如1秒唤醒1次,唤醒后用比较器判断外部电压:1,正常,正常工作;2,如电压偏低,继续休眠,主时钟停止震荡,RTC继续工作.
比较器正极通过可调电阻分压后输入到P5.0口,比较器负极使用内部1.19V参考电压.
该分压电路的地用I/O(P3.5)控制,I/O设置为开漏,不比较时,对外设置为1,I/O口浮空,省电;比较时,对外输出0,就是地!
下载时, 选择时钟 48MHz (用户可自行修改频率).
******************************************/
#include "..\comm\STC32G144K246.h"
typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;
/****************用户定义宏****************/
#define MAIN_Fosc 48000000UL
#define PrintUart 1 //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; //闹钟标志
u8ledIndex;
/****************本地函数声明**************/
void RTC_config(void);
void CMP_config(void);
void Ext_Vcc_Det(void);
void UartInit(void);
/**********************************************/
void main(void)
{
EAXFR = 1; //扩展寄存器(XFR)访问使能
CKCON = 0; //提高访问XRAM速度
P0M1 = 0x00; P0M0 = 0xff; //设置为推挽输出
P3M1 = 0x20; P3M0 = 0xa2; //设置P3.7,P3.1为推挽输出,P3.5为开漏
P4M1 = 0x00; P4M0 = 0xc2; //设置P4.7,P4.6,P4.1为推挽输出
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",RTCYEAR,RTCMONTH,RTCDAY,RTCHOUR,RTCMIN,RTCSEC);
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,做比较电路的地线
CMP1_6P6N_CR1 |= 0x80;//使能比较器1模块
NOP20();
if(CMP1_6P6N_CR1 & 0x01) //判断是否CMP+电平高于CMP-,外部电源连接
{
P41 = 0; //LED Power On
P0 = ~ledNum; //输出低驱动
ledIndex++;
if(ledIndex > 7)
{
ledIndex = 0;
}
}
else
{
CMP1_6P6N_CR1 &= ~0x80; //关闭比较器1模块
P35 = 1; //不比较时,对外设置为1,I/O口浮空,省电
P41 = 1; //LED Power Off
_nop_();
_nop_();
PCON = 0x02;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
}
//========================================================================
// 函数: void CMP_config(void)
// 描述: 比较器初始化函数。
// 参数: 无.
// 返回: 无.
// 版本: V1.0, 2025-12-26
//========================================================================
void CMP_config(void)
{
CMP1_6P6N_CR1 &= ~0x20; //禁止比较器上升沿中断
//CMP1_6P6N_CR1 |= 0x20; //使能比较器上升沿中断
CMP1_6P6N_CR1 &= ~0x10; //禁止比较器下降沿中断
//CMP1_6P6N_CR1 |= 0x10; //使能比较器下降沿中断
CMP1_6P6N_CR1 &= ~0x0c; //比较器中断最低优先级
//CMP1_6P6N_CR1 |= 0x04; //比较器中断较低优先级
//CMP1_6P6N_CR1 |= 0x08; //比较器中断较高优先级
//CMP1_6P6N_CR1 |= 0x0c; //比较器中断最高优先级
//CMP1_6P6N_CR1 &= ~0x02; //禁止比较结果输出
CMP1_6P6N_CR1 |= 0x02; //使能比较结果输出
CMP1_6P6N_CR2 &= ~0x80; //比较器结果正向输出
//CMP1_6P6N_CR2 |= 0x80; //比较器结果反向输出
//CMP1_6P6N_CR2 &= ~0x40; //关闭0.1us模拟滤波功能
CMP1_6P6N_CR2 |= 0x40; //使能0.1us模拟滤波功能
CMP1_6P6N_CR2 &= ~0x3f; //关闭数字滤波
CMP1_6P6N_CR2 |= 0x10; //使能(n+2)个系统时钟数字滤波
CMP1_6P6N_CR3 &= ~0xc0;
//CMP1_6P6N_CR3 |= 0x40; //比较器DC迟滞输入选择,0:0mV; 0x40:10mV; 0x80:20mV; 0xc0:30mV
CMP1_6P6N_CR3 &= ~0x3f; //CMP1+: P3.7, CMP1-: P3.6
CMP1_6P6N_CR3 |= 0x01; //CMP1+: P5.0
//CMP1_6P6N_CR3 |= 0x02; //CMP1+: OP1O
//CMP1_6P6N_CR3 |= 0x03; //CMP1+: ADCIN
//CMP1_6P6N_CR3 |= 0x04; //CMP1+: DAC1O
//CMP1_6P6N_CR3 |= 0x05; //CMP1+: DAC2O
//CMP1_6P6N_CR3 |= 0x08; //CMP1-: P5.1
//CMP1_6P6N_CR3 |= 0x10; //CMP1-: OP2O
CMP1_6P6N_CR3 |= 0x18; //CMP1-: BGV(1.19V)
//CMP1_6P6N_CR3 |= 0x20; //CMP1-: DAC1O
//CMP1_6P6N_CR3 |= 0x28; //CMP1-: DAC2O
CMP1_6P6N_CR4 &= ~0x03; //CMP1O: P3.4
//CMP1_6P6N_CR4 |= 0x01; //CMP1O: P4.1
CMP1_6P6N_CR1 &= ~0x80; //关闭比较器1模块
//CMP1_6P6N_CR1 |= 0x80; //使能比较器1模块
}
//========================================================================
// 函数: void RTC_config(void)
// 描述: RTC初始化函数。
// 参数: 无.
// 返回: 无.
// 版本: V1.0, 2022-10-10
//========================================================================
void RTC_config(void)
{
INIYEAR = 25; //Y:2025
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 RTC_VECTOR
{
if(RTCIF & 0x80) //闹钟中断
{
// P01 = !P01;
RTCIF &= ~0x80;
B_Alarm = 1;
}
if(RTCIF & 0x08) //秒中断
{
// P00 = !P00;
RTCIF &= ~0x08;
B_1s = 1;
}
}
/*****************************************************************************/
//如果开启了比较器中断就需要编写对应的中断函数
void CMP_Isr() interrupt CMP_VECTOR
{
CMP1_6P6N_CR1 &= ~0x40; //清除CMP1IF中断标志
P47 = (CMP1_6P6N_CR1 & 0x01); //中断方式读取比较器比较结果
}
/******************** 串口打印函数 ********************/
void UartInit(void)
{
#if(PrintUart == 1)
S1_S1 = 0; //UART1 switch to, 00: P3.0 P3.1, 01: P3.6 P3.7, 10: P1.6 P1.7, 11: P4.3 P4.4
S1_S0 = 0;
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 = 0; //UART2 switch to: 0: P1.0 P1.1,1: P4.6 P4.7
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;
}
页:
[1]