色婷婷AⅤ一区二区三区|亚洲精品第一国产综合亚AV|久久精品官方网视频|日本28视频香蕉

          新聞中心

          Stm32時鐘分析

          作者: 時間:2016-11-28 來源:網(wǎng)絡(luò) 收藏

          最后:配置SW,以及SWS。表示啟用HIS作為系統(tǒng)時鐘。

          到這一步,經(jīng)過分析得知,RCC->CFGR &= 0xF8FF0000;主要是用來配置ahb等各個分頻器的設(shè)置,以及將片內(nèi)時鐘作為系統(tǒng)內(nèi)部時鐘。

          (6)關(guān)閉HSEON,CSSON,PLLON

          RCC->CR &= 0xFEF6FFFF;

          通過分析CR寄存器可以看出,該寄存器主要涉及三個時鐘PLL,CSS,HSE。

          (7)復(fù)位HSEBYP.

          RCC->CR &= 0xFFFBFFFF;這一步有什么作用呢?查詢數(shù)據(jù)手冊57頁可知,外部時鐘源HSE有兩種模式,HSEBYP設(shè)置為0時,是選擇外部晶體作為外部時鐘源這種時鐘更加精準,當然也是和外部電路有關(guān)的。當然因為第(6)步已經(jīng)設(shè)置了HSEON關(guān)閉了,所以這一步才可自由設(shè)置HSEBYP。

          (8)復(fù)位PLLSRC,PLLXTPRE,PLLMUL and USBPRE

          RCC->CFGR &= 0xFF80FFFF;

          注意:在這一部中可能會有這樣的疑問:

          RCC->CFGR &= 0xFF80FFFF;
          PLLSRC=0 HSI振蕩器時鐘經(jīng)2分頻后作為PLL輸入時鐘
          PLLXTPRE=0,HSE分頻器作為PLL輸入,HSE不分頻
          這樣不沖突嗎?

          答案是:以最后配置為準,就是最后一次配置會改變前一次的配置,所以說以最后一次配置為準。

          也就是說后文還有其他代碼對其進行定義。那干嘛還要怎么重復(fù)配置呢?

          有時候是有用的。比如你想讓stm32超頻一會,然后又恢復(fù)正常運行,這就有用了。

          (9)關(guān)閉所有中斷

          RCC->CIR = 0x00000000;

          (10)配置向量表

          #ifndef VECT_TAB_RAM

          MY_NVIC_SetVectorTable(NVIC_VectTab_RAM,0x0);

          #else

          MY_NVIC_SetVectorTable(NVIC_VextTab_FLASH,0x0);

          #endif

          下面對該函數(shù)分析:

          //函數(shù)功能:設(shè)置向量表偏移地址

          //NVIC_VectTab:基址

          //Offset:偏移量

          void MY_NVIC_SetVectorTable(u32 NVIC_VectTab, u32 Offset)
          {
          //檢查參數(shù)合法性
          assert_param(IS_NVIC_VECTTAB(NVIC_VectTab));
          assert_param(IS_NVIC_OFFSET(Offset));
          SCB->VTOR = NVIC_VectTab|(Offset & (u32)0x1FFFFF80);//設(shè)置NVIC的向量表偏移寄存器
          //用于標識向量表是在CODE區(qū)還是在RAM區(qū)
          }
          前面兩行是用來檢查參數(shù)合法性,這里不作分析。重點看第三行

          配置這個向量表有什么用?相見cortexm3權(quán)威指南113頁向量表的解釋

          這里

          #define NVIC_VectTab_RAM((u32)0x20000000)

          #define NVIC_VectTab_FLASH((u32)0x08000000)

          Offset的值為0x0,為偏移地址,地址必須能被64 * 4 = 256整除,具體請看權(quán)威手冊113頁

          SCB->VTOR = NVIC_VectTab|(Offset & (u32)0x1FFFFF80);//設(shè)置NVIC的向量表偏移寄存器的疑問如下:

          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二進制看看是不是【28:7】。
          然后再看下面一段話:

          在<<權(quán)威指南>>第一百零四頁,有這么一段話:
          NVIC中有一個寄存器,稱為“向量表偏移量寄存器”(在地址0xE000_ED08處),通過修改它的值就能定位向量表。但必須注意的是:向量表的起始地址是有要求的:必須先求出系統(tǒng)中共有多少個向量,再把這個數(shù)字向上增大到是2的整次冪,而起始地址必須對齊到后者的邊界上。例如,如果一共有32個中斷,則共有32+16(系統(tǒng)異常)=48個向量,向上增大到2的整次冪后值為64,因此地址
          地址必須能被64*4=256整除,從而合法的起始地址可以是:0x0, 0x100, 0x200等。
          向量表偏移量寄存器,也就是SCB->VTOR.它的第29位,用來標識向量表是在CODE區(qū)還是RAM區(qū),從而0X1,就是最高3位不去動,這好理解.但是低位,根據(jù)上面這段話的理解,STM32自己有60個中斷,加上CM3的16個,總共有76個中斷,擴大到2的整次冪,那就是128,然后再乘以4,得到512,也就是0X200.根據(jù)這樣計算,合法的偏移地址應(yīng)該是0X0,0X200,0X400,0X600...因此,在此處應(yīng)該&0X1FFF FE00.才對.
          以上是我的理解.實際上確是&0X1FFF FF80;這點,我也有疑問.

          答案:cortex-m3權(quán)威指南上介紹bit28-7為向量表的起始地址。所以低7位沒有用到,所以&0X80,為的就是將低七位清零。但這里寫&0X1FFF FE00,也能達到清零的目的。至于地址必須是512的整數(shù)只要offset這個參數(shù)注意就可以了。

          下面我們回到例說stm32這本書61頁的Stm32_Clock_Init()函數(shù):

          經(jīng)過上面配置完畢后,下面開始配置外部時鐘。

          Ministm32開發(fā)板目前的實都是采用高速外部時鐘作為時鐘源,在經(jīng)過MYRCC_Deinit()先將外部時鐘源關(guān)閉,然后在cfgr重新配置之后,下面就準備開啟高速外部時鐘。

          (11)RCC->CR |= 0x00010000;外部高速時鐘使能HSEON,前面說過以最后一次設(shè)置為準,所以自打這一步開始HSE作為了外部時鐘。

          (12)等待外部時鐘是否就緒

          While(!(RCC->CR>>17));(其實這一步的作用和while(RCC->CR&(u32)(1<<17));是一樣的,因為在MYRCC_Deinit()中的18位至31位全為0了,當然在論壇中http://www.openedv.com/posts/list/1943.htm第23樓也承認While(!(RCC->CR>>17)這樣寫有點輕率,23樓這樣寫道

          對此,原子哥也說了寫成(RCC-CR>>17)&0X01比較合適,但我感覺RCC-CR>>17是不準確的,比方說如果第十八位是1,那么右移17位后不管時鐘是否就緒,表達式“RCC-CR>>17”的結(jié)果始終為真,這樣while(?。≧CC-CR>>17))不就沒有意義了嗎?所以寫成(RCC-CR>>17)&0X01才是最準確的

          )

          (13)配置APB1/2=DIV2和AHB = DIV1

          RCC->CFGR = 0x00000400;

          (14)設(shè)置PLL分頻

          PLL -=2;

          RCC->CFGR = PLL <<18;

          設(shè)置PLL 9倍頻

          這里還涉及到了一個問題,如下

          其實,這里今天林妹妹問了一個比較專業(yè)的問題,那就是PLL是一個u8的數(shù)據(jù)類型,為什么在這里可以右移18位呢?不是早超出了么?其實,我們看看匯編代碼就明白了,匯編代碼如下: 219: RCC->CFGR|=PLL<<18; //設(shè)置PLL值2~16 0x08000618 4608 MOV r0,r1 0x0800061A 6840 LDR r0,[r0,#0x04] 0x0800061C EA404084 ORR r0,r0,r4,LSL #18 0x08000620 6048 STR r0,[r1,#0x04]可以看到,這個移位操作,是在R0和R1里面進行的,r0,r1均是32位的寄存器,所以,這里的移位操作并不會產(chǎn)生錯誤(結(jié)果是賦值給32位的寄存器:RCC->CFGR).

          (15)FLASH->ACR |= 0x32 //flash 2個延時周期。FLASH->ACR|=0x32是為了使頻率匹配,

          //具體見《STM32閃存編程》

          (16)打開PLLON

          RCC->CR|=0x01000000;

          (17)等待PLL鎖定

          while(!((RCC->CR>>25)&0x01));

          (18)PLL作為系統(tǒng)時鐘

          RCC->CFGR |= 0x00000002;

          (19)等待PLL作為系統(tǒng)時鐘設(shè)置成功

          Unsigned char Temp = 0;

          While(Temp!=0x02)

          {

          Temp = RCC->CFGR>>2;

          Temp &= 0x03;

          }

          其實這段代碼就是判斷SWS,等待系統(tǒng)時鐘成功轉(zhuǎn)為PLL時鐘。

          結(jié)合上面的分析已經(jīng)明了STM32時鐘一個始終配置過程,主要流程圖如下:

          其實個人感覺不用想mini32中自帶例程配置有一些沒有必要,所以自己改動了一些,發(fā)現(xiàn)在跑馬燈程序中也能運行,目前只在跑馬燈程序中試驗過:

          第一步:

          RCC->APB1RSTR = 0x00000000;//復(fù)位結(jié)束

          RCC->APB2RSTR = 0x00000000;

          第二步:

          RCC->AHBENR = 0x00000014;//睡眠模式閃存和SRAM時鐘使能.其他關(guān)閉.

          第三步:關(guān)閉所有外設(shè)時鐘

          RCC->APB2ENR = 0x00000000; //外設(shè)時鐘關(guān)閉.

          RCC->APB1ENR = 0x00000000;

          為什么要這步因為在配置cfgr以及cr等寄存器時,一些外設(shè)時鐘要關(guān)閉。

          第四步:

          RCC->CR &= 0xFEF2FFFF;//該補的主要作用是開啟內(nèi)部HSION,且關(guān)閉HSE,CSS,PLLON

          第五步:設(shè)置分頻寄存器,配置分頻,使能PLLSRC ON



          關(guān)鍵詞: Stm32時鐘分

          評論


          技術(shù)專區(qū)

          關(guān)閉