提前說說
學習32這麼長時間了,中間有一段內容也比較生疏,比如就是這個時鐘。那會初學,真的沒有搞清楚,今天再次回過頭複習一下,徹底把時鐘這一部分弄清楚
時鐘
時鐘樹
用戶可通過多個預分頻器配置AHB、高速APB(APB2)和低速APB(APB1)域的頻率。AHB和
APB2域的最大頻率是72MHz。APB1域的最大允許頻率是36MHz。SDIO接口的時鐘頻率固定爲HCLK/2。
RCC通過AHB時鐘(HCLK)8分頻後作爲Cortex系統定時器(SysTick)的外部時鐘。通過對SysTick
控制與狀態寄存器的設置,可選擇上述時鐘或Cortex(HCLK)時鐘作爲SysTick時鐘。ADC時鐘
由高速APB2時鐘經2、4、6或8分頻後獲得。
定時器時鐘頻率分配由硬件按以下2種情況自動設置:
- 如果相應的APB預分頻係數是1,定時器的時鐘頻率與所在APB總線頻率一致。
- 否則,定時器的時鐘頻率被設爲與其相連的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 定時器的原理。