Stm32時鐘分析
最后:配置SW,以及SWS。表示啟用HIS作為系統(tǒng)時鐘。
到這一步,經(jīng)過分析得知,RCC->CFGR &= 0xF8FF0000;主要是用來配置ahb等各個分頻器的設(shè)置,以及將片內(nèi)時鐘作為系統(tǒng)內(nèi)部時鐘。
(6)
RCC->CR &= 0xFEF6FFFF;
通過分析CR寄存器可以看出,該寄存器主要涉及三個時鐘PLL,CSS,HSE。
(7)
RCC->CR &= 0xFFFBFFFF;這一步有什么作用呢?查詢數(shù)據(jù)手冊57頁可知,外部時鐘源HSE有兩種模式,HSEBYP設(shè)置為0時,是選擇外部晶體作為外部時鐘源這種時鐘更加精準(zhǔn),當(dāng)然也是和外部電路有關(guān)的。當(dāng)然因為第(6)步已經(jīng)設(shè)置了HSEON關(guān)閉了,所以這一步才可自由設(shè)置HSEBYP。
(8)
RCC->CFGR &= 0xFF80FFFF;
注意:在這一部中可能會有這樣的疑問:
RCC->CFGR &= 0xFF80FFFF;
PLLSRC=0 HSI振蕩器時鐘經(jīng)2分頻后作為PLL輸入時鐘
PLLXTPRE=0,HSE分頻器作為PLL輸入,HSE不分頻
這樣不沖突嗎?
答案是:以最后配置為準(zhǔn),就是最后一次配置會改變前一次的配置,所以說以最后一次配置為準(zhǔn)。
也就是說后文還有其他代碼對其進(jìn)行定義。那干嘛還要怎么重復(fù)配置呢?
有時候是有用的。比如你想讓stm32超頻一會,然后又恢復(fù)正常運行,這就有用了。
(9)
RCC->CIR = 0x00000000;
(10)
#ifndef VECT_TAB_RAM
#else
#endif
下面對該函數(shù)分析:
//函數(shù)功能:設(shè)置向量表偏移地址
//NVIC_VectTab:基址
//Offset:偏移量
void MY_NVIC_SetVectorTable(u32 NVIC_VectTab, u32 Offset)
{
}
前面兩行是用來檢查參數(shù)合法性,這里不作分析。重點看第三行
配置這個向量表有什么用?相見cortexm3權(quán)威指南113頁向量表的解釋
這里
#define NVIC_VectTab_RAM
#define NVIC_VectTab_FLASH
Offset的值為0x0,為偏移地址,地址必須能被64 * 4 = 256整除,具體請看權(quán)威手冊113頁
SCB->VTOR = NVIC_VectTab|(Offset & (u32)0x1FFFFF80);//設(shè)置NVIC的向量表偏移寄存器。
既然是設(shè)置NVIC的向量表偏移量,為什么還要和NVIC_VectTab相或呢。只設(shè)置OFFSET不就可以了嗎,另外VTOR設(shè)置只有BIT【28:7】有作用啊,相或以后也放不下這么多位吧?
這個是基址。
那個7~28的,你能定義一個28位的數(shù)據(jù)出來嘛?
VTOR設(shè)置只有BIT【28:7】,你把(u32)0x1FFFFF80二進(jìn)制看看是不是【28:7】。
然后再看下面一段話:
地址必須能被64*4=256整除,從而合法的起始地址可以是:0x0, 0x100, 0x200等。
答案:cortex-m3權(quán)威指南上介紹
下面我們回到例說stm32這本書61頁的Stm32_Clock_Init()函數(shù):
經(jīng)過上面配置完畢后,下面開始配置外部時鐘。
Ministm32開發(fā)板目前的實都是采用高速外部時鐘作為時鐘源,在經(jīng)過MYRCC_Deinit()先將外部時鐘源關(guān)閉,然后在cfgr重新配置之后,下面就準(zhǔn)備開啟高速外部時鐘。
(11)
(12)
While(!(RCC->CR>>17));
對此,原子哥也說了寫成(RCC-CR>>17)&0X01比較合適,但我感覺RCC-CR>>17是不準(zhǔn)確的,比方說如果第十八位是1,那么右移17位后不管時鐘是否就緒,表達(dá)式“RCC-CR>>17”的結(jié)果始終為真,這樣while(!(RCC-CR>>17))不就沒有意義了嗎?所以寫成(RCC-CR>>17)&0X01才是最準(zhǔn)確的
)
(13)
RCC->CFGR = 0x00000400;
(14)
PLL -=2;
RCC->CFGR = PLL <<18;
設(shè)置PLL 9倍頻
這里還涉及到了一個問題,如下
其實,這里今天林妹妹問了一個比較專業(yè)的問題,那就是PLL是一個u8的數(shù)據(jù)類型,為什么在這里可以右移18位呢?不是早超出了么?其實,我們看看匯編代碼就明白了,匯編代碼如下: 219: RCC->CFGR|=PLL<<18; //設(shè)置PLL值
(15)
//具體見《STM32閃存編程》
(16)
RCC->CR|=0x01000000;
(17)
while(!((RCC->CR>>25)&0x01));
(18)
RCC->CFGR |= 0x00000002;
(19)
Unsigned char Temp = 0;
While(Temp!=0x02)
{
}
其實這段代碼就是判斷SWS,等待系統(tǒng)時鐘成功轉(zhuǎn)為PLL時鐘。
結(jié)合上面的分析已經(jīng)明了STM32時鐘一個始終配置過程,主要流程圖如下:
其實個人感覺不用想mini32中自帶例程配置有一些沒有必要,所以自己改動了一些,發(fā)現(xiàn)在跑馬燈程序中也能運行,目前只在跑馬燈程序中試驗過:
第一步:
第二步:
第三步:關(guān)閉所有外設(shè)時鐘
為什么要這步因為在配置cfgr以及cr等寄存器時,一些外設(shè)時鐘要關(guān)閉。
第四步:
第五步:設(shè)置分頻寄存器,配置分頻,使能PLLSRC ON
評論