- 打卡等级:常住居民II
- 打卡总天数:80
- 最近打卡:2026-07-23 09:36:34
已绑定手机
版主
- 积分
- 1081
|
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; //中断方式读取比较器比较结果
}
|
|