#申请原创# #有奖活动#[url=home.php?mod=space&uid=760190]@21小跑堂 [/url]
CW32L052的实时时钟(RTC)
12.1 概述
实时时钟(RTC)是一个专用的计数器 / 定时器,可提供日历信息,包括小时、分钟、秒、日、月份、年份以及星期。
RTC 具有两个独立闹钟,时间、日期可组合设定,可产生闹钟中断,并通过引脚输出;支持时间戳功能,可通过
引脚触发,记录当前的日期和时间,同时产生时间戳中断;支持周期中断;支持自动唤醒功能,可产生中断并通
过引脚输出;支持 1Hz 方波和 RTCOUT 输出功能;支持内部时钟校准补偿。
CW32L052 内置经独立校准的 32kHz 频率的 RC 时钟源,为 RTC 提供驱动时钟,RTC 可在深度休眠模式下运行,
适用于要求低功耗的应用场合。
12.2 主要特性
• 日历功能(BCD 码格式)
- 秒、分、时 ( 支持 12 / 24 小时制 )
- 星期、日、月份和年份,支持自动闰年修正
• 中断功能
- 闹钟 A、B 中断,可通过引脚输出
- 周期中断,宽范围:0.5s ~ 1 个月
- 自动唤醒中断,范围:61μs ~ 145h,可通过引脚输出
- 时间戳中断
• 校准补偿功能
- 最小时钟误差补偿步长,0.119ppm
- 1Hz 方波输出引脚
• 寄存器锁定保护功能,防止意外修改
其功能框图如下:
可工作于运行模式、休眠模式和深度休眠模式
结合CW32L052开发板上的LCD,可以制作一个电子时钟,可以显示日期、时间。为此将如何实现这一功能分享如下:
本次使用的RTC功能有三个,一个是设置和读取日期寄存器,二个是设置与读取时间寄存器,三是设置周期中官定时器,实现中断回调函数。
根据CW32L052用户手册需要包括以下步骤:
步骤 1:向 RTC_KEY 寄存器顺序写入 0xCA、0x53,解除 RTC 寄存器锁定;
步骤 2:
配置 RTC_CR0.H24 位域,我们选择24小时制;
步骤 3:
配置 RTC_CR1.SOURCE 位域,选择 RTC 时钟源;
注: 如选择 LSE 或 LSI,需要先使能和启动 LSE 或 LSI,并等待时钟稳定。
步骤 4:
设置正确的时间和日期值,写入时间和日期寄存器;
步骤 5:
配置需要的周期中断单元;按照官方给的功能框图,我们选择1秒产生一个中断:
步骤 6:
配置 RTC_IER 寄存器,设置周期中断;
步骤 7:
向 RTC_KEY 寄存器顺序写入 0xCA、0x--,启动 RTC 寄存器锁定保护。
用户应用中,对 RTC进行初始化时,应先检查 MCU的复位状态(SYSCTRL_RESETFLAG)。如果是上电复位(SYSCTRL_RESETFLAG.POR = 1),RTC 的寄存器会被复位到默认值,需要重新配置 RTC 控制寄存器、RTC 日期和时间寄存器,
并重新启动 RTC;其它复位条件不会复位 RTC 的寄存器,RTC 持续正常计时。
以上的配置功能,在CW32的固件库中cw32l052_rtc.c/cw32l052_rtc.h中给用户封装好了几个函数,用户只需要指定的时钟源、需要设置的当前日期、时间以及周期中断值就行了。然后使能中断就行了大大的简化了用户的代码量,以及在CW32同系列的移植.
对RTC的设置代码如下:
void my_rtc_init(void)
{
RTC_InitTypeDef RTC_InitStruct = {0};
RCC_APBPeriphClk_Enable1(RCC_APB1_PERIPH_RTC, ENABLE); //开启RTC时钟
RCC_LSI_Enable(); //开启LSI时钟
RTC_InitStruct.DateStruct.Day = 0x19; //设置日期,DAY、MONTH、YEAR必须为BCD方式,星期为0~6,代表星期日,星期一至星期六
RTC_InitStruct.DateStruct.Month = 7;
RTC_InitStruct.DateStruct.Week = RTC_Weekday_Monday;
RTC_InitStruct.DateStruct.Year = 0x23;
RTC_InitStruct.TimeStruct.Hour = 0x11; //设置时间,HOUR、MINIUTE、SECOND必须为BCD方式,用户须保证HOUR、AMPM、H24之间的关联正确性
RTC_InitStruct.TimeStruct.Minute = 0x58;
RTC_InitStruct.TimeStruct.Second = 0x59;
RTC_InitStruct.TimeStruct.AMPM = 0;
RTC_InitStruct.TimeStruct.H24 = 1;
RTC_InitStruct.RTC_ClockSource = RTC_RTCCLK_FROM_LSI; // 用户需选定需要使用的时钟源
RTC_Init(&RTC_InitStruct);
RTC_SetInterval(RTC_INTERVAL_EVERY_1S); //设置周期中断为1S
RTC_ITConfig(RTC_IT_INTERVAL, ENABLE); //配置周期中断开启
__disable_irq();
NVIC_EnableIRQ(RTC_IRQn); //使能RTC中断
__enable_irq();
}
中断函数中,我们设置了一个RTC_IRQHandlerCallBack回调函数,函数中检测是否为周期中断,如果是,先清中断标志,然后执行一个LCD显示日期以及时期的函数,程序代码如下:
void RTC_IRQHandlerCallBack(void)
{
if (RTC_GetITState(RTC_IT_INTERVAL)) //判断是否是RTC周期中断
{
RTC_ClearITPendingBit(RTC_IT_INTERVAL); //清除中断标志
ShowTime(); //执行LCD显示
}
}
在LDC显示函数中,我们首先定义两个结构体,用于存放获取的日期与时间函数,获取日期与时间后,执行LCD的显示函数,将BCD码分解并显示到LCD屏上。在程序中,我们设志了一个标志位,间隔显示日期与时间。
void ShowTime(void)
{
static uint8_t show_state = 0;
show_state =show_state%2;//大于2归标志位
RTC_TimeTypeDef RTC_TimeStruct = {0};
RTC_DateTypeDef RTC_DateStruct = {0};
lcd_clear();//清除显示
RTC_GetDate(&RTC_DateStruct);
RTC_GetTime(&RTC_TimeStruct);
//显示固定的‘-’
lcd_show_string(5,18); //
lcd_show_string(2,18);
if(show_state == 0)
{
lcd_show_string(7,RTC_DateStruct.Year>>4);
lcd_show_string(6,RTC_DateStruct.Year&0x0F);
lcd_show_string(4,RTC_DateStruct.Month>>4);
lcd_show_string(3,RTC_DateStruct.Month&0x0F);
lcd_show_string(1,RTC_DateStruct.Day>>4);
lcd_show_string(0,RTC_DateStruct.Day&0x0F);
}else {
lcd_show_string(7,RTC_TimeStruct.Hour>>4);
lcd_show_string(6,RTC_TimeStruct.Hour&0x0F);
lcd_show_string(4,RTC_TimeStruct.Minute>>4);
lcd_show_string(3,RTC_TimeStruct.Minute&0x0F);
lcd_show_string(1,RTC_TimeStruct.Second>>4);
lcd_show_string(0,RTC_TimeStruct.Second&0x0F);
}
show_state++;
}
程序下载到开发板显示效果如下 :
显示视频如下:
|
以CW32L052 RTC外设制作简易电子时钟,经典的RTC时钟案例,适合低功耗的应用场景。