最近在用stc32g12k128单片机做一款手表,在阅读芯片手册时发现这款芯片拥有rtc实时时钟的功能,所以就直接拿来用了。
首先,让我们先来看看这款芯片的rtc实时时钟有哪些功能:
同样的,在这里我们也是使用STC32G的库函数,先将STC32G_RTC.c添加到工程文件中,然后新建一个文件存放rtc的相关操作函数,我写的函数如下:
u8 datetime[6]={0,0,0,10,25,0};
//========================================================================
// 函数: RTC_init
// 描述: 用户初始化程序.
// 参数: None.
// 返回: None.
// 版本: V1.0, 2020-09-25
//========================================================================
void RTC_init(void)
{
RTC_InitTypeDef RTC_InitStructure;
RTC_InitStructure.RTC_Clock = RTC_IRC32KCR;//RTC 时钟, RTC_IRC32KCR, RTC_X32KCR
RTC_InitStructure.RTC_Enable = ENABLE; //I2C功能使能, ENABLE, DISABLE
RTC_InitStructure.RTC_Year = 22; //RTC 年, 00~99, 对应2000~2099年
RTC_InitStructure.RTC_Month = 9; //RTC 月, 01~12
RTC_InitStructure.RTC_Day = 23; //RTC 日, 01~31
RTC_InitStructure.RTC_Hour = 22; //RTC 时, 00~23
RTC_InitStructure.RTC_Min = 50; //RTC 分, 00~59
RTC_InitStructure.RTC_Sec = 55; //RTC 秒, 00~59
RTC_InitStructure.RTC_Ssec = 00; //RTC 1/128秒, 00~127
RTC_InitStructure.RTC_ALAHour= 00; //RTC 闹钟时, 00~23
RTC_InitStructure.RTC_ALAMin = 00; //RTC 闹钟分, 00~59
RTC_InitStructure.RTC_ALASec = 00; //RTC 闹钟秒, 00~59
RTC_InitStructure.RTC_ALASsec= 00; //RTC 闹钟1/128秒, 00~127
RTC_Inilize(&RTC_InitStructure);
// NVIC_RTC_Init(RTC_ALARM_INT|RTC_SEC_INT,Priority_0); //中断使能, RTC_ALARM_INT/RTC_DAY_INT/RTC_HOUR_INT/RTC_MIN_INT/RTC_SEC_INT/RTC_SEC2_INT/RTC_SEC8_INT/RTC_SEC32_INT/DISABLE; 优先级(低到高) Priority_0,Priority_1,Priority_2,Priority_3
}
void Get_time(u8 *datetime)
{
datetime[0]=YEAR;
datetime[1]=MONTH;
datetime[2]=DAY;
datetime[3]=HOUR;
datetime[4]=MIN;
datetime[5]=SEC;
}
void Write_RTC(u8 *new_datetime)
{
INIYEAR = new_datetime[0];
INIMONTH = new_datetime[1];
INIDAY = new_datetime[2];
INIHOUR = new_datetime[3]; //修改时分秒
INIMIN = new_datetime[4];
INISEC = new_datetime[5];
INISSEC = 0;
RTCCFG |= 0x01; //触发RTC寄存器初始化
}
void Show_time(void)
{
u8 show[4]={1,0,2,5};
Get_time(datetime);
show[0]=datetime[3]/10;
show[1]=datetime[3]-show[0]*10;
show[2]=datetime[4]/10;
show[3]=datetime[4]-show[2]*10;
OLED_ShowChar(24,2,show[0],32);
OLED_ShowChar(40,2,show[1],32);
OLED_ShowChar(56,2,10,32);
OLED_ShowChar(72,2,show[2],32);
OLED_ShowChar(88,2,show[3],32);
}
其中里面的YEAR,MONTH,DAY等是单片机的寄存器,可以直接读取;INIYEAR,INIMONTH,INIDAY等也是单片机的寄存器,不过是初始化rtc时钟用的;因为在作用过程中可能需要修改时间,所以我写了write_RTC函数,可以修改时间,输入参数为时间的数组。
最后就是一些自己在开发时的一些问题,在芯片手册时钟管理这一章提到使用内部32k时钟会误差比较大,我不清楚是用做主时钟时误差比较大,还是用做rtc时钟时误差比较大,或者说都会有误差,使用在使用时还是建议使用外部晶振,原理图也给出了:
我也有一个不能很好解决的问题,就是单片机不知道能不能同时启动两个不同频率的时钟,也就是说我在使用24Mhz为主时钟的同时,还选用32khz为rtc时钟。而我在使用rtc后,程序按照24Mhz的延时是没有错误,也就是说主时钟还是24Mhz,但是不知道这个判断方法准不准确,希望有路过的大佬答疑一下。
在最后,使用芯片内部的RTC实时时钟最大的好处就是可以节约成本了,而缺点也有,就是没有备用电源引脚,当单片机断电停止工作后时钟也会停止工作。
经过我的使用,若使用外部32.768kHz的晶振作为RTC的时钟晶振,C1和C2的大小必须严格控制在20p~47p,同时我推荐是在20p到30p,若C的电容过大,可能会导致时钟初始化慢,或者初始化失败等的问题。