日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

纠结的STM32 RTC时钟源LSE

發(fā)布時(shí)間:2025/3/21 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 纠结的STM32 RTC时钟源LSE 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一開始,所有實(shí)驗(yàn)都是在神舟板上去完成,根本就沒有發(fā)現(xiàn)RTC的問題。直到我們自己畫板來后調(diào)試時(shí),才發(fā)現(xiàn)STM32 RTC的外部時(shí)鐘源存在問題。

這也算是STM32的一個(gè)雞肋,對(duì)于LSE外部晶振太過于苛刻,手冊(cè)上要求使用6pf,這個(gè)規(guī)格的晶振市場(chǎng)上太少,魚龍混雜,中招的高手菜鳥不在少數(shù)。我們自己的板也是如此,幾經(jīng)波折,反反復(fù)復(fù)嘗試使用不同的規(guī)格的晶振,替換外部的電容,電阻都沒有能讓這個(gè)32.768K的LSE起振。但是又需要有RTC來提供時(shí)間,考慮的方法主要有2種,第一采用外部RTC時(shí)鐘芯片,如DS1302。第二是使用內(nèi)部其它的時(shí)鐘源來提供RTC時(shí)鐘。毫無疑問,目前板已經(jīng)制好,添加時(shí)鐘芯片肯定造成板上布局更改,還得重新打板,這里采用了第二種方法。

查看STM32的手冊(cè)上時(shí)鐘樹,如下:

除去不能起振的外部低速LSE外,可供使用的只有LSI和HSE的128分頻,LSI這個(gè)是內(nèi)部的40KHz RC振蕩器,頻率在30~60KHz浮動(dòng),自然這個(gè)不能用于RTC計(jì)時(shí),誤差太大。

我們的板上配的是STM32F107這款芯片,外部高速晶振是25MHz的。128分頻后頻率為 25000000 / 128 = 195312.5 Hz,很顯然這里也不能做到很精確,有小許誤差。

然后設(shè)置RTC_PRL寄存器,寫入195312這個(gè)分頻值,便可以得到1Hz的頻率。使用HSE作為RTC時(shí)鐘,缺點(diǎn)就是無法在斷開電源后使用后備電池進(jìn)行供電,維持RTC的正常。下次需要上位機(jī)重新去設(shè)置時(shí)間。

?

