微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > STM32 RTC时钟源LSE

STM32 RTC时钟源LSE

时间:11-17 来源:互联网 点击:
一开始,所有实验都是在神舟板上去完成,根本就没有发现RTC的问题。直到我们自己画板来后调试时,才发现STM32 RTC的外部时钟源存在问题。

这也算是STM32的一个鸡肋,对于LSE外部晶振太过于苛刻,手册上要求使用6pf,这个规格的晶振市场上太少,鱼龙混杂,中招的高手菜鸟不在少数。我们自己的板也是如此,几经波折,反反复复尝试使用不同的规格的晶振,替换外部的电容,电阻都没有能让这个32.768K的LSE起振。但是又需要有RTC来提供时间,考虑的方法主要有2种,第一采用外部RTC时钟芯片,如DS1302。第二是使用内部其它的时钟源来提供RTC时钟。毫无疑问,目前板已经制好,添加时钟芯片肯定造成板上布局更改,还得重新打板,这里采用了第二种方法。

查看STM32的手册上时钟树,如下:

除去不能起振的外部低速LSE外,可供使用的只有LSI和HSE的128分频,LSI这个是内部的40KHz RC振荡器,频率在30~60KHz浮动,自然这个不能用于RTC计时,误差太大。

我们的板上配的是STM32F107这款芯片,外部高速晶振是25MHz的。128分频后频率为 25000000 / 128 = 195312.5 Hz,很显然这里也不能做到很精确,有小许误差。

然后设置RTC_PRL寄存器,写入195312这个分频值,便可以得到1Hz的频率。使用HSE作为RTC时钟,缺点就是无法在断开电源后使用后备电池进行供电,维持RTC的正常。下次需要上位机重新去设置时间。

代码大致如下:

  1. voidRTC_Configuration(void)
  2. {
  3. u8i=0;
  4. /*EnablePWRandBKPclocks*/
  5. /*PWR时钟(电源控制)与BKP时钟(RTC后备寄存器)使能*/
  6. RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE);
  7. /*AllowaccesstoBKPDomain*/
  8. /*使能RTC和后备寄存器访问*/
  9. PWR_BackupAccessCmd(ENABLE);
  10. /*ResetBackupDomain*/
  11. /*将外设BKP的全部寄存器重设为缺省值*/
  12. BKP_DeInit();
  13. /*EnableLSE*/
  14. /*使能LSE(外部32.768KHz低速晶振)*/
  15. RCC_LSEConfig(RCC_LSE_ON);
  16. /*WaittillLSEisready*/
  17. /*等待外部晶振震荡稳定输出*/
  18. TIM5_Init_Query(CALC_TYPE_MS);//ms级别
  19. for(i=0;i<10;i++)//10次检测,如果LSE仍然没有起振,证明这玩意有问题,跳出循环
  20. {
  21. if(RCC_GetFlagStatus(RCC_FLAG_LSERDY)!=RESET)
  22. break;
  23. TIM5_MS_CALC(1);//1ms延时
  24. }
  25. //while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET){}
  26. if(i==10)
  27. {
  28. //RCC->CSR|=0x1;//开启内部低速晶振
  29. //while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY)==RESET);
  30. //RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);//使用LSI提供RTC时钟
  31. //使用外部高速晶振128分频
  32. RCC_RTCCLKConfig(RCC_RTCCLKSource_HSE_Div128);
  33. }else
  34. {
  35. /*SelectLSEasRTCClockSource*/
  36. /*使用外部32.768KHz晶振作为RTC时钟*/
  37. RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
  38. }
  39. /*EnableRTCClock*/
  40. /*使能RTC的时钟供给*/
  41. RCC_RTCCLKCmd(ENABLE);
  42. /*WaitforRTCregisterssynchronization*/
  43. /*等待RTC寄存器同步*/
  44. RTC_WaitForSynchro();
  45. /*WaituntillastwriteoperationonRTCregistershasfinished*/
  46. /*等待上一次对RTC寄存器的写操作完成*/
  47. RTC_WaitForLastTask();
  48. /*EnabletheRTCSecond*/
  49. /*使能RTC的秒中断*/
  50. RTC_ITConfig(RTC_IT_SEC,ENABLE);
  51. /*WaituntillastwriteoperationonRTCregistershasfinished*/
  52. /*等待上一次对RTC寄存器的写操作完成*/
  53. RTC_WaitForLastTask();
  54. /*SetRTCprescaler:setRTCperiodto1sec*/
  55. /*32.768KHz晶振预分频值是32767,如果对精度要求很高可以修改此分频值来校准晶振*/
  56. if(i!=10)//LSE不能正常
  57. RTC_SetPrescaler(32767);/*RTCperiod=RTCCLK/RTC_PR=(32.768KHz)/(32767+1)*/
  58. else
  59. RTC_SetPrescaler(195312);//25000000/128=195312.5,如果是8M/128=62500,则这里应该填为62499
  60. /*WaituntillastwriteoperationonRTCregistershasfinished*/
  61. /*等待上一次对RTC寄存器的写操作完成*/
  62. RTC_WaitForLastTask();
  63. }
  64. voidInit_RTC(void)
  65. {
  66. /*以下if...else....if判断系统时间是否已经设置,判断RTC后备寄存器1的值
  67. 是否为事先写入的0XA5A5,如果不是,则说明RTC是第一次上电,需要配置RTC,
  68. 提示用户通过串口更改系统时间,把实际时间转化为RTC计数值写入RTC寄存器,
  69. 并修改后备寄存器1的值为0XA5A5。
  70. else表示已经设置了系统时间,打印上次系统复位的原因,并使能RTC秒中断
  71. */
  72. if(BKP_ReadBackupRegister(BKP_DR1)!=RTC_SEQ_ID)
  73. {
  74. /*Backupdataregistervalueisnotcorrectornotyetprogrammed(when
  75. thefirsttimetheprogramisexecuted)*/
  76. /*RTCConfiguration*/
  77. RTC_Configuration();
  78. /*Adjusttimebyvaluesentredbytheuseronthehyperterminal*/
  79. RTC_SetCounter(Time_Regulate(YEAR_BASE,01,01,0,0,0));//2008-1-10:0:0
  80. /*修改后备寄

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top