找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4736|回复: 0
打印 上一主题 下一主题
收起左侧

RTC实时时钟驱动函数固件库版和寄存器版对比

[复制链接]
跳转到指定楼层
楼主
ID:72008 发表于 2015-1-12 15:17 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
      前天,有个朋友问:如果电脑突然掉电导致一些重要数据丢失怎么办?我觉得对于STM32而言无需外挂E2PROM,凭借自身资源就可以解决:1,大容量STM32一般有512k的flash,可以在程序运行当中实时将重要数据更新到片内flash中;具体如何操作可以参考IAP例程,这个例程很好,不光可以学习IAP(在应用编程功能),还可以学到CM3内核的一些结构知识和对片内flash的操作;2,STM32的备份域(BKP)有42个u16类型数据寄存器,只要按流程操作这42个16位的备份域数据寄存器就可以当E2PROM用,当然必须配有电池。通过对备份域的操作还可以做一个闹钟。

       STM32的资源很丰富对应每个功能,STM32的软件工程师为其搭配了相应的库函数。有了这个固件库使得我们对STM32的应用程序开发更加简单,节省开发时间。但是我感觉要熟练运用库函数也不是一件容易的事,必须经常练习。

下面是RTC实时时钟固件库版驱动函数(原子例程):
  1. //实时时钟配置
  2. //初始化RTC时钟,同时检测时钟是否工作正常
  3. //BKP->DR1用于保存是否第一次配置的设置
  4. //返回0:正常
  5. //其他:错误代码
  6. u8 RTC_Init(void)
  7. {
  8. //检查是不是第一次配置时钟
  9. u8 temp=0;

  10. if (BKP_ReadBackupRegister(BKP_DR1) != 0x5050)//从指定的后备寄存器中读出数据:读出了与写入的指定数据不相乎
  11. {
  12. RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);//使能PWR和BKP外设时钟   
  13. PWR_BackupAccessCmd(ENABLE);//使能后备寄存器访问
  14. BKP_DeInit();//复位备份区域
  15. RCC_LSEConfig(RCC_LSE_ON);//设置外部低速晶振(LSE),使用外设低速晶振
  16. while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)//检查指定的RCC标志位设置与否,等待低速晶振就绪
  17. {
  18. temp++;
  19. delay_ms(10);
  20. }
  21. if(temp>=250)return 1;//初始化时钟失败,晶振有问题   
  22. RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//设置RTC时钟(RTCCLK),选择LSE作为RTC时钟   
  23. RCC_RTCCLKCmd(ENABLE);//使能RTC时钟  
  24. RTC_WaitForLastTask();//等待最近一次对RTC寄存器的写操作完成
  25. RTC_WaitForSynchro();//等待RTC寄存器同步  
  26. RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能RTC秒中断
  27. RTC_WaitForLastTask();//等待最近一次对RTC寄存器的写操作完成
  28. RTC_EnterConfigMode();/// 允许配置
  29. RTC_SetPrescaler(32767); //设置RTC预分频的值
  30. RTC_WaitForLastTask();//等待最近一次对RTC寄存器的写操作完成
  31. RTC_Set(2009,12,2,10,0,55);  //设置时间
  32. RTC_ExitConfigMode(); //退出配置模式  
  33. BKP_WriteBackupRegister(BKP_DR1, 0X5050);//向指定的后备寄存器中写入用户程序数据
  34. }
  35. else//系统继续计时
  36. {

  37. RTC_WaitForSynchro();//等待最近一次对RTC寄存器的写操作完成
  38. RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能RTC秒中断
  39. RTC_WaitForLastTask();//等待最近一次对RTC寄存器的写操作完成
  40. }
  41. RTC_NVIC_Config();//RCT中断分组设置         
  42. RTC_Get();//更新时间
  43. return 0; //ok

  44. }
复制代码

      该函数用的就是固件库中关于RTC部分的函数,整个操作都是按数据手册的操作流程来执行;其中用到了c语言编程技巧,临时变量temp防止程序死机。中断如何配置?一般都有固定格式。

下面是RTC实时时钟寄存器版驱动函数(原子例程):
  1. //实时时钟配置
  2. //初始化RTC时钟,同时检测时钟是否工作正常
  3. //BKP->DR1用于保存是否第一次配置的设置
  4. //返回0:正常
  5. //其他:错误代码
  6. u8 RTC_Init(void)
  7. {
  8. //检查是不是第一次配置时钟
  9. u8 temp=0;
  10. if(BKP->DR1!=0X5050)//第一次配置
  11. {
  12. RCC->APB1ENR|=1<<28;     //使能电源时钟   
  13. RCC->APB1ENR|=1<<27;     //使能备份时钟   
  14. PWR->CR|=1<<8;           //取消备份区写保护
  15. RCC->BDCR|=1<<16;        //备份区域软复位   
  16. RCC->BDCR&=~(1<<16);     //备份区域软复位结束   
  17.    RCC->BDCR|=1<<0;         //开启外部低速振荡器
  18.    while((!(RCC->BDCR&0X02))&&temp<250)//等待外部时钟就绪
  19. {
  20. temp++;
  21. delay_ms(10);
  22. };
  23. if(temp>=250)return 1;//初始化时钟失败,晶振有问题   

  24. RCC->BDCR|=1<<8; //LSI作为RTC时钟     
  25. RCC->BDCR|=1<<15;//RTC时钟使能  
  26. while(!(RTC->CRL&(1<<5)));//等待RTC寄存器操作完成
  27.     while(!(RTC->CRL&(1<<3)));//等待RTC寄存器同步  
  28.     RTC->CRH|=0X01;    //允许秒中断
  29.     while(!(RTC->CRL&(1<<5)));//等待RTC寄存器操作完成
  30. RTC->CRL|=1<<4;              //允许配置

  31. RTC->PRLH=0X0000;
  32. RTC->PRLL=32767;          //时钟周期设置(有待观察,看是否跑慢了?)理论值:32767
  33.    
  34. RTC_Set(2012,9,7,13,16,55);  //设置时间  
  35. RTC->CRL&=~(1<<4);           //配置更新
  36. while(!(RTC->CRL&(1<<5)));   //等待RTC寄存器操作完成   
  37. BKP->DR1=0X5050;  
  38. printf("FIRST TIME\n");
  39. }else//系统继续计时
  40. {
  41.     while(!(RTC->CRL&(1<<3)));//等待RTC寄存器同步  
  42.     RTC->CRH|=0X01;    //允许秒中断
  43.     while(!(RTC->CRL&(1<<5)));//等待RTC寄存器操作完成
  44. printf("OK\n");
  45. }      
  46. MY_NVIC_Init(0,0,RTC_IRQChannel,2);//优先级设置   
  47. RTC_Get();//更新时间
  48. return 0; //ok
  49. }
复制代码



就个人而言偏爱寄存器版本函数,思路清晰;同时可以学习如何操作寄存器。


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表