STM32 時鐘設置

時鐘設置

時鐘樹介紹

有以下三種時鐘可以作爲系統時鐘(SYSCLK):

  • HSI 振盪器時鐘
  • HSE 振盪器時鐘
  • PLL 時鐘

時鐘樹如下:
在這裏插入圖片描述

  • OSC_OUT 和 OSC_IN 爲外部晶振的接口,爲 HSE(高速) 提供振盪源,接 4 -16 MHz 的晶振;

  • OSC32_OUT 和 OSC32_IN 爲外部晶振的接口,爲 LSE(低速) 提供振盪源,接 32.768 kHz 的晶振。其爲看門狗時鐘 (IWDGCLK) 提供動力;

  • LSI RC 爲內部低速振盪器,頻率爲 40kHz;

  • RTCCLK (Real Time Clock) 由 HSE/128LSELSI 提供動力;

  • PLLXTPRE 爲預分頻選擇器,主要選擇 不分頻/2,它和 HSI RC 8MHz(內部高速振盪器)的 /2 共同接入到了 PLLSRC ,由其選擇使用外部時鐘 HSE 還是內部時鐘 HSI,再將時鐘信號輸入到 PLLMUL

  • HSI RC 8MHz 不但有上述作用,flash 編程接口也是由其驅動的;

  • PLLMUL 爲倍頻器,最高倍頻到 16,主要倍頻 HSIHSE,得到 PLLCLK,其可用作 USBCLK 的驅動源,一般預分頻到 48 MHz;

  • CSS

  • SYSCLK 主要由 HSEHSIPLLCLK 提供,最大頻率爲 72 MHz;

  • I2S3I2S2 都是由 SYSCLK 驅動的;

  • SYSCLK 主要爲 AHB 總線提供驅動:
    在這裏插入圖片描述

上圖可以看到 AHB 系統總線主要與 SDIORCCAPB1APB2 交互,且爲它們提供時鐘驅動。APB2APB1 兩個總線連接上圖的片上外設;

  • SYSCLK 會經過 AHB 預分頻器(/1,…,/512),從而爲其他總線提供時鐘:
  1. HCLK 提供時鐘,頻率最高爲 72 MHz。HCLKAHB BUScorememoryDMA 等;
  2. AHB/8 至 Cortex 系統定時器;
  3. AHB/1 也可直接爲 FCLK Cortex 自由運行定時器提供驅動;
  4. APB1 總線的最大頻率爲 36 MHz,由此需要經由 APB1 預分頻器分頻(/1,2,4,8,16)。再由外設時鐘使能得到 PCLK1 至 APB1 總線上的外設;
  5. APB2 總線的最大頻率爲 72 MHz,同樣需要經由 APB2 預分頻器分頻(/1,2,4,8,16)。再由外設時鐘使能得到 PCLK2 至 APB2 總線上的外設;
  6. APB2 總線的時鐘頻率在給 ADC 驅動時,需要先分頻(/2,4,6,8),ADCCLK 最大頻率爲 14 MHz;
  7. AHB/2 經由外設時鐘使能(HCLK/2),至 SDIO AHB 接口;
  • MCO(主時鐘輸出)由以下 4 個時鐘源以供選擇:
    • PLLCLK
    • HSI
    • HSE
    • SYSCLK
#include <stm32f10x.h>

// 設置向量表偏移地址
//NVIC_VectTab: 基址
//Offset: 偏移量		 
void MY_NVIC_SetVectorTable(u32 NVIC_VectTab, u32 Offset){ 	   	 
    //設置NVIC的向量表偏移寄存器,用於標識向量表在CODE區還是RAM區
	SCB->VTOR = NVIC_VectTab|(Offset & (u32)0x1FFFFF80);
}


// 系統初始的配置:主要用來配置向量表
void MYRCC_DeInit(void) {
    RCC->APB1RSTR = 0x0000 0000;  // No effect
    RCC->APB2RSTR = 0x0000 0000;
    
    // 初始是睡眠狀態,打開閃存接口電路時鐘使能(FLITFEN)和SRAM時鐘使能(SRAMEN)
    RCC->AHBENR  = 0x0000 0014;
    RCC->APB2ENR = 0x0000 0000;
    RCC->APB1ENR = 0x0000 0000;
    
    // 使能內部高速時鐘HSI開始工作
    RCC->CR |= RCC_CR_HSION;   
    
    // datasheet's note:先配置,再控制
    // 配置RCC(復位SW[1:0],HPRE[3:0],PPRE1[2:0],PPRE2[2:0],ADCPRE[1:0],MCO[2:0]):SYSClock<--HSI(時鐘樹的SW處), SYSClock不分頻,APB1和APB2也都不分頻,ADC默認/2,PLL時鐘源選擇HSE(現在用不到), MCO:No Clock¸
    RCC->CFGR &= 0xF8FF 0000;
    // 關閉 HSE、PLL、CSS 使能
    RCC->CR &= 0xFEF6FFFF;
    // 在HSE未使能時,設置HSE晶振沒有旁路
    RCC->CR &= 0xFFFBFFFF;
    // 復位 PLLSRC, PLLXTPRE, PLLMUL[3:0] and USBPRE 
    RCC->CFGR &= 0xFF80FFFF;
    // 清除所有中斷標誌
    RCC->CIR = 0x00000000; 
    
	// 配置向量表				  
#ifdef  VECT_TAB_RAM
	MY_NVIC_SetVectorTable(0x20000000, 0x0);
#else   
	MY_NVIC_SetVectorTable(0x08000000,0x0);
#endif
}

// stm32時鐘的初始化
void Stm32_Clock_Init(u8 pll){
    // 復位並配置向量表
	MYRCC_DeInit();
    // 使能HSEON
    RCC->CR |= RCC_CR_HSEON;
    // 等待 HSE 使能就緒:HSERDY == 1
    while(!(RCC->CR>>17));
    // APB1 = DIV2; APB2 = DIV1; AHB = DIV1
    RCC->CFGR = (RCC_CFGR_PPRE1_DIV2 + RCC_CFGR_PPRE2_DIV1 + RCC_CFGR_HPRE_DIV1); 
    // PLLMUL[21:18] ====> 0000: PLL Clock x 2,所以要 -2.
    PLL -= 2;	
    // 設置倍頻,PLL = 9 即倍頻到72MHz
    RCC->CFGR |= PLL<<18;
    // PLL Clock <--- HSE
    RCC->CFGR |= RCC_CFGR_PLLSRC;
    
    // ?? FLASH 兩個延時週期 
    FLASH->ACR|=0x32;
    
    // 使能PLL時鐘
    RCC->CR |= RCC_CR_PLLON;
    // 等待PLL時鐘就緒:PLLRDY == 1
    while(!(RCC->CR>>25));
    // 設置 PLL 爲 SYSCLK
    RCC->CFGR |= RCC_CFGR_SW_PLL;
    // 等待SYSCLK設置就緒:SWS == 10 -- PLL
	while(temp!=0x02)     
	{   
		temp = RCC->CFGR>>2;
		temp &= 0x03;
	}
}
發佈了47 篇原創文章 · 獲贊 52 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章