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