RTC时钟
上电之后,初始化完成,只要不断电,它就一直自动记录当前时间。任何时候都可以从它内部的寄存器读出当前的时间和日期。
一般32K晶振都会有一定的误差。如果希望RTC非常准,32K晶振就要进行补偿。新唐的RTC一般都带频率补偿寄存器。补偿值需要软件自行填入。一般一批32K晶振误差都差不多,使用频率计数器测一下晶振,然后将补偿值填入RTC就可以了。补偿值具体应该填多少,TRM(技术参考手册)里面RTC部分介绍的很详细,这里就不再赘述。
RTC除了做时钟,还能产生Tick中断和Alarm中断,并能唤醒系统。
使能外部32.768KHZ晶振:
void CLK_EnableXtalRC(uint32_t u32ClkMask);
* -
ef CLK_PWRCTL_HXTEN_Msk
* -
ef CLK_PWRCTL_LXTEN_Msk
* -
ef CLK_PWRCTL_HIRCEN_Msk
* -
ef CLK_PWRCTL_LIRCEN_Msk
等待时钟稳定:
uint32_t CLK_WaitClockReady(uint32_t u32ClkMask);
* -
ef CLK_STATUS_HXTSTB_Msk
* -
ef CLK_STATUS_LXTSTB_Msk
* -
ef CLK_STATUS_HIRCSTB_Msk
* -
ef CLK_STATUS_LIRCSTB_Msk
* -
ef CLK_STATUS_PLLSTB_Msk
* @retval 0 clock is not stable
* @retval 1 clock is stable
设置RTC时钟源:
void CLK_SetModuleClock(uint32_t u32ModuleIdx, uint32_t u32ClkSrc, uint32_t u32ClkDiv);
* |Module index | Clock source | Divider |
* |
ef RTC_MODULE |
ef CLK_CLKSEL3_RTCSEL_LXT | x |
* |
ef RTC_MODULE | ref CLK_CLKSEL3_RTCSEL_LIRC | x |
使能RTC时钟源:
void CLK_EnableModuleClock(uint32_t u32ModuleIdx);
* - ef RTC_MODULE
选择时钟源+使能时钟::: /* 使能RTC的时钟 */ CLK->APBCLK |= CLK_APBCLK_RTC_EN_Msk;
开启并初始化时钟值:
void RTC_Open(S_RTC_TIME_DATA_T *sPt);
* @param[in] sPt Specify the time property and current date and time. It includes:
* u32Year: Year value, range between 2000 ~ 2099.
* u32Month: Month value, range between 1 ~ 12.
* u32Day: Day value, range between 1 ~ 31.
* u32DayOfWeek: Day of the week. [RTC_SUNDAY / RTC_MONDAY / RTC_TUESDAY /
* RTC_WEDNESDAY / RTC_THURSDAY / RTC_FRIDAY /
* RTC_SATURDAY]
* u32Hour: Hour value, range between 0 ~ 23.
* u32Minute: Minute value, range between 0 ~ 59.
* u32Second: Second value, range between 0 ~ 59.
* u32TimeScale: [RTC_CLOCK_12 / RTC_CLOCK_24]
* u8AmPm: [RTC_AM / RTC_PM]
开启TICK中断:
void RTC_SetTickPeriod(uint32_t u32TickSelection);
* @param[in] u32TickSelection It is used to set the RTC tick period time for Periodic Time Tick request.
* It consists of:
* RTC_TICK_1_SEC: Time tick is 1 second
* RTC_TICK_1_2_SEC: Time tick is 1/2 second
* RTC_TICK_1_4_SEC: Time tick is 1/4 second
* RTC_TICK_1_8_SEC: Time tick is 1/8 second
* RTC_TICK_1_16_SEC: Time tick is 1/16 second
* RTC_TICK_1_32_SEC: Time tick is 1/32 second
* RTC_TICK_1_64_SEC: Time tick is 1/64 second
* RTC_TICK_1_128_SEC: Time tick is 1/128 second
void RTC_EnableInt(uint32_t u32IntFlagMask);
* @param[in] u32IntFlagMask Specify the interrupt source. It consists of:
* RTC_INTEN_ALMIEN_Msk: Alarm interrupt
* RTC_INTEN_TICKIEN_Msk: Tick interrupt
* RTC_INTEN_SNPDIEN_Msk: Snooper Pin Event Detection interrupt
开启总中断:
NVIC_EnableIRQ(RTC_IRQn);
贴上代码(遇到的小问题:没有解锁保护寄存器时,LXT是启动不了的。)
void rtc_init(void) { S_RTC_TIME_DATA_T mDataTime; // 解锁保护寄存器 SYS_UnlockReg(); CLK_EnableXtalRC(CLK_PWRCTL_LXTEN_Msk); CLK_WaitClockReady(CLK_STATUS_LXTSTB_Msk); CLK_SetModuleClock(RTC_MODULE,CLK_CLKSEL3_RTCSEL_LXT,1); CLK_EnableModuleClock(RTC_MODULE); // 加锁保护寄存器 SYS_LockReg(); mDataTime.u32Year = 2018; mDataTime.u32Month = 5; mDataTime.u32Day = 24; mDataTime.u32DayOfWeek = RTC_THURSDAY; mDataTime.u32Hour = 23; mDataTime.u32Minute = 0; mDataTime.u32Second = 0; mDataTime.u32TimeScale = RTC_CLOCK_24; RTC_Open(&mDataTime); RTC_SetTickPeriod(RTC_TICK_1_SEC); RTC_EnableInt(RTC_INTEN_TICKIEN_Msk); NVIC_EnableIRQ(RTC_IRQn); }
void RTC_IRQHandler(void) { S_RTC_TIME_DATA_T mDataTime; if( RTC_GET_TICK_INT_FLAG() ) { RTC_CLEAR_TICK_INT_FLAG(); RTC_GetDateAndTime(&mDataTime); printf("Time:%d/%02d/%02d %02d:%02d:%02d ",mDataTime.u32Year,mDataTime.u32Month,mDataTime.u32Day,mDataTime.u32Hour,mDataTime.u32Minute,mDataTime.u32Second); } }