ARM學習《十》—關於STM32的RTC調試

來源:互聯網
上載者:User

覺得不錯轉過來,原地址http://home.eeworld.com.cn/my/space.php?uid=116357&do=blog&id=31769

這兩天一直在調試STM32的RTC部分,本來打算弄一個萬年曆的,但是現在看來是暫時實現不了了。為什麼這樣說,因為RTC對晶振的要求非常高,必須是6p負載電容的32768晶振,這種晶振很難買,而且還很貴。下面是摘自一位網友的話:

今天到電子市場找了一下,幾乎都是12.5p負載電容的32768晶振,只有一家有少量,負載電容是6p,20ppm的晶振要價是12.5p晶振的5倍,而且從外觀上也看不出來,也沒有測試方法能測出負載電容是6p還是12.5p。賣晶振的老闆在這行幹了10幾年,一說到6p的32768晶振就笑了。這個要求以前就有多個公司中過招,特別是DALLAS的片子,讓一家公司吃盡了苦頭,焊上的許多高精度12.5p晶振被迫全部換掉,訂的數萬隻晶振也只能委託賣掉。老闆說這種方式是IC廠家和大的晶振廠家聯合的一個小陰謀,因為以前6p的晶振只有很少幾個大廠家能做好,這樣可以協助大晶振廠家形成壟斷。DALLAS的東西不敢恭維,向來賣得很貴,一片增強型的51經常還要賣四五十。
   6p的晶振既昂貴又不好採購,而且也難以辨認和測試。STM32這樣設計實在是難以理喻。其它我們用過的所有涉及RTC的MCU和時鐘晶片都不存在這個問題,如三星的44B0,2410,2440,飛利浦的LPC213x,LP214x等等。
   STM32是高度強調性價比的晶片,但是卻在RTC晶振上給中小客戶帶來很大不必要的麻煩,既增加成本和採購難度,又留下致命的隱患(RTC啟動死機)。特別是試樣和試生產階段,量又不大,怎麼去專門訂做?
   希望ST公司能正視這個問題,在以後的改進中修正這個問題,能支援12.5p的常規32768晶振。

調試了好長時間,我說怎麼沒有反應,原來是因為晶振的原因,而且電容必須接6PF,我用的是15P的電容,等待晶振起振的時間特別長(1分鐘左右),開始我還以為是程式死在哪了呢!

後來程式是調通了,但是1S中斷特別不準,我相信一定是因為晶振和電容的原因,先不管準不準,至少程式是調通了。把設定RTC的過程和大家分享:

還是將寄存器定義添加若標頭檔:

//*************************************************************

//PWR-Register

//*************************************************************

#define PWR_CR        (*((volatile unsigned long *)0x40007000))

#define PWR_CSR        (*((volatile unsigned long *)0x40007004))

//*******************************************************************

//

// RTC-Register

//           

//*******************************************************************

#define RTC_CRH     (*((volatile unsigned long *)0x40002800))

#define RTC_CRL     (*((volatile unsigned long *)0x40002804))

#define RTC_PRLH    (*((volatile unsigned long *)0x40002808))

#define RTC_PRLL    (*((volatile unsigned long *)0x4000280C))

#define RTC_DIVH    (*((volatile unsigned long *)0x40002810))

#define RTC_DIVL    (*((volatile unsigned long *)0x40002814))

#define RTC_CNTH    (*((volatile unsigned long *)0x40002818))

#define RTC_CNTL    (*((volatile unsigned long *)0x4000281C))

#define RTC_ALRH    (*((volatile unsigned long *)0x40002820))

#define RTC_ALRL    (*((volatile unsigned long *)0x40002824))

 

接下來就是RTC的寄存器配置:

void RTC_Configuration(void)

{

 RCC_APB1ENR|=0x18000000;  //電源介面時鐘使能, 備份介面時鐘使能

 PWR_CR|=0x00000100;//位8,允許訪問RTC 寄存器和備份寄存器

 RCC_APB1RSTR|=0x08000000;//位27 BKPRST 備份介面複位

 RCC_BDCR|=0x00000001;     //位0 LSEON 外部低速振蕩器使能

 while(RCC_BDCR&0x00000002==0); // 位1 LSERDY 外部低速振蕩器可用

 

  RCC_BDCR|=0x00000100; //選擇LSE位RTC時鐘

  RCC_BDCR|=0x00008000; //位15 RTCEN RTC 時鐘使能

 

 RTC_CRL|=0x10;   //位4 配置標誌,1: 進入配置模式

while(RTC_CRL&0x04==0);   //位3 RSF: 寄存器同步標誌

 while(RTC_CRL&0x20==0); //位5, 在RTC 寄存器上最近一次寫操作已經完成

 RTC_CRH=0x01;//使能1S中斷

while(RTC_CRL&0x20==0);  //位5, 在RTC 寄存器上最近一次寫操作已經完成

 

 RTC_PRLL=0xFF;//(1S中斷應該是32767,但我的晶振不準,0xFF都是1S多)

 

while(RTC_CRL&0x20==0);  //位5,在RTC 寄存器上最近一次寫操作已經完成

 

 RTC_CRL&=0xFFEF; //位4,退出配置模式(開始更新RTC 寄存器).

 

 SETENA0|=0x00000008;    //允許RTC中斷

 

}

RTC中斷處理函數:

void RTC_IRQHandler(void)

{

 if(RTC_CRL&0x01==1) //查詢1S中斷標誌

 {

  RTC_CRL&=0xFFFE; // 1S中斷標誌清除

  if(IO_flag==0)   //1S,LED閃爍一次

 {

  GPIO_PORTB_ODR|=(1<<5);

  IO_flag=1; // IO_flag為自己設的一個全域變數,用於LED取反

 }

 else {    GPIO_PORTB_ODR&=~(1<<5);

       IO_flag=0;

       }

 }

}

 

int main()

 {

 SystemInit0();    //系統(時鐘)初始化

 stm32_GpioSetup (); //GPIO初始化

 RTC_Configuration();//RTC配置

 while(1)

 {

}

}

又搞定了一部分……

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.