今天學習了野火的STM32教程學會了如何設置STM32的時鐘頻率,步驟比較詳細,也很容易理解,就是視頻教程不能跳著看,只能一節節的看,不然會知識不連貫,造成有些知識不理解,連續著看還是沒有什么難度的。
我把怎么設置系統時鐘的步驟總結一下吧:
第一步:將RCC的所有寄存器都恢復成默認值
第二步:使能HSE
第三步:判斷HSE啟動是否成功
? ? ? ? HSE啟動成功的話:
? ? ? ? {
? ? ? ? ? ? ? ? 1:使能預取緩沖區
? ? ? ? ? ? ? ? 2:預取緩沖區等待周期2
? ? ? ? ? ? ? ? 3:設置AHB的時鐘 1分頻? ?72M
? ? ? ? ? ? ? ? 4:APB1的時鐘設置 2分頻 36M
? ? ? ? ? ? ? ? 5:APB2的時鐘設置 1分頻 72M
? ? ? ? ? ? ? ? 6:鎖相環時鐘配置:來源HSE1分頻,倍頻因子9倍(也可以改成自己想要的倍數,超頻就改這里)
? ? ? ? ? ? ? ? 7:使能鎖相環
? ? ? ? ? ? ? ? 8:等待鎖相環穩定
? ? ? ? ? ? ? ? 9:系統時鐘選擇鎖相環時鐘
? ? ? ? ? ? ? ? 10:等待系統時鐘切換成功
????????}
? ? ? ? HSE啟動不成功:
? ? ? ? {
? ? ? ? ? ? ? ? 寫不成功的代碼。
????????}
*******************************************************************************************************************
按照上面的步驟操作后,系統時鐘就按照我們的標準來設置了。其實這個操作沒有什么太大的必要性,因為系統會自動為我們配置好的,研究這個過程是為了更深一步的了解STM32的工作步驟。能叫自己的腦子里的思路更加清晰。
下面我就把源碼發出來,自己研究吧!
RCC.c文件:
#include "RCC.h" // Device header/*HSE時鐘設置函數(傳入倍頻因子)*/
void HSE_SetSysClk(uint32_t RCC_PLLMul_x)
{ErrorStatus HSEStatus; //定義一個HSE啟動成功與否的標志位變量RCC_DeInit(); //RCC所有寄存器恢復成默認值RCC_HSEConfig(RCC_HSE_ON);//使能HSEHSEStatus = RCC_WaitForHSEStartUp();//HSE啟動是否成功的返回值if(HSEStatus == SUCCESS){FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//使能預取緩沖區 在《STM32F10xxx閃存編程》的3.1節 的FLASH_ACR 的 位4:PRFTBE 取值1 :啟用預取緩沖區FLASH_SetLatency(FLASH_Latency_2); //預取緩沖區等待周期2RCC_HCLKConfig(RCC_SYSCLK_Div1); // AHB的時鐘設置 1分頻RCC_PCLK1Config(RCC_HCLK_Div2); // APB1的時鐘設置 2分頻RCC_PCLK2Config(RCC_HCLK_Div1); // APB2的時鐘設置 1分頻RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_x); //鎖相環配置 時鐘來源與倍頻因子 16倍頻 8*16=128MRCC_PLLCmd(ENABLE); //使能鎖相環//等待鎖相環穩定// RCC_GetFlagStatus(uint8_t RCC_FLAG); //RCC的標志位while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) != SET);//選擇鎖相環時鐘RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); //時鐘源選擇while( RCC_GetSYSCLKSource() != 0x08 ); //如果不等于0x08就是沒有切換成功就while等待}else{/* 如果HSE啟動失敗,用戶可以在這里添加處理錯誤的代碼 */}}//配置PA8為時鐘輸出
void MCO_GPIO_Config(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);
}
RCC.h文件:
#ifndef __RCC_H
#define __RCC_H#include "stm32f10x.h" // Device headervoid HSE_SetSysClk(uint32_t RCC_PLLMul_x);void MCO_GPIO_Config(void);#endif /*__RCC_H*/
main.c文件:
#include "stm32f10x.h" // Device header
#include "led.h"
#include "RCC.h" void Delay(uint32_t val)
{while(val){val--;}
}int main(void)
{LED_Init();//HSE_SetSysClk(RCC_PLLMul_16); //設置時鐘頻率為16倍頻 8*16=128M 超頻MCO_GPIO_Config();RCC_MCOConfig(RCC_MCO_PLLCLK_Div2);//MCO輸出A8口輸出鎖相環時鐘2分頻,用示波器可以測量A8口的頻率while(1){LED(ON);Delay(0xfffff);LED(OFF);Delay(0xfffff);}
}
由于我沒有示波器,所以就只能用個led燈看看閃爍的速度來判斷是不是超頻了,所以還有個led的模塊:
led.c文件:
#include "led.h" // Device headervoid LED_Init(void)
{RCC_APB2PeriphClockCmd(GPIO_CLK, ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStruct.GPIO_Pin = GPIO_PIN;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOx, &GPIO_InitStruct);}
led.h文件:
#ifndef __LED_H
#define __LED_H#include "stm32f10x.h" // Device header#define GPIOx GPIOB
#define GPIO_PIN GPIO_Pin_0
#define GPIO_CLK RCC_APB2Periph_GPIOB#define ON 1
#define OFF 0#define LED(x) if(x)\GPIO_ResetBits(GPIOx, GPIO_PIN);\else \GPIO_SetBits(GPIOx, GPIO_PIN);void LED_Init(void);#endif