STM32的系統(tǒng)時(shí)鐘的配置的代碼的講解
ST公司默認(rèn)是將系統(tǒng)時(shí)鐘配置到72MHZ。
以下的七個(gè)步奏是設(shè)置系統(tǒng)時(shí)鐘的函數(shù),該函數(shù)截取自庫(kù)文件system_stm32f10x.c。
將互聯(lián)型相關(guān)的代碼刪掉便于分析,并標(biāo)上了序號(hào),總共七個(gè)步奏,這個(gè)順序也是系統(tǒng)時(shí)鐘配置的
的步奏,通過直接操作寄存器,主要相關(guān)的寄存器,主要是時(shí)鐘配置寄存器RCC_CFGR,具體位的設(shè)置
和bit的含義,參考STM32參考手冊(cè)
static void SetSysClockTo72(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
// SYSCLK, HCLK, PCLK2 and PCLK1 配置過程的順序
//(1)使能 HSE(高速外部時(shí)鐘),并等待 HSE 穩(wěn)定
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
// 等待 HSE 啟動(dòng)穩(wěn)定,并做超時(shí)處理
// Wait till HSE is ready and if Time out is reached exit
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
//HSE啟動(dòng)成功,則繼續(xù)往下處理
if (HSEStatus == (uint32_t)0x01)
{
// 使能FLASH預(yù)存取緩沖區(qū)
FLASH->ACR |= FLASH_ACR_PRFTBE;
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
//(2)設(shè)置AHB、APB2、APB1預(yù)分頻因子
// HCLK = SYSCLK
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
// PCLK2 = HCLK
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
//PCLK1 = HCLK
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
// (3)設(shè)置PLL的時(shí)鐘來源,設(shè)置PLL的倍頻因子, PLLCLK = HSE * 9 = 72 MHz
RCC->CFGR &= (uint32_t)((uint32_t)
~(RCC_CFGR_PLLSRC
| RCC_CFGR_PLLXTPRE
| RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE
| RCC_CFGR_PLLMULL9);
//(4) 使能 PLL
RCC->CR |= RCC_CR_PLLON;
//(5) 等待PLL的穩(wěn)定
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
// (6)選擇PLL作為時(shí)鐘來源
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
//(7)讀取時(shí)鐘切換狀態(tài),確保PLLCLK被選為系統(tǒng)時(shí)鐘
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
}
else
{ // 如果HSE啟動(dòng)失敗,用戶可以再這里添加錯(cuò)誤代碼出來
}
}
#endif
系統(tǒng)是時(shí)鐘配置代碼學(xué)習(xí)中遇到的基礎(chǔ)的函數(shù)定義、雜文集。。
一、__IO uint32_t (很早之前遇到的一個(gè)問題,記錄一下
庫(kù)文件的定義如下:
#define __IO volatile
可以看出 __IO 其實(shí)就是 volatile 的意思。
volatile 的作用就是指示編譯器不要因優(yōu)化而省略此指令,必須每次都直接讀寫其值。
寫一段測(cè)試代碼如下
u8 test;
test = 1;
test = 2;
test = 3;
設(shè)置優(yōu)化級(jí)別中級(jí)
運(yùn)行后test會(huì)被直接取值為3 只有最后一個(gè)語(yǔ)句被編譯
如用volatile
volatile u8 test;
test = 1;
test = 2;
test = 3;
則所有語(yǔ)句都會(huì)被編譯。test先后被設(shè)置成1、2、3
由此可以看出這個(gè)作用在IO操作,寄存器操作,特殊變量,多線程變量讀寫都是很重要。
二、(uint32_t)0x01
uint32_t 是系統(tǒng)定義的 typedef uint32_t unsigned int
(uint32_t)0x01
的作用就是將0x01裝換成32位的進(jìn)行操作。