經過這么10天的瞎搞,我的庫已經初具規模了,于是,不用每次都把所有的文件copy過去,直接在Option里面把path給加上就ok了。

RTC的時鐘配置,RTC的時間寄存器是2個32位的寄存器,無非就是一個計數器,大概可以這樣理解吧,我們先看看時鐘吧

RTC的時鐘可以從這3路來,我們需要PTCSEL寄存器來進行設置,

上面這個圖是摘自李想老師的課件里面的,我覺得這個是做的相對好的!
位了保證RTC正常工作,我們需要在系統斷電時,RTC不受影響,當然我們一般都需要接一個Battery,作為rtc的后備電源,這里設計到電源管理,我們先來看看電源管理里面關于rtc的

只要我們把第八位置1我們就可以對其進行正常供電,我們還發現,他也可以給后備寄存器供電,這個后備寄存器是是個什么東東呢?
有興趣的可以研究研究備份寄存器(BKP),他的主要功能是侵入檢查和RTC校準,他既然跟RTC有關系,我們就要好好看看他了;
復位和時鐘控制里面有個備份域控制寄存器RCC_BDCR
注意: ?備份域控制寄存器中(RCC_BDCR)的LSEON、LSEBYP、RTCSEL和RTCEN位處于備份域。因
此,這些位在復位后處于寫保護狀態,只有在電源控制寄存器(PWR_CR)中的DBP位置’1’后才
能對這些位進行改動。進一步信息請參考5.1節。這些位只能由備份域復位清除(見6.1.3節)。任
何內部或外部復位都不會影響這些位。

位31:17 ?保留,始終讀為0。
BDRST:備份域軟件復位(Backup domain software reset) ?位16?
由軟件置’1’或清’0’?
0:復位未激活;
1:復位整個備份域。
RTCEN:RTC時鐘使能(RTC clock enable) ?位15?
由軟件置’1’或清’0’?
0:RTC時鐘關閉;
1:RTC時鐘開啟。
位14:10 ?保留,始終讀為0。
RTCSEL[1:0]:RTC時鐘源選擇(RTC clock source selection) ?位9:8?
由軟件設置來選擇RTC時鐘源。一旦RTC時鐘源被選定,直到下次后備域被復位,它不能在被
改變。可通過設置BDRST位來清除。
00:無時鐘;
01:LSE振蕩器作為RTC時鐘;
10:LSI振蕩器作為RTC時鐘;
11:HSE振蕩器在128分頻后作為RTC時鐘。
位7:3 ?保留,始終讀為0。
LSEBYP:外部低速時鐘振蕩器旁路(External low-speed oscillator bypass) ?位2?
在調試模式下由軟件置’1’或清’0’來旁路LSE。只有在外部32kHz振蕩器關閉時,才能寫入該位
0:LSE時鐘未被旁路;
1:LSE時鐘被旁路。
LSERDY:外部低速LSE就緒(External low-speed oscillator ready) ?位1?
由硬件置’1’或清’0’來指示是否外部32kHz振蕩器就緒。在LSEON被清零后,該位需要6個外部
低速振蕩器的周期才被清零。
0:外部32kHz振蕩器未就緒;
1:外部32kHz振蕩器就緒。
LSEON:外部低速振蕩器使能(External low-speed oscillator enable) ?位0?
由軟件置’1’或清’0’?
0:外部32kHz振蕩器關閉;
1:外部32kHz振蕩器開啟。
看來這一寄存器果真與RTC有很大的聯系,我們需要啟用外部32K的振蕩器,所以RCC->BDCR |= 1<<0;
設置完了,我們還需要等待32K的時鐘就緒,判斷bit1的狀態!
由于我們選用的32K的LSE作為RTC的時鐘,所以上面我們提到的RTCSEL寄存器必須設置為1,設置完后我們就開啟32K時鐘
RCC->BDCR |= 1<<8;
RCC->BDCR |= 1<<15;
下面正式看RTC的寄存器,先從低位控制寄存器開始CRL

