STM32系統學習 SysTick(系統定時器)

2021-08-11 10:09:51 字數 4982 閱讀 9634

systick系統定時器是屬於cm3核心中的乙個外設,內嵌在nvic(巢狀向量中斷控制器,控制整個晶元中斷相關的功能,它與核心緊密藕合,是核心中的乙個外設)中。系統定時器是乙個24位的向下遞減的計數器,計數器每計數一次的時間為1/sysclk,一般我們設定系統時鐘sysclk為72mhz,當重裝載數值暫存器的值遞減為0時,系統定時器就產生一次中斷,以此迴圈往返。

因為systick是屬於cm3核心的外設,所以所有基於cm3核心的微控制器都具有這個系統定時器,這使得軟體在cm3微控制器中可以很容易被移植。系統定時器一般用於作業系統,用於產生時基,維持作業系統的心跳。

一、systick暫存器介紹

systick系統定時器中有4個暫存器,分別是:

ctrl——systick控制及狀態暫存器

load——systick重裝載數值暫存器

val——systick當前數值暫存器

calib——systick校準數值暫存器

在使用systick產生定時的時候,只需要配置前3個暫存器,最後乙個校準暫存器不需要使用。

二、systick定時實驗

建立兩個檔案bsp_systick.c和bsp_systick.h用來存放systick驅動程式及相關巨集定義,中斷服務函式放在stm32f10x_it.h中。要點在於1)設定重裝載暫存器的值;2)清楚當前數值暫存器的值;3)配置控制與狀態暫存器。

1、systick配置庫函式

**清單——systick配置庫函式
__static_inline uint32_t systick_config(uint32_t ticks)

// 設定重裝載暫存器

systick->load = (uint32_t)(ticks - 1ul);

// 設定中斷優先順序

nvic_setpriority (systick_irqn, (1ul << __nvic_prio_bits) - 1ul);

// 設定當前數值暫存器

systick->val = 0ul;

// 設定系統定時器的時鐘源為 ahbclk=72m

// 使能系統定時器中斷

// 使能定時器

systick->ctrl = systick_ctrl_clksource_msk |

systick_ctrl_tickint_msk |

systick_ctrl_enable_msk;

return (0ul);

}

用韌體庫程式設計時我們只需要呼叫庫函式systick_config()即可,形參ticks用來設定重裝載暫存器的值,再大不超過重裝載暫存器的值2^24,當重裝載暫存器的值遞減到0的時候產生中斷,然後重裝載暫存器的值又重新裝載往下遞減計數,以此迴圈往復。隨後設定好中斷優先順序,最後配置系統定時器的時鐘等於ahbclk=72mhz,使能定時器和定時器中斷,這樣系統定時器就配置好了。

systick_config()庫函式主要配置了systick中的3個暫存器:load、val和ctrl。

2、配置systick中斷優先順序

systick_config()庫函式還呼叫了韌體庫nvic_setpriority()來配置系統定時器的中斷優先順序,該函式也在core_m3.h中定義。

**清單——配置systick中斷優先順序
_static_inline void nvic_setpriority(irqn_type irqn, uint32_t priority)

else

}

函式首先判斷形參irqn的大小,如果小於0,則表示這個是系統異常,系統異常的優先順序由核心外設scb的暫存器shprx控制;如果大於0,則是外部中斷,外部中斷的優先順序由核心外設nvic中的ipx暫存器控制。

因為systick屬於核心外設 ,與普通外設的中斷優先順序有些區別,並沒有 搶占優先順序和子優先順序的說法。在stm32f103中,核心外設的中斷優先順序由核心scb這個外設的暫存器shprx(x=1~3)來配置。

sprh1~sprh3是乙個32位的暫存器,但是只能通過位元組訪問,每8個字段控制乙個核心外設的中斷優先順序的配置。stm32f103中,只有位7~位3這高4位有效,低4位沒有用到,所以核心外設的中斷優先順序可程式設計為0~15,只有16個程式設計優先順序,數值越小優先順序越高。

在系統定時器中,配置優先順序為(1ul << __nvic_prio_bits) - 1ul),其中巨集

__nvic_prio_bits 為 4,那計算結果就等於 15,可以看出系統定時器此時設定的優先順序

在核心外設中是最低的,如果要修改優先順序則修改這個值即可,範圍為:0~15。

設定系統定時器中斷優先順序

nvic_setpriority (systick_irqn, (1ul << __nvic_prio_bits) - 1ul);

以上是核心的外設優先順序設定,如果同時使用了systick和片上外設呢 ?

比如配置乙個外設的中斷優先順序分組為2,搶占優先順序為1,子優先順序為1,systick的優先順序為韌體庫預設配置的15。當我們比較核心外設和片上外設的時候,我們只需要抓住nvic的中斷優先順序分組不僅對片上外設有效,同樣對核心的外設也有效,把systick的優先順序15轉換成二進位制就是1111(0b),又因為nvic的優先順序分組為2,那麼前兩位的11(0b)也是3,後兩位也是3,無論從搶占還是子優先順序都比我們設定的外設的優先順序低。如果2個軟體優先順序配置成一樣,那就比較硬體編號,編號越小,優先順序越高。

3、systick初始化函式

**清單——systick初始化
/**

*@brief 啟動系統滴答定時器 systick

*/void systick_init(void)

}

systick初始化函式由使用者編寫,裡面的systick_config()韌體庫函式,通過設定該韌體庫的形參,就決定了系統定時器經過多少時間產生一次中斷。

4、systick_config中斷時間的計算

systick 定時器的計數器是向下遞減計數的,計數一次的時間 t (dec) =1/clk (ahb) ,當重裝載暫存器中的值 value (load) 減到 0 的時候,產生中斷,可知中斷一次的時間t (int) =value (load) * t (dec) = value (load) /clk (ahb) , 其 中 clk (ahb) =72mhz 。 如 果 設 置value (load) 為 72,那中斷一次的時間 t (int) =72/72m=1us。不過 1us 的中斷沒啥意義,整個程式的重心都花在進出中斷上了,根本沒有時間處理其他的任務。

systick_config(systemcoreclock / 100000))

systick_config()的形我們配置為 systemcoreclock / 100000=72m/100000=720,從剛剛分析我們知道這個形參的值最終是寫到重裝載暫存器 load 中的,從而可知我們現在把systick 定時器中斷一次的時間 t (int) =720/72m=10us。

5、systick定時時間的計算

設定好t(int)後,可以設定乙個變數t,用來記錄進入中斷的次數,那麼用變數t乘以中斷的時間t(int),就可以計算出需要定時的時間。

6、systick定時函式

定義乙個微妙級別的延時函式,形參為ntime,用這個形參乘以中斷時間t(int)就得出我們需要的延時時間。

**清單——systick定時函式
/**

*@brief us 延時程式,10us 為乙個單位

*@param

*@arg ntime: delay_us( 1 ) 則實現的延時為 1 * 10us = 10us

*@retval 無

*/void delay_us(__io u32 ntime)

函式delay_us中我們等待timingdelay為0,當timingdelay為0時表示延時時間到。即systick每進行一次中斷(10us),timingdelay遞減一次。

7、systick中斷服務函式

void systick_handler(void)

中斷復位函式呼叫了另外乙個函式 timingdelay_decrement(),如下

* @attention 在 systick 中斷函式 systick_handler()呼叫

*/ void timingdelay_decrement(void)

}

三、另一種更簡潔的定時程式設計

systick的counter從reloader的值往下遞減到0的時候,ctrl暫存器的位16:countflag會置1,且讀取該位的值可清0,所以可以使用軟體查詢的方法實現延時。

**清單——systick微秒級延時
void systick_delay_us( __io uint32_t us)

// 關閉 systick 定時器

systick->ctrl &=~systick_ctrl_enable_msk;

}

**清單——systick毫秒級延時
void systick_delay_ms( __io uint32_t ms)

// 關閉 systick 定時器

systick->ctrl &=~ systick_ctrl_enable_msk;

}

**清單——systick配置函式
// 這個 韌體庫函式 在 core_cm3.h 中

static __inline uint32_t systick_config(uint32_t ticks)

引用《stm32庫開發實戰指南》

UCOSIII系統學習 STM32

硬體 stm32f103c8t6 軟體 正點原子stm32f103 裸機程式 ucosiii系統程式 本文主要是描述ucosiii系統的優點和特點 有嵌入式經驗的同胞們都知道,多工處理時,最好的方法就是建立程序和執行緒,我個人拙見,ucos系統就是因為stm32無法跑gcc,而且微控制器都是單核單執...

STM32學習 時鐘系統

眾所周知,時鐘系統是 cpu 的脈搏,就像人的心跳一樣。所以時鐘系統的重要性就不言而 喻了。stm32 的時鐘系統 stm32 的時鐘系統比較複雜,不像簡單的 51 微控制器乙個系統時鐘就可以解決一切。於 是有人要問,採用乙個系統時鐘不是很簡單嗎?為什麼 stm32 要有多個時鐘源呢?因為首先 st...

STM32系統架構

這裡所講的 stm32 系統架構主要針對的 stm32f103 這些非互聯型晶元 stm32 主系統主要由 四個驅動單元 和四個被動單元 構成。四個驅動單元是 核心 dcode 匯流排 系統匯流排 通用 dma1 通用 dma2 四被動單元是 ahb 到 apb 的橋 連線所有的 apb 裝置 內部...