一开始,一切试验都是在神舟板上去完结,根本就没有发现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的正常。下次需求上位机从头去设置时刻。
代码大致如下:
- voidRTC_Configuration(void)
- {
- u8i=0;
- /*EnablePWRandBKPclocks*/
- /*PWR时钟(电源操控)与BKP时钟(RTC后备存放器)使能*/
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE);
- /*AllowaccesstoBKPDomain*/
- /*使能RTC和后备存放器拜访*/
- PWR_BackupAccessCmd(ENABLE);
- /*ResetBackupDomain*/
- /*将外设BKP的悉数存放器重设为缺省值*/
- BKP_DeInit();
- /*EnableLSE*/
- /*使能LSE(外部32.768KHz低速晶振)*/
- RCC_LSEConfig(RCC_LSE_ON);
- /*WaittillLSEisready*/
- /*等候外部晶振震动安稳输出*/
- TIM5_Init_Query(CALC_TYPE_MS);//ms等级
- for(i=0;i<10;i++)//10次检测,假如LSE依然没有起振,证明这玩意有问题,跳出循环
- {
- if(RCC_GetFlagStatus(RCC_FLAG_LSERDY)!=RESET)
- break;
- TIM5_MS_CALC(1);//1ms延时
- }
- //while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET){}
- if(i==10)
- {
- //RCC->CSR|=0x1;//敞开内部低速晶振
- //while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY)==RESET);
- //RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);//运用LSI供应RTC时钟
- //运用外部高速晶振128分频
- RCC_RTCCLKConfig(RCC_RTCCLKSource_HSE_Div128);
- }else
- {
- /*SelectLSEasRTCClockSource*/
- /*运用外部32.768KHz晶振作为RTC时钟*/
- RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
- }
- /*EnableRTCClock*/
- /*使能RTC的时钟供应*/
- RCC_RTCCLKCmd(ENABLE);
- /*WaitforRTCregisterssynchronization*/
- /*等候RTC存放器同步*/
- RTC_WaitForSynchro();
- /*WaituntillastwriteoperationonRTCregistershasfinished*/
- /*等候上一次对RTC存放器的写操作完结*/
- RTC_WaitForLastTask();
- /*EnabletheRTCSecond*/
- /*使能RTC的秒中止*/
- RTC_ITConfig(RTC_IT_SEC,ENABLE);
- /*WaituntillastwriteoperationonRTCregistershasfinished*/
- /*等候上一次对RTC存放器的写操作完结*/
- RTC_WaitForLastTask();
- /*SetRTCprescaler:setRTCperiodto1sec*/
- /*32.768KHz晶振预分频值是32767,假如对精度要求很高可以修正此分频值来校准晶振*/
- if(i!=10)//LSE不能正常
- RTC_SetPrescaler(32767);/*RTCperiod=RTCCLK/RTC_PR=(32.768KHz)/(32767+1)*/
- else
- RTC_SetPrescaler(195312);//25000000/128=195312.5,假如是8M/128=62500,则这儿应该填为62499
- /*WaituntillastwriteoperationonRTCregistershasfinished*/
- /*等候上一次对RTC存放器的写操作完结*/
- RTC_WaitForLastTask();
- }
- voidInit_RTC(void)
- {
- /*以下if…else….if判别体系时刻是否现已设置,判别RTC后备存放器1的值
- 是否为事前写入的0XA5A5,假如不是,则阐明RTC是榜首次上电,需求装备RTC,
- 提示用户经过串口更改体系时刻,把实践时刻转化为RTC计数值写入RTC存放器,
- 并修正后备存放器1的值为0XA5A5。
- else表明现已设置了体系时刻,打印前次体系复位的原因,并使能RTC秒中止
- */
- if(BKP_ReadBackupRegister(BKP_DR1)!=RTC_SEQ_ID)
- {
- /*Backupdataregistervalueisnotcorrectornotyetprogrammed(when
- thefirsttimetheprogramisexecuted)*/
- /*RTCConfiguration*/
- RTC_Configuration();
- /*Adjusttimebyvaluesentredbytheuseronthehyperterminal*/
- RTC_SetCounter(Time_Regulate(YEAR_BASE,01,01,0,0,0));//2008-1-10:0:0
- /*修正后备存放器1的值为0XA5A5*/
- BKP_WriteBackupRegister(BKP_DR1,RTC_SEQ_ID);
- }else
- {
- /*CheckifthePowerOnResetflagisset*/
- //RCC_GetFlagStatus(RCC_FLAG_PORRST)!=RESET
- //printf(“\r\n\nPowerOnResetoccurred….”);
- /*CheckifthePinResetflagisset*/
- //elseif(RCC_GetFlagStatus(RCC_FLAG_PINRST)!=RESET)
- //printf(“\r\n\nExternalResetoccurred….”);
- if(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET)
- {
- //RCC->CSR|=0x1;//敞开内部低速晶振
- //while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY)==RESET);
- //RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);//运用LSI供应RTC时钟
- //RCC_RTCCLKConfig(RCC_RTCCLKSource_HSE_Div128);
- RTC_Configuration();
- }
- //printf(“\r\nNoneedtoconfigureRTC….”);
- /*WaitforRTCregisterssynchronization*/
- RTC_WaitForSynchro();
- /*EnabletheRTCSecond*/
- RTC_ITConfig(RTC_IT_SEC,ENABLE);
- /*WaituntillastwriteoperationonRTCregistershasfinished*/
- RTC_WaitForLastTask();
- }
- #ifdefRTCClockOutput_Enable
- /*EnablePWRandBKPclocks*/
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE);
- /*AllowaccesstoBKPDomain*/
- PWR_BackupAccessCmd(ENABLE);
- /*DisabletheTamperPin*/
- BKP_TamperPinCmd(DISABLE);/*TooutputRTCCLK/64onTamperpin,thetamper
- functionalitymustbedisabled*/
- /*EnableRTCClockOutputonTamperPin*/
- BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock);
- #endif
- /*Clearresetflags*/
- RCC_ClearFlag();
- }
实践测验,RTC作用还行,然后合作上位机隔必定的时刻后同步时刻基本上可以满足要求。
万恶的LSE晶振,这东西几乎不能忍耐……