STM32学习之总线与时钟
前言
上一篇博客復(fù)習(xí)了C語言,這一篇博客主要是學(xué)習(xí)STM32F407中的總線與時鐘,這一部分對計算機組成原理的知識有一定的要求,
這一部分極其枯燥,但是十分重要,望仔細學(xué)習(xí)
學(xué)習(xí)資料來自:STM32F407最小系統(tǒng)板開發(fā)指南-庫函數(shù)版本_V1.1.pdf
正點原子,感謝原子哥的開源奉獻
正點原子資料下載中心
STM32單片機學(xué)習(xí)資料均來自 正點原子 ,僅用于學(xué)習(xí),如有侵權(quán)請聯(lián)系我刪除
本博客內(nèi)容原創(chuàng),創(chuàng)作不易,轉(zhuǎn)載請注明
本文鏈接
個人博客:https://ronglin.fun/?p=115
PDF鏈接:見博客網(wǎng)站
CSDN: https://blog.csdn.net/RongLin02/article/details/121308080
總線
總線
STM32F4 的總線架構(gòu)比 51 單片機就要強大很多了。
STM32F4 總線架構(gòu)的知識可以在《STM32F4XX 中文參考手冊》第二章有講解,這里我們也把這一部分知識抽取出來講解,是為了大家在學(xué)習(xí) STM32F4 之前對系統(tǒng)架構(gòu)有一個初步的了解。
這里的內(nèi)容基本也是從中文參考手冊中參考過來的,讓大家能通過我們手冊也了解到,免除了到處找資料的麻煩吧。
如果需要詳細深入的了解 STM32 的系統(tǒng)架構(gòu),還需要多看看《STM32F4XX 中文參考手冊》或者在網(wǎng)上搜索其他相關(guān)資料學(xué)習(xí)。
我們這里所講的 STM32F4 系統(tǒng)架構(gòu)主要針對的 STM32F407 系列芯片。
架構(gòu)圖
首先我們看看STM32 的總線架構(gòu)圖:
主系統(tǒng)由 32 位多層 AHB 總線矩陣構(gòu)成。
總線矩陣用于主控總線之間的訪問仲裁管理。仲裁采取循環(huán)調(diào)度算法。總線矩陣可實現(xiàn)以下部分互聯(lián):
八條主控總線是:
- Cortex-M4 內(nèi)核 I 總線, D 總線和 S 總線;
- DMA1 存儲器總線, DMA2 存儲器總線;
- DMA2 外設(shè)總線;
- 以太網(wǎng) DMA 總線;
- USB OTG HS DMA 總線;
七條被控總線: - 內(nèi)部 FLASH ICode 總線;
- 內(nèi)部 FLASH DCode 總線;
- 主要內(nèi)部 SRAM1(112KB)
- 輔助內(nèi)部 SRAM2(16KB);
- 輔助內(nèi)部 SRAM3(64KB) (僅適用 STM32F42xx 和 STM32F43xx 系列器件);
- AHB1 外設(shè) 和 AHB2 外設(shè);
- FSMC;
功能講解
下面我們具體講解一下圖中幾個總線的知識。
此總線用于將 Cortex-M4 內(nèi)核的指令總線連接到總線矩陣。內(nèi)核通過此總線獲取指令。此總線訪問的對象是包括代碼的存儲器。
此總線用于將 Cortex-M4 數(shù)據(jù)總線和 64KB CCM 數(shù)據(jù) RAM 連接到總線矩陣。內(nèi)核通過此總線進行立即數(shù)加載和調(diào)試訪問。
此總線用于將 Cortex-M4 內(nèi)核的系統(tǒng)總線連接到總線矩陣。此總線用于訪問位于外設(shè)或 SRAM 中的數(shù)據(jù)。
此總線用于將 DMA 存儲器總線主接口連接到總線矩陣。DMA 通過此總線來執(zhí)行存儲器數(shù)據(jù)的傳入和傳出。
此總線用于將 DMA 外設(shè)主總線接口連接到總線矩陣。DMA 通過此總線訪問 AHB 外設(shè)或執(zhí)行存儲器之間的數(shù)據(jù)傳輸。
此總線用于將以太網(wǎng) DMA 主接口連接到總線矩陣。以太網(wǎng) DMA通過此總線向存儲器存取數(shù)據(jù)。
此總線用于將 USB OTG HS DMA 主接口連接到總線矩陣。USB OTG HS DMA 通過此總線向存儲器加載/存儲數(shù)據(jù)。
對于系統(tǒng)架構(gòu)的知識,在剛開始學(xué)習(xí) STM32 的時候只需要一個大概的了解,大致知道是個什么情況即可。對于尋址之類的知識,這里就不做深入的講解,中文參考手冊都有很詳細的講解。
時鐘
STM32F4 時鐘系統(tǒng)的知識在《STM32F4 中文參考手冊》第六章復(fù)位和時鐘控制章節(jié)有非常詳細的講解,網(wǎng)上關(guān)于時鐘系統(tǒng)的講解也基本都是參考的這里,講不出啥特色,這些知識也不是什么原創(chuàng),純粹根據(jù)官方提供的中文參考手冊和自己的應(yīng)用心得來總結(jié)的,如有不合理之處望大家諒解。
這部分對于計算機組成原理的知識有一定的要求
STM32F4 時鐘樹概述
眾所周知,時鐘系統(tǒng)是 CPU 的脈搏,就像人的心跳一樣。所以時鐘系統(tǒng)的重要性就不言而喻了。
STM32F4 的時鐘系統(tǒng)比較復(fù)雜,不像簡單的 51 單片機一個系統(tǒng)時鐘就可以解決一切。
于是有人要問,采用一個系統(tǒng)時鐘不是很簡單嗎?為什么 STM32 要有多個時鐘源呢?
因為首先 STM32 本身非常復(fù)雜,外設(shè)非常的多,但是并不是所有外設(shè)都需要系統(tǒng)時鐘這么高的頻率,比如看門狗以及 RTC 只需要幾十 k 的時鐘即可。同一個電路,時鐘越快功耗越大,同時抗電磁干擾能力也會越弱,所以對于較為復(fù)雜的 MCU 一般都是采取多時鐘源的方法來解決這些問題。
總述
首先讓我們來看看 STM32F4 的時鐘系統(tǒng)圖
在 STM32F4 中,有 5 個最重要的時鐘源,為 HSI、HSE、LSI、LSE、PLL。
其中 PLL 實際是分為兩個時鐘源,分別為主 PLL 和專用 PLL。
從時鐘頻率來分可以分為高速時鐘源和低速時鐘源,在這 5 個中 HSI,HSE 以及 PLL 是高速時鐘,LSI 和 LSE 是低速時鐘。
從來源可分為外部時鐘源和內(nèi)部時鐘源,外部時鐘源就是從外部通過接晶振的方式獲取時鐘源,其中 HSE 和LSE 是外部時鐘源,其他的是內(nèi)部時鐘源。
功能講解
輸入。
- 主 PLL(PLL)由 HSE 或者 HSI 提供時鐘信號,并具有兩個不同的輸出時鐘。
第一個輸出 PLLP 用于生成高速的系統(tǒng)時鐘(最高 168MHz)
第二個輸出 PLLQ 用于生成 USB OTG FS 的時鐘(48MHz),隨機數(shù)發(fā)生器的時鐘和 SDIO
時鐘。 - 專用 PLL(PLLI2S)用于生成精確時鐘,從而在 I2S 接口實現(xiàn)高品質(zhì)音頻性能。
其余細節(jié)部分請查看文檔
STM32F4 時鐘初始化配置
STM32F4 時鐘系統(tǒng)初始化是在 system_stm32f4xx.c中的 SystemInit()函數(shù)中完成的。
對于系統(tǒng)時鐘關(guān)鍵寄存器設(shè)置主要是在SystemInit函數(shù)中調(diào)用 SetSysClock()函數(shù)來設(shè)置的。
在設(shè)置完相關(guān)寄存器后,接下來 SystemInit 函數(shù)內(nèi)部會調(diào)用 SetSysClock函數(shù)。
在配置的時候,特別需要注意的地方,就是我們還要同步修改 stm32f4xx.h 中宏定義標識符HSE_VALUE 的值為我們的外部時鐘:
#if !defined (HSE_VALUE) #define HSE_VALUE ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */#endif /* HSE_VALUE */這里默認固件庫配置的是 25000000,我們外部時鐘為 8MHz,所以我們根據(jù)我們硬件情況修改為 8000000 即可。
那么 SystemInit 函數(shù)是怎么被系統(tǒng)調(diào)用的呢?
SystemInit 是整個設(shè)置系統(tǒng)時鐘的入口函數(shù)。這個函數(shù)對于我們使用 ST提供的 STM32F4 固件庫的話,會在系統(tǒng)啟動之后先執(zhí)行 main 函數(shù),然后再接著執(zhí)行 SystemInit 函數(shù)實現(xiàn)系統(tǒng)相關(guān)時鐘的設(shè)置。
這個過程設(shè)置是在啟動文件 startup_stm32f40_41xxx.s 中間設(shè)置的,我們接下來看看啟動文件中這段啟動代碼:
這段代碼的作用是在系統(tǒng)復(fù)位之后引導(dǎo)進入 main 函數(shù),同時在進入 main 函數(shù)之前,首先要調(diào)用 SystemInit 系統(tǒng)初始化函數(shù)完成系統(tǒng)時鐘等相關(guān)配置。
最后我們總結(jié)一下 SystemInit()函數(shù)中設(shè)置的系統(tǒng)時鐘大小:
這部分內(nèi)容十分復(fù)雜,對模電和數(shù)電的知識儲備有要求,內(nèi)容很多就不再貼出來。
STM32F4 時鐘使能和配置
上一部分,說明了系統(tǒng)復(fù)位之后調(diào)用 SystemInit 函數(shù)之后相關(guān)時鐘的默認配置。
如果在系統(tǒng)初始化之后,我們還需要修改某些時鐘源配置,或者我們要使能相關(guān)外設(shè)的時鐘該怎么設(shè)置呢?這些設(shè)置實際是在 RCC 相關(guān)寄存器中配置的。因為 RCC 相關(guān)寄存器非常多,有興趣的同學(xué)可以直接打開《STM32F4 中文參考手冊》6.3 小節(jié)查看所有 RCC 相關(guān)寄存器的配置。
所以這里我們不直接講解寄存器配置,而是通過 STM32F4 標準固件庫配置方法給大家講解。
在 STM32F4 標準固件庫里,時鐘源的選擇以及時鐘使能等函數(shù)都是在 RCC 相關(guān)固件庫文件 stm32f4xx_rcc.h 和 stm32f4xx_rcc.c 中聲明和定義的。大家打開 stm32f4xx_rcc.h 文件可以看到文件開頭有很多宏定義標識符,然后是一系列時鐘配置和時鐘使能函數(shù)申明。這些函數(shù)大致可以歸結(jié)為三類,一類是外設(shè)時鐘使能函數(shù),一類是時鐘源和分頻因子配置函數(shù),還有一類是外設(shè)復(fù)位函數(shù)。當(dāng)然還有幾個獲取時鐘源配置的函數(shù)。
下面我們以幾種常見的操作來簡要介紹一下這些庫函數(shù)的使用。
時鐘使能函數(shù)
首先是時鐘使能函數(shù)。時鐘使能相關(guān)函數(shù)包括外設(shè)設(shè)置使能和時鐘源使能兩類。首先我們來看看外設(shè)時鐘使能相關(guān)的函數(shù):
void RCC_AHB1PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState); void RCC_AHB2PeriphClockCmd(uint32_t RCC_AHB2Periph, FunctionalState NewState); void RCC_AHB3PeriphClockCmd(uint32_t RCC_AHB3Periph, FunctionalState NewState); void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState); void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);這里主要有 5 個外設(shè)時鐘使能函數(shù)。5 個函數(shù)分別用來使能 5 個總線下面掛載的外設(shè)時鐘,這些總線分別為:AHB1 總線,AHB2 總線,AHB3 總線,APB1 總線以及 APB2 總線。要使能某個外設(shè),調(diào)用對應(yīng)的總線外設(shè)時鐘使能函數(shù)即可。
這里我們要特別說明一下,STM32F4 的外設(shè)在使用之前,必須對時鐘進行使能,如果沒有使能時鐘,那么外設(shè)是無法正常工作的。對于哪個外設(shè)是掛載在哪個總線之下,雖然我們也可以查手冊查詢到,但是這里如果大家使用的是庫函數(shù)的話,實際上是沒有必要去查詢手冊的,這里我們給大家介紹一個小技巧。
如何查看?
比如我們要使能 GPIOA,我們只需要在 stm32f4xx_rcc.h 頭文件里面搜索 GPIOA,就可以搜索到對應(yīng)的時鐘使能函數(shù)的第一個入口參數(shù)為 RCC_AHB1Periph_GPIOA,從這個宏定義標識符一眼就可以看出,GPIOA 是掛載在 AHB1 下面。
同理,對于串口 1 我們可以搜索 USART1,找到標識符為 RCC_APB2Periph_USART1,那么很容易知道串口 1 是掛載在 APB2 之下。
如何調(diào)用?
如果我們要使能 GPIOA,那么我們可以在頭文件 stm32f4xx_rcc.h 里面查看到宏定義標識符 RCC_AHB1Periph_GPIOA,顧名思義 GPIOA是掛載在 AHB1 總線之下,所以,我們調(diào)用 AHB1 總線下外設(shè)時鐘使能函數(shù) RCC_AHB1PeriphClockCmd 即可。
-具體調(diào)用方式入如下:
同理,如果我們要使能串口 1 的時鐘,那么我們調(diào)用的函數(shù)為:
void RCC_AHB2PeriphClockCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState);具體的調(diào)用方法是:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);還有一類時鐘使能函數(shù)是時鐘源使能函數(shù),前面已經(jīng)講解過 STM32F4 有 5 大類時鐘源。
這里我們列出來幾種重要的時鐘源使能函數(shù):
這些函數(shù)是用來使能相應(yīng)的時鐘源。比如我們要使能 PLL 時鐘,那么調(diào)用的函數(shù)為:
void RCC_PLLCmd(FunctionalState NewState);具體調(diào)用方法如下:
RCC_PLLCmd(ENABLE);我們要使能相應(yīng)的時鐘源,調(diào)用對應(yīng)的函數(shù)即可。
時鐘功能函數(shù)
接下來我們要講解的是第二類時鐘功能函數(shù):時鐘源選擇和分頻因子配置函數(shù)。這些函數(shù)是用來選擇相應(yīng)的時鐘源以及配置相應(yīng)的時鐘分頻系數(shù)。
比如我們之前講解過系統(tǒng)時鐘SYSCLK,我們可以選擇 HSI,HSE 以及 PLL三個中的一個時鐘源為系統(tǒng)時鐘。那么到底選擇哪一個,這是可以配置的。下面我們列舉幾種時鐘源配置函數(shù):
比如我們要設(shè)置系統(tǒng)時鐘源為 HSI,那么我們可以調(diào)用系統(tǒng)時鐘源配置函數(shù):
void RCC_HCLKConfig(uint32_t RCC_SYSCLK);具體配置方法如下:
RCC_HCLKConfig(RCC_SYSCLKSource_HSI);//配置時鐘源為 HSI又如我們要設(shè)置 APB1 總線時鐘為 HCLK 的 2 分頻,也就是設(shè)置分頻因子為 2 分頻,那么如果我們要使能 HSI,那么調(diào)用的函數(shù)為:
void RCC_PCLK1Config(uint32_t RCC_HCLK);具體配置方法如下:
RCC_PCLK1Config(RCC_HCLK_Div2);外設(shè)復(fù)位函數(shù)
接下來我們看看第三類外設(shè)復(fù)位函數(shù)。如下:
void RCC_AHB1PeriphResetCmd(uint32_t RCC_AHB1Periph, FunctionalState NewState); void RCC_AHB2PeriphResetCmd(uint32_t RCC_AHB2Periph, FunctionalState NewState); void RCC_AHB3PeriphResetCmd(uint32_t RCC_AHB3Periph, FunctionalState NewState); void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState); void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);這類函數(shù)跟前面講解的外設(shè)時鐘函數(shù)使用方法基本一致,不同的是一個是用來使能外設(shè)時鐘,一個是用來復(fù)位對應(yīng)的外設(shè)。這里大家在調(diào)用函數(shù)的時候一定不要混淆。
對于這些時鐘操作函數(shù),我們就不一一列舉出來,大家可以打開 RCC 對應(yīng)的文件仔細了解。
總結(jié)
總線與時鐘部分讓人頭大,草草的過了一遍知識點,有點囫圇吞棗的意思了,不過我的目標也是先用起來,暫時不深究,等用到了之后再仔細學(xué)習(xí)相應(yīng)的部分,未完待續(xù) =w=
總結(jié)
以上是生活随笔為你收集整理的STM32学习之总线与时钟的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 程序员之常用软件安装过程记录
- 下一篇: WAMP本地环境配置多站点虚拟目录教程(