代碼大致如下:

  • void RTC_Configuration(void)

  • {

  • u8 i = 0;

  • /* Enable PWR and BKP clocks */

  • /* PWR時(shí)鐘(電源控制)與BKP時(shí)鐘(RTC后備寄存器)使能 */

  • RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);

  • ?
  • /* Allow access to BKP Domain */

  • /*使能RTC和后備寄存器訪問 */

  • PWR_BackupAccessCmd(ENABLE);

  • ?
  • /* Reset Backup Domain */

  • /* 將外設(shè)BKP的全部寄存器重設(shè)為缺省值 */

  • BKP_DeInit();

  • ?
  • /* Enable LSE */

  • /* 使能LSE(外部32.768KHz低速晶振)*/

  • RCC_LSEConfig(RCC_LSE_ON);

  • ?
  • /* Wait till LSE is ready */

  • /* 等待外部晶振震蕩穩(wěn)定輸出 */

  • TIM5_Init_Query(CALC_TYPE_MS); //ms 級(jí)別

  • for (i = 0;i < 10;i++) //10次檢測(cè),如果LSE仍然沒有起振,證明這玩意有問題,跳出循環(huán)

  • {

  • if (RCC_GetFlagStatus(RCC_FLAG_LSERDY) != RESET)

  • break;

  • TIM5_MS_CALC(1); //1ms延時(shí)

  • }

  • //while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET){}

  • if (i == 10)

  • {

  • //RCC->CSR |= 0x1; //開啟內(nèi)部低速晶振

  • //while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);

  • //RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); //使用LSI提供RTC時(shí)鐘

  • //使用外部高速晶振 128分頻

  • RCC_RTCCLKConfig(RCC_RTCCLKSource_HSE_Div128);

  • }else

  • {

  • /* Select LSE as RTC Clock Source */

  • /*使用外部32.768KHz晶振作為RTC時(shí)鐘 */

  • RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

  • }

  • ?
  • /* Enable RTC Clock */

  • /* 使能 RTC 的時(shí)鐘供給 */

  • RCC_RTCCLKCmd(ENABLE);

  • ?
  • /* Wait for RTC registers synchronization */

  • /*等待RTC寄存器同步 */

  • RTC_WaitForSynchro();

  • ?
  • /* Wait until last write operation on RTC registers has finished */

  • /* 等待上一次對(duì)RTC寄存器的寫操作完成 */

  • RTC_WaitForLastTask();

  • ?
  • /* Enable the RTC Second */

  • /* 使能RTC的秒中斷 */

  • RTC_ITConfig(RTC_IT_SEC, ENABLE);

  • ?
  • /* Wait until last write operation on RTC registers has finished */

  • /* 等待上一次對(duì)RTC寄存器的寫操作完成 */

  • RTC_WaitForLastTask();

  • ?
  • /* Set RTC prescaler: set RTC period to 1sec */

  • /* 32.768KHz晶振預(yù)分頻值是32767,如果對(duì)精度要求很高可以修改此分頻值來校準(zhǔn)晶振 */

  • if (i != 10) //LSE不能正常

  • RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */

  • else

  • RTC_SetPrescaler(195312); //25000000 / 128 = 195312.5,如果是8M / 128 = 62500,則這里應(yīng)該填為62499

  • ?
  • /* Wait until last write operation on RTC registers has finished */

  • /* 等待上一次對(duì)RTC寄存器的寫操作完成 */

  • RTC_WaitForLastTask();

  • }

  • ?
  • void Init_RTC(void)

  • {

  • /* 以下if...else.... if判斷系統(tǒng)時(shí)間是否已經(jīng)設(shè)置,判斷RTC后備寄存器1的值

  • 是否為事先寫入的0XA5A5,如果不是,則說明RTC是第一次上電,需要配置RTC,

  • 提示用戶通過串口更改系統(tǒng)時(shí)間,把實(shí)際時(shí)間轉(zhuǎn)化為RTC計(jì)數(shù)值寫入RTC寄存器,

  • 并修改后備寄存器1的值為0XA5A5。

  • else表示已經(jīng)設(shè)置了系統(tǒng)時(shí)間,打印上次系統(tǒng)復(fù)位的原因,并使能RTC秒中斷

  • */

  • if (BKP_ReadBackupRegister(BKP_DR1) != RTC_SEQ_ID)

  • {

  • /* Backup data register value is not correct or not yet programmed (when

  • the first time the program is executed) */

  • ?
  • /* RTC Configuration */

  • RTC_Configuration();

  • ?
  • ?
  • /* Adjust time by values entred by the user on the hyperterminal */

  • RTC_SetCounter(Time_Regulate(YEAR_BASE,01,01,0,0,0)); //2008-1-1 0:0:0

  • /* 修改后備寄存器1的值為0XA5A5 */

  • BKP_WriteBackupRegister(BKP_DR1, RTC_SEQ_ID);

  • }else

  • {

  • /* Check if the Power On Reset flag is set */

  • //RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET

  • // printf("\r\n\n Power On Reset occurred....");

  • ?
  • /* Check if the Pin Reset flag is set */

  • //else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET)

  • // printf("\r\n\n External Reset occurred....");

  • if (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)

  • {

  • //RCC->CSR |= 0x1; //開啟內(nèi)部低速晶振

  • //while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);

  • //RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); //使用LSI提供RTC時(shí)鐘

  • //RCC_RTCCLKConfig(RCC_RTCCLKSource_HSE_Div128);

  • RTC_Configuration();

  • }

  • //printf("\r\n No need to configure RTC....");

  • /* Wait for RTC registers synchronization */

  • RTC_WaitForSynchro();

  • ?
  • /* Enable the RTC Second */

  • RTC_ITConfig(RTC_IT_SEC, ENABLE);

  • ?
  • /* Wait until last write operation on RTC registers has finished */

  • RTC_WaitForLastTask();

  • }

  • ?
  • #ifdef RTCClockOutput_Enable

  • /* Enable PWR and BKP clocks */

  • RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);

  • ?
  • /* Allow access to BKP Domain */

  • PWR_BackupAccessCmd(ENABLE);

  • ?
  • /* Disable the Tamper Pin */

  • BKP_TamperPinCmd(DISABLE); /* To output RTCCLK/64 on Tamper pin, the tamper

  • functionality must be disabled */

  • ?
  • /* Enable RTC Clock Output on Tamper Pin */

  • BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock);

  • #endif

  • ?
  • /* Clear reset flags */

  • RCC_ClearFlag();

  • }



  • 實(shí)際測(cè)試,RTC效果還行,然后配合上位機(jī)隔一定的時(shí)間后同步時(shí)間基本上能夠滿足要求。

    萬惡的LSE晶振,這東西簡(jiǎn)直不能忍受......

    總結(jié)

    以上是生活随笔為你收集整理的纠结的STM32 RTC时钟源LSE的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。