位15:6 ?保留,被硬件強制為0。
位5 RTOFF:RTC操作關閉(RTC operation OFF) ?位5?
RTC模塊利用這位來指示對其寄存器進行的最后一次操作的狀態,指示操作是否完成。若此位
為’0’,則表示無法對任何的RTC寄存器進行寫操作。此位為只讀位。
0:上一次對RTC寄存器的寫操作仍在進行;?
1:上一次對RTC寄存器的寫操作已經完成。
位4 CNF:配置標志(Configuration flag) ?位4?
此位必須由軟件置’1’以進入配置模式,從而允許向RTC_CNT、RTC_ALR或RTC_PRL寄存器
寫入數據。只有當此位在被置’1’并重新由軟件清’0’后,才會執行寫操作。
0:退出配置模式(開始更新RTC寄存器);
1:進入配置模式。
位3?RSF:寄存器同步標志(Registers synchronized flag)
每當RTC_CNT寄存器和RTC_DIV寄存器由軟件更新或清’0’時,此位由硬件置’1’。在APB1復位
后,或APB1時鐘停止后,此位必須由軟件清’0’。要進行任何的讀操作之前,用戶程序必須等待
這位被硬件置’1’,以確保RTC_CNT、RTC_ALR或RTC_PRL已經被同步。
0:寄存器尚未被同步;
1:寄存器已經被同步。
位2 OWF:溢出標志(Overflow flag) ?位2?
當32位可編程計數器溢出時,此位由硬件置’1’。如果RTC_CRH寄存器中OWIE=1,則產生中
斷。此位只能由軟件清’0’。對此位寫’1’是無效的。
0:無溢出;
1:32位可編程計數器溢出。
位1 ALRF:鬧鐘標志(Alarm flag) ?位1?
當32位可編程計數器達到RTC_ALR寄存器所設置的預定值,此位由硬件置’1’。如果RTC_CRH
寄存器中ALRIE=1,則產生中斷。此位只能由軟件清’0’。對此位寫’1’是無效的。
0:無鬧鐘;
1:有鬧鐘。
位0 SECF:秒標志(Second flag) ?位0?
當32位可編程預分頻器溢出時,此位由硬件置’1’同時RTC計數器加1。因此,此標志為分辨率可
編程的RTC計數器提供一個周期性的信號(通常為1秒)。如果RTC_CRH寄存器中SECIE=1,則
產生中斷。此位只能由軟件清除。對此位寫’1’是無效的。
0:秒標志條件不成立;
1:秒標志條件成立。
感覺CRL更像SR,我在想為什么他有點功能不放到SR的里面呢?
好吧,CRL里的功能說的很清楚,看著不會有什么異議,我這里就不解釋了,直接掠過,包括CRH。

在RTC計數器寄存器里面和RTC鬧鐘寄存器里面有這么一段話
RTC核有一個32位可編程的計數器,可通過兩個16位的寄存器訪問。計數器以預分頻器產生的
TR_CLK時間基準為參考進行計數。RTC_CNT寄存器用來存放計數器的計數值。他們受
RTC_CR的位RTOFF寫保護,僅當RTOFF值為’1’時,允許寫操作。在高或低寄存器
(RTC_CNTH或RTC_CNTL)上的寫操作,能夠直接裝載到相應的可編程計數器,并且重新裝載
RTC預分頻器。當進行讀操作時,直接返回計數器內的計數值(系統時間)。
當可編程計數器的值與RTC_ALR中的32位值相等時,即觸發一個鬧鐘事件,并且產生RTC鬧鐘
中斷。此寄存器受RTC_CR寄存器里的RTOFF位寫保護,僅當RTOFF值為’1’時,允許寫操作。
所以我們在配置RTC_CNTx RTC_ALRx 寄存器時,不行把RTOFF寄存器置為1,當寫完之后將CNT設為1,即進入配置模式,等待RTOFF配置完成,即RTOFF自動置為0,才完成對CNTx和ALRx兩個寄存器進行修改!
為了實現計數的時間間隔,我們要對RTC預分頻裝載寄存器進行配置
我們需要1s鐘計時一次,而我們用的是LSE 32KHz的振蕩器,所以我們需要配置的分頻器是?

可以看出我們只需讓RTC_PRLL = 0x7fff 即 32767即可得到1s的周期
當然我們需要兩秒的話那就是0xffff了。
這樣,整個就配置完成了,下面附上我的代碼,大家可以研究下!
~~~
#include <stm32f10x.h>
#include "init.h"
#include "usart.h"
#define RTC_CF 0x01CD //Define RTC Config Flag
int rtc_init()
{
u8 temp = 0;
if(BKP->DR1 != RTC_CF)
{
RCC->APB1ENR |= 1<<28; //Power Interface Clock Enable
RCC->APB1ENR |= 1<<27; //Backup Interface Clock Enable
PWR->CR |= 1<<8; //Disable backup domain write protection
RCC->BDCR |= 1<<16;
RCC->BDCR &= ~(1<<16);
RCC->BDCR |= 1<<0;
while((!(RCC->BDCR&1<<1))&&(temp++)<250)
delay_ms(10);
if(temp>=250)return -1;
RCC->BDCR |= 1<<8;
RCC->BDCR |= 1<<15;
while(!(RTC->CRL & (1<<5)));
while(!(RTC->CRL & (1<<3)));
RTC->CRH |= 1<<0;
while(!(RTC->CRL & (1<<5)));
/* Config Time */
RTC->CRL |= 1<<4;
RTC->PRLH = 0;
RTC->PRLL = 32767;
RTC->CNTH = 0;//Config time
RTC->CNTL = 0;
RTC->ALRH = 0;
RTC->ALRL = 20;
RTC->CRL &= ~(1<<4);
while(!(RTC->CRL & (1<<5)));
BKP->DR1 = RTC_CF;
}
else{
while(!(RTC->CRL & (1<<3)));
RTC->CRH |= 1<<0;
while(!(RTC->CRL & (1<<5)));
}
init_interrupt(2,3,3,2);
rs232_send_int(RTC->CNTL);
return 0;
}
void RTC_IRQHandler(void)
{
rs232_send_str("INTER\n",6);
if(RTC->CRL & (1<<0))
{
rs232_send_int(RTC->CNTL);
rs232_send_byte('\n');
}
if(RTC->CRL & (1<<1))
{
RTC->CRL |= 1<<4;
RTC->CNTL = 1;
RTC->CRL &= ~(1<<4);
rs232_send_str("Time==>\n",8);
}
RTC->CRL &= ~(7<<0);//Clear all interrupt flag
while(!(RTC->CRL & (1<<5)));
}
~~~
多謝各位指導!
- 前言
- 【菜鳥入門】stm32的第一個程序--LED
- 【菜鳥入門】stm32 之 掃描按鍵
- 【菜鳥入門】stm32 之 中斷按鍵
- 【菜鳥入門】stm32 之 USART
- 【菜鳥入門】stm32 之 iic
- 【菜鳥入門】stm32 之 eeprom
- 【菜鳥入門】stm32 之 pwm
- 【菜鳥入門】stm32 之 ADC 模數轉換
- 【菜鳥入門】stm32 之 實時時鐘
- 【菜鳥入門】stm32 之 DMA
- 【菜鳥入門】stm32 之 DAC
- 【STM庫應用】stm32 之 USART
- 中斷源去抖辦法
- stm32 啟動代碼應用技巧
- 【STM庫應用】stm32 之 IIC應用
- 【STM庫應用】stm32 之 中斷按鍵初始化(注意事項)
- 關于結構體初始化
- 【STM庫應用】stm32 之 TIM (詳解一 通用定時器)
- 【STM庫應用】stm32 之 TIM (詳解二 脈沖寬度、周期測量)
- 【stm32庫應用】SD驅動移植(基于SDIO外設)
- SD卡fat文件系統移植
- stm32 DMA初始化選項研究
- stm32 靈活靜態存儲控制器(FSMC)(NORFLASH\PSRAM)
- 【stm32+uC/OS-II】ucosii移植簡單詳細步驟
- STM32 加入調試信息來調試代碼
- NRF24L01 無線通信模塊使用