stm32學習筆記(10)時鐘

提前說說

學習32這麼長時間了,中間有一段內容也比較生疏,比如就是這個時鐘。那會初學,真的沒有搞清楚,今天再次回過頭複習一下,徹底把時鐘這一部分弄清楚

時鐘

時鐘樹
在這裏插入圖片描述用戶可通過多個預分頻器配置AHB、高速APB(APB2)和低速APB(APB1)域的頻率。AHB和
APB2域
的最大頻率是72MHzAPB1域的最大允許頻率是36MHz。SDIO接口的時鐘頻率固定爲HCLK/2。
RCC通過AHB時鐘(HCLK)8分頻後作爲Cortex系統定時器(SysTick)的外部時鐘。通過對SysTick
控制與狀態寄存器的設置,可選擇上述時鐘或Cortex(HCLK)時鐘作爲SysTick時鐘。ADC時鐘
由高速APB2時鐘經2、4、6或8分頻後獲得。
定時器時鐘頻率分配由硬件按以下2種情況自動設置:

  1. 如果相應的APB預分頻係數是1,定時器的時鐘頻率與所在APB總線頻率一致。
  2. 否則,定時器的時鐘頻率被設爲與其相連的APB總線頻率的2倍。

這裏總結一下 SystemInit()函數中設置的系統時鐘大小:
SYSCLK(系統時鐘) =72MHz
AHB 總線時鐘(使用 SYSCLK) =72MHz
APB1 總線時鐘(PCLK1) =36MHz
APB2 總線時鐘(PCLK2) =72MHz
PLL 時鐘 =72MHz

SysTick滴答定時器

void delay_init()
{
#if SYSTEM_SUPPORT_OS  							//如果需要支持OS.
	u32 reload;
#endif
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);	//選擇外部時鐘  HCLK/8
	fac_us=SystemCoreClock/8000000;				//爲系統時鐘的1/8  
#if SYSTEM_SUPPORT_OS  							//如果需要支持OS.
	reload=SystemCoreClock/8000000;				//每秒鐘的計數次數 單位爲K	   
	reload*=1000000/delay_ostickspersec;		//根據delay_ostickspersec設定溢出時間
												//reload爲24位寄存器,最大值:16777216,在72M下,約合1.86s左右	
	fac_ms=1000/delay_ostickspersec;			//代表OS可以延時的最少單位,爲5	   

	SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;   	//開啓SYSTICK中斷
	SysTick->LOAD=reload; 						//每1/delay_ostickspersec秒中斷一次	
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;   	//開啓SYSTICK    

#else
	fac_ms=(u16)fac_us*1000;					//非OS下,代表每個ms需要的systick時鐘數   
#endif
}					
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);	//選擇外部時鐘  HCLK/8

這一段代碼,就是選擇delay函數的時鐘,爲72/8mhz,也就是9mhz。我是這麼理解的,現在delay函數時鐘爲9mhz,那麼它的單位就是1/(9mhz)=1/9us

fac_us=SystemCoreClock/8000000;

第二段代碼是fac_us爲72mhz/8000000,也就是9個單位,那麼fac_us=9*(1/9)us=1us。以上是不是操作系統的情況。

這裏我們將介紹的是 ALIENTEK 提供的最新版本的延時函數,該版本的延時函數支持在任
意操作系統(OS)下面使用,它可以和操作系統共用 SysTick 定時器。
這裏,我們以 UCOSII 爲例,介紹如何實現操作系統和我們的 delay 函數共用 SysTick 定時
器。首先,我們簡單介紹下 UCOSII 的時鐘:ucos 運行需要一個系統時鐘節拍(類似 “心跳”),
而這個節拍是固定的(由 OS_TICKS_PER_SEC 宏定義設置),比如要求 5ms 一次(即可設置:
OS_TICKS_PER_SEC=200),在 STM32 上面,一般是由 SysTick 來提供這個節拍,也就是 SysTick
要設置爲 5ms 中斷一次,爲 ucos 提供時鐘節拍,而且這個時鐘一般是不能被打斷的(否則就不
準了)。

因爲在 ucos 下 SysTick 不能再被隨意更改,如果我們還想利用 SysTick 來做 delay_us 或者
delay_ms 的延時,就必須想點辦法了,這裏我們利用的是時鐘摘取法。以 delay_us 爲例,比如
delay_us(50),在剛進入 delay_us 的時候先計算好這段延時需要等待的 SysTick 計數次數,這裏
爲 50 * 9(假設系統時鐘爲 72Mhz,那麼 SysTick 每增加 1,就是 1/9us),然後我們就一直統計
SysTick 的計數變化,直到這個值變化了 50 * 9,一旦檢測到變化達到或者超過這個值,就說明
延時 50us 時間到了。這樣,我們只是抓取 SysTick 計數器的變化,並不需要修改 SysTick 的任
何狀態,完全不影響 SysTick 作爲 UCOS 時鐘節拍的功能,這就是實現 delay 和操作系統共用
SysTick 定時器的原理。

發佈了74 篇原創文章 · 獲贊 65 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章