APT32 单片机RTC功能强大, 在所有低功耗模式下均可独立运行,并支持系统唤醒。实时时钟计数器(RTC)为一个独立的 BCD 编码计数器,提供实时的日历和时间信息,包括星期,年、月、日和小时、分钟、秒。支持可编程的闹钟中断。RTC 具有产生周期性的中断事件的能力。RTC 一旦初始化成功并开始工作,任何复位信号均不能影响其工作,除非重新上电。
RTC 的基本特性:
1) 支持万年历功能,自动闰年判定。计时器包括小时、分钟、秒和微秒,BCD 格式计数。
(资料图片)
2) 二十四小时或者十二小时制可选,支持星期判断。
3) 支持多个时钟源,包括外部晶振、内部低速振荡器和内部主振荡器。
4) 支持低功耗唤醒功能
5) 两个可编程闹钟。
6) 支持周期事件触发。
RTC 的系统框图:
由于 RTC 工作时钟与 APB 总线时钟(PCLK)为异步时钟,对 RTC 的读写操作均需要通过两个异步时钟同步
后进行。任何对 RTC 控制器的操作不会立即产生作用,可以通过对 CR[UPD_BSY]控制位进行查询,以获得更新状
态。UPD_BSY 控制位在写请求发生时,会立即置位,直到更新结束后才会自动清除。在 RTC 未初始化前,对寄存
器的更新值都保存在缓冲中,所以只需要在初始化时,查询 UPD_BSY 即可。当 RTC 已经初始化完成后(RTC 已经
开始工作),任何对寄存器的修改,例如 CR 和 ALRAR,都需要查询 UPD_BSY,以保证更新成功。
对 RTC 的初始化,包括如下操作。
1) 设置保护寄存器关闭
2) 设置 TIMR、DATR、ALRAR、ALRBR
3) 设置 CCR,包括时钟选择和分频选择
4) 使能 RTC 时钟(设置 CCR[CLKEN]),等待 RTC 工作时钟稳定(通过 CCR[RTCCK_ST]控制位查询)。
5) 设置 CR 寄存器,以设置时间格式或闹钟使能等配置。同时清除 INIT 位,启动初始化。
6) 回读 INIT 状态位,确认 RTC 工作
void rtc_set_time_demo(void)
{
csi_rtc_config_t tRtcConfig;
csi_rtc_time_t tRtcTime,tRtcTimeRdbk;
uint32_t wSec = 0;
csi_pin_set_mux(PA03, PA03_OSC_XI);//设置PA0.3为SXIN,如果使用外部主晶振作为RTC时钟源,必须先对管脚进行配置
csi_pin_set_mux(PA04, PA04_OSC_XO); //设置PA0.4为SXOUT,如果使用外部主晶振作为RTC时钟源,必须先对管脚进行配置
csi_pin_set_mux(PA01,PA01_OSC_SXI); //设置PA0.1为XIN,如果使用外部副晶振作为RTC时钟源,必须先对管脚进行配置
csi_pin_set_mux(PA02,PA02_OSC_SXO); //设置PA0.2为XOUT,如果使用外部副晶振作为RTC时钟源,必须先对管脚进行配置
tRtcConfig.byClkSrc = RTC_CLKSRC_ESOSC;//外部副晶振作为RTC时钟源
tRtcConfig.byFmt = RTC_24FMT;//选择时间模式
csi_rtc_init(RTC, &tRtcConfig);//初始化设置
tRtcTime.iYear = 22;
tRtcTime.iMon = 2;
tRtcTime.iMday = 14;
//tRtcTime.iWday = 1; //星期1-7
tRtcTime.iPm = RTC_AM;// AM or PM
tRtcTime.iHour = 9;//如果是12小时制,回读到的hour范围为1->12;如果是24小时制,回读到的hour范围是0->23
tRtcTime.iHour = 9;//如果是12小时制,回读到的hour范围为1->12;如果是24小时制,回读到的hour范围是0->23
tRtcTime.iMin = 50;
tRtcTime.iSec = 59;
csi_rtc_set_time(RTC, &tRtcTime);//设置时间
csi_rtc_start(RTC);//RTC开始计时
csi_rtc_change_fmt(RTC, RTC_12FMT);//修改时间模式为12小时制
tRtcTime.iYear = 22;
tRtcTime.iMon = 2;
tRtcTime.iMday = 14;
//tRtcTime.iWday = 1; //星期1-7
tRtcTime.iPm = RTC_AM;// AM or PM
tRtcTime.iHour = 11;
tRtcTime.iHour = 9;
tRtcTime.iMin = 59;
tRtcTime.iSec = 56;
csi_rtc_set_time(RTC, &tRtcTime);//修改时间以后需要重新start rtc
csi_rtc_start(RTC);
csi_rtc_get_time(RTC, &tRtcTimeRdbk);//回读当前时间
my_printf("12FMT: %d:%d:%d\n", tRtcTimeRdbk.iHour, tRtcTimeRdbk.iMin, tRtcTimeRdbk.iSec);
csi_rtc_change_fmt(RTC, RTC_24FMT);//修改时间模式为24小时制
csi_rtc_get_time(RTC, &tRtcTimeRdbk);//回读当前时间
my_printf("24FMT: %d:%d:%d\n", tRtcTimeRdbk.iHour, tRtcTimeRdbk.iMin, tRtcTimeRdbk.iSec);
csi_rtc_change_fmt(RTC, RTC_12FMT);//修改时间模式为12小时制
while(1)
{
csi_rtc_get_time(RTC, &tRtcTimeRdbk);
if(wSec != tRtcTimeRdbk.iSec )
{
wSec = tRtcTimeRdbk.iSec;
my_printf("%d:%d:%d pm= %d\n", tRtcTimeRdbk.iHour, tRtcTimeRdbk.iMin, tRtcTimeRdbk.iSec, tRtcTimeRdbk.iPm);
}
}
}
经过2小时测试,RTC精度稳定可好