标题:
RTC实时时钟驱动函数固件库版和寄存器版对比
[打印本页]
作者:
liuyy
时间:
2015-1-12 15:17
标题:
RTC实时时钟驱动函数固件库版和寄存器版对比
前天,有个朋友问:如果电脑突然掉电导致一些重要数据丢失怎么办?我觉得对于STM32而言无需外挂E2PROM,凭借自身资源就可以解决:1,大容量STM32一般有512k的flash,可以在程序运行当中实时将重要数据更新到片内flash中;具体如何操作可以参考IAP例程,这个例程很好,不光可以学习IAP(在应用编程功能),还可以学到CM3内核的一些结构知识和对片内flash的操作;2,STM32的备份域(BKP)有42个u16类型数据寄存器,只要按流程操作这42个16位的备份域数据寄存器就可以当E2PROM用,当然必须配有电池。通过对备份域的操作还可以做一个闹钟。
STM32的资源很丰富对应每个功能,STM32的软件工程师为其搭配了相应的库函数。有了这个固件库使得我们对STM32的应用程序开发更加简单,节省开发时间。但是我感觉要熟练运用库函数也不是一件容易的事,必须经常练习。
下面是RTC实时时钟固件库版驱动函数(原子例程):
//实时时钟配置
//初始化RTC时钟,同时检测时钟是否工作正常
//BKP->DR1用于保存是否第一次配置的设置
//返回0:正常
//其他:错误代码
u8 RTC_Init(void)
{
//检查是不是第一次配置时钟
u8 temp=0;
if (BKP_ReadBackupRegister(BKP_DR1) != 0x5050)//从指定的后备寄存器中读出数据:读出了与写入的指定数据不相乎
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);//使能PWR和BKP外设时钟
PWR_BackupAccessCmd(ENABLE);//使能后备寄存器访问
BKP_DeInit();//复位备份区域
RCC_LSEConfig(RCC_LSE_ON);//设置外部低速晶振(LSE),使用外设低速晶振
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)//检查指定的RCC标志位设置与否,等待低速晶振就绪
{
temp++;
delay_ms(10);
}
if(temp>=250)return 1;//初始化时钟失败,晶振有问题
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//设置RTC时钟(RTCCLK),选择LSE作为RTC时钟
RCC_RTCCLKCmd(ENABLE);//使能RTC时钟
RTC_WaitForLastTask();//等待最近一次对RTC寄存器的写操作完成
RTC_WaitForSynchro();//等待RTC寄存器同步
RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能RTC秒中断
RTC_WaitForLastTask();//等待最近一次对RTC寄存器的写操作完成
RTC_EnterConfigMode();/// 允许配置
RTC_SetPrescaler(32767); //设置RTC预分频的值
RTC_WaitForLastTask();//等待最近一次对RTC寄存器的写操作完成
RTC_Set(2009,12,2,10,0,55); //设置时间
RTC_ExitConfigMode(); //退出配置模式
BKP_WriteBackupRegister(BKP_DR1, 0X5050);//向指定的后备寄存器中写入用户程序数据
}
else//系统继续计时
{
RTC_WaitForSynchro();//等待最近一次对RTC寄存器的写操作完成
RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能RTC秒中断
RTC_WaitForLastTask();//等待最近一次对RTC寄存器的写操作完成
}
RTC_NVIC_Config();//RCT中断分组设置
RTC_Get();//更新时间
return 0; //ok
}
复制代码
该函数用的就是固件库中关于RTC部分的函数,整个操作都是按数据手册的操作流程来执行;其中用到了c语言编程技巧,临时变量temp防止程序死机。中断如何配置?一般都有固定格式。
下面是RTC实时时钟寄存器版驱动函数(原子例程):
//实时时钟配置
//初始化RTC时钟,同时检测时钟是否工作正常
//BKP->DR1用于保存是否第一次配置的设置
//返回0:正常
//其他:错误代码
u8 RTC_Init(void)
{
//检查是不是第一次配置时钟
u8 temp=0;
if(BKP->DR1!=0X5050)//第一次配置
{
RCC->APB1ENR|=1<<28; //使能电源时钟
RCC->APB1ENR|=1<<27; //使能备份时钟
PWR->CR|=1<<8; //取消备份区写保护
RCC->BDCR|=1<<16; //备份区域软复位
RCC->BDCR&=~(1<<16); //备份区域软复位结束
RCC->BDCR|=1<<0; //开启外部低速振荡器
while((!(RCC->BDCR&0X02))&&temp<250)//等待外部时钟就绪
{
temp++;
delay_ms(10);
};
if(temp>=250)return 1;//初始化时钟失败,晶振有问题
RCC->BDCR|=1<<8; //LSI作为RTC时钟
RCC->BDCR|=1<<15;//RTC时钟使能
while(!(RTC->CRL&(1<<5)));//等待RTC寄存器操作完成
while(!(RTC->CRL&(1<<3)));//等待RTC寄存器同步
RTC->CRH|=0X01; //允许秒中断
while(!(RTC->CRL&(1<<5)));//等待RTC寄存器操作完成
RTC->CRL|=1<<4; //允许配置
RTC->PRLH=0X0000;
RTC->PRLL=32767; //时钟周期设置(有待观察,看是否跑慢了?)理论值:32767
RTC_Set(2012,9,7,13,16,55); //设置时间
RTC->CRL&=~(1<<4); //配置更新
while(!(RTC->CRL&(1<<5))); //等待RTC寄存器操作完成
BKP->DR1=0X5050;
printf("FIRST TIME\n");
}else//系统继续计时
{
while(!(RTC->CRL&(1<<3)));//等待RTC寄存器同步
RTC->CRH|=0X01; //允许秒中断
while(!(RTC->CRL&(1<<5)));//等待RTC寄存器操作完成
printf("OK\n");
}
MY_NVIC_Init(0,0,RTC_IRQChannel,2);//优先级设置
RTC_Get();//更新时间
return 0; //ok
}
复制代码
就个人而言偏爱寄存器版本函数,思路清晰;同时可以学习如何操作寄存器。
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1