今天花了一个多小时反复调了几次RTC,上电断电好几次,终于算是调通了,为了简单我只做了一个时间显示,没有加日期,不过原理都是一样的,可以根据不同情况来修改。
由于需要LCD来显示时间,写了一个新函数,代码如下:
void GC_showtime(u32 Time)
{
u8 hh,mm,ss;//时分秒
//测试只显示时间,采用24小时制
if (Time>=(24*3600)) RTC_SetCounter(0);
hh=Time/3600;
Time%=3600;
mm=Time/60;
ss=Time%60;
LCD_DrawNum(5,0x10,hh,2);
LCD_DrawChar(5,0x20,Dcolon);//":"
LCD_DrawNum(5,0x28,mm,2);
LCD_DrawChar(5,0x38,Dcolon);
LCD_DrawNum(5,0x40,ss,2);
}
好像那个DrawNum也是我自己写的...记不清了,年前的事情了,感觉那个函数有很强的个人风格,大家知道原理自己写一个就行,我就不公布误人子弟了。
下面是两个初始化相关的函数,都是网上找的,后者调用了前者,注释也比较清晰,相信对于理解有帮助(我要是早点儿看了这个多好~)。根据实际情况修改了一下,E板测试通过。
/*******************************************************************************
* Function Name : RTC_Configuration
* Description : Configures the RTC.
* Input :
None
* Output : None
* Return : None
*******************************************************************************/
void RTC_Configuration(void)
{
/* Enable PWR and BKP clocks */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR |
RCC_APB1Periph_BKP, ENABLE);
/* Allow access to BKP Domain */
PWR_BackupAccessCmd(ENABLE);
/* Reset Backup Domain */
BKP_DeInit();
/* Enable LSE */
RCC_LSEConfig(RCC_LSE_ON);
/* Wait till LSE is ready */
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
{
}
/* Select LSE as RTC Clock Source */
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
/* Enable RTC Clock */
RCC_RTCCLKCmd(ENABLE);
/* Wait for RTC registers synchronization */
RTC_WaitForSynchro();
/* Wait until last write operation on RTC registers has
finished */
RTC_WaitForLastTask();
/* Enable the RTC Second */
RTC_ITConfig(RTC_IT_SEC, ENABLE);
/* Wait until last write operation on RTC registers has
finished */
RTC_WaitForLastTask();
/* Set RTC prescaler: set RTC period to 1sec */
RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR =
(32.768 KHz)/(32767+1) */
/* Wait until last write operation on RTC registers has
finished */
RTC_WaitForLastTask();
}
/*******************************************************************************
* Function Name : RTC_Config
* Description : 上电时调用本函数,自动检查是否需要RTC初始化,
* 若需要重新初始化RTC,则调用RTC_Configuration()完成相应操作
* Input :
None
* Output : None
* Return : None
*******************************************************************************/
void RTC_Config(void)
{
//我们在BKP的后备寄存器1中,存了一个特殊字符0x1234
//第一次上电或后备电源掉电后,该寄存器数据丢失,
//表明RTC数据丢失,需要重新配置
if
(BKP_ReadBackupRegister(BKP_DR1) != 0x1234)
{
//重新配置RTC
RTC_Configuration();
//配置完成后,向后备寄存器中写特殊字符0x1234
BKP_WriteBackupRegister(BKP_DR1, 0x1234);
}
else
{
//若后备寄存器没有掉电,则无需重新配置RTC
//这里我们可以利用RCC_GetFlagStatus()函数查看本次复位类型
if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET)
{
//这是上电复位
}
else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET)
{
//这是外部RST管脚复位
}
//清除RCC中复位标志
RCC_ClearFlag();
//使能秒中断
RTC_ITConfig(RTC_IT_SEC, ENABLE);
//等待操作完成
RTC_WaitForLastTask();
}
//如果程序要修改RTC时钟,必须打开PWR模块和BKP模块的时钟,并解除BKP模块的写保护!!
/* Enable PWR and BKP
clocks */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP,
ENABLE);
/* Allow access to BKP
Domain */
PWR_BackupAccessCmd(ENABLE);
#ifdef RTCClockOutput_Enable
/* Disable the Tamper
Pin */
BKP_TamperPinCmd(DISABLE);
/* Enable RTC Clock
Output on Tamper Pin */
BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock);
#endif
return;
}
用到的函数基本就是这些,经过合理的组合就可以使用啦,主函数中使用RTC_GetCounter()函数读取当前计数值。到目前为止时钟已经可以掉电后仍然计时(别忘了板子上Vbat的跳线),实现24小时制的循环,日期什么的也都同理,选择一个时间原点相对计时就可以。不过显然还少了点儿什么...就是时间设置功能,传统的方法还是用按钮调节,我想用其他方法,也许行得通...暂且卖个关子。下次再续~