STM32学习及应用笔记一:SysTick定时器学习及应用
這幾年一直使用STM32的MCU,對ARM內核的SysTick計時器也經常使用,但幾乎沒有仔細了解過。最近正好要在移植一個新的操作系統時接觸到了這塊,據比較深入的了解了一下。
1、SysTick究竟是什么?
關于SysTick在STM32的資料中并沒有詳細的介紹,這可能由于SysTick是ARM內核的東西。在《STM32F10xxx參考手冊》、《STM32F4xx參考手冊》以及《STM32F7xx參考手冊》中,介紹時鐘的時候僅僅是在使用樹上簡單的畫出了HCLK時鐘經過8分頻后送到了Cortex系統時鐘。對這個時鐘的描述也非常的簡單。在《STM32F10xxx參考手冊》中僅僅說:“RCC通過AHB時鐘(HCLK)8分頻后作為Cortex系統定時器(SysTick)的外部時鐘?!蓖瑯釉凇禨TM32F4xx參考手冊》和《STM32F7xx參考手冊》中,也只是說:“RCC 向 Cortex 系統定時器 (SysTick) 饋送 8 分頻的 AHB 時鐘 (HCLK)。”
另外,STM32在中斷部分對SysTick也有一句話的描述。如在《STM32F10xxx參考手冊》中的“9.1.1 系統嘀嗒(SysTick)校準值寄存器”中提到:“系統嘀嗒校準值固定為9000,當系統嘀嗒時鐘設定為9MHz(HCLK/8的最大值),產生1ms時間基準?!倍凇禨TM32F4xx參考手冊》的“10.1.2SysTick 校準值寄存器”一節和《STM32F7xx參考手冊》“10.1.1SysTick 校準值寄存器”一節中也都有:“SysTick 校準值設置為 18750。當 SysTick 時鐘設置為 18.75 MHz(HCLK/8,HCLK 設為150 MHz),會產生 1 ms 時間基準。”
僅看這些讓我們覺得SysTick似乎都是定好的,但事實上并非如此,因為在庫函數中有相關寄存器的操作函數。為了搞清楚這一點,我們必須查看Cortex-M3和M4的手冊。在《Cortex-M3權威指南》的“第8章 NVIC與中斷控制”中有比較詳細的描述。首先很明確SysTick?就是一個定時器;其次SysTick定時器被捆綁在NVIC中,用于產生SYSTICK異常,主要適用于操作系統的“心跳”節律。關于SysTick的時鐘來源最終還是由芯片廠商決定。
SysTick定時器能產生中斷,并且是一個單獨的異常類型,并且在向量表中有它的一席之地。并有四個寄存器來控制SysTick,在《Cortex-M3權威指南》中對他們的描述如下:
(1)、STK_CSR控制寄存器:寄存器內有4個位具有意義
(2)、STK_LOAD?重載寄存器
Systick?是一個遞減的定時器,當定時器遞減至0?時,重載寄存器中的值就?會被重裝載,繼續開始遞減。STK_LOAD?重載寄存器是個24?位的寄存器最大計數0xFFFFFF。
?
(3)、STK_VAL當前值寄存器
?????也是個24?位的寄存器,讀取時返回當前倒計數的值,寫它則使之清零,同時還會清除在SysTick?控制及狀態寄存器中的COUNTFLAG?標志。
?
(4)、STK_CALRB?校準值寄存器?
?
2、STM32中的SysTick
作為一用于系統級的24位遞減計時器,在STM32中又是處理的呢?ST在手冊里介紹的比較簡單,但在庫函數中卻有比較清楚的定義。不論是標準庫還是HAL庫都有較為清楚的定義,如在標準庫中就定義SysTick寄存器結構體機器操作函數,在misc.C文件中的SysTick_CLKSourceConfig函數,它是一個時鐘源配置函數,其定義如下:
/*@功能:配置SysTick時鐘源
*@輸入參數:? SysTick_CLKSource:? 指定 SysTick 時鐘源.
*? 該參數可以是以下其中一個值:
* @ SysTick_CLKSource_HCLK_Div8: AHB 時鐘 8 分頻作為SysTick時鐘源
* @ SysTick_CLKSource_HCLK: AHB 時鐘作為 SysTick 時鐘源. */?
void SysTick_CLKSourceConfig(uint32_t Sy sTick_CLKSource)
{
assert_param(IS_SYSTICK_CLK_SOURCE(SysTi ck_CLKSource));
????? if(SysTick_CLKSource==? SysTick_CLKSource_HCLK)
? ?? {
SysTick->CTRL|= SysTi ck_CLKSource_HCLK;
}?
else
{
SysTick->CTRL&= SysTick_CLKSource_HCLK_Div8;
}
}
由此可見,在STM32中時鐘可以設置為HCLK或者HCLK的8分頻,根據使用的需求而定。默認不配置的話時鐘就是HCLK的8分頻。同樣在HAL苦衷的定義也是如此。
在core_cm3.h文件中有寄存器定義:
typedefstruct
{
__IOuint32_t CTRL;
__IOuint32_t LOAD;
__IOuint32_t VAL;
__Iuint32_t CALIB;
}SysTick_Type;
還定義了一個SysTick_Config 函數
#if (!defined(__Vendor_Sy sTickConfig )) ||(__Vendor_SysTickConfig? == 0)
/**
* @功能? 初始化并開啟 Sy sTick 計數器及其中斷
*@輸入參數??? ticks???兩次中斷間的 ticks 數值
*@返回值? 1 =? 失敗, 0=成功
*? 初始化系統滴答定時器及其中斷并開啟系統滴答定時器在自由運行模式下以產生周期中斷*/
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if(ticks >SysTick_LOAD_RELOAD_Msk)? return(1);/* 重裝值超過了 24 位,是不可能的。返回失敗值 0 */
SysTick->LOAD? =(ticks & SysTick_LOAD_RELOAD_Msk) - 1;/*? 設置重裝載寄存器? */
NVIC_SetPriority(SysTick_IRQn,( 1<<__NVIC_PRIO_BITS) - 1);? /*設置優先級for Cortex-M0系統中斷*/
SysTick->VAL? = 0; /*裝載計數器值(當前計數值清 0)? */
SysTick->CTRL =SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk| SysTick_CTRL_ENABLE_Msk;/* 使能 Sy sTick 中斷請求和 Sy stick 定時*/
return(0);????????? /*成功,返回 0 */
?}
?#endif
經過以上分析,我們我們需要,可以很方便的在自己的軟件中操作SysTick來實現一些功能。
3、STM32中SysTick應用舉例
既然SysTick我們已經清楚了他的原理及操作,也明白了STM32庫中如何來操作它,那么我們能用他來做什么呢?首先我們可以在STM32中使用嵌入式操作系統的時候使用它來,并更具實際應用來設置。其實在不考慮操作系統是我們還可以使用SysTick來實現延時計時器。
一個實現的例子如下:
//定義延時計數的變量
__IO uint32_t TimingDelay;
const uint16_t delayAdjustments=12;
?
//函數名:ms延時函數
//描 述:參數1即為1ms,1000即為1s;只有幾us的誤差;
void Delayms(__IO uint32_t nTime)
{
?while(SysTick_Config(SystemCoreClock/1000));
? SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;// 關閉滴答定時器
? TimingDelay = nTime;
? SysTick->CTRL |=SysTick_CTRL_ENABLE_Msk;// 使能滴答定時器
? while(TimingDelay != 0);
? SysTick->CTRL=0x00; //關閉計數器
? SysTick->VAL =0X00; //清空計數器
}
?
//函數名:us延時函數
//描 述:參數1即為1us,1000即為1ms;只有幾us的誤差;
void Delayus(__IO uint32_t nTime)
{
? while(SysTick_Config(SystemCoreClock/1000000));
? SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;// 關閉滴答定時器
? TimingDelay = nTime;
? SysTick->CTRL |=SysTick_CTRL_ENABLE_Msk;// 使能滴答定時器
? while(TimingDelay != 0);
? SysTick->CTRL=0x00; //關閉計數器
? SysTick->VAL =0X00; //清空計數器
}
?
//函數名:延時遞減計數函數
//描 述:由systick的中斷函數調用,實現延時數值的遞減計數
void TimingDelay_Decrement(void)
{
? if (TimingDelay != 0x00)
? {
??? TimingDelay--;
? }
}
?
//函數名:延時調整形式的delaynus函數
//描 述:參數1即為1us,1000即為1ms,根據時鐘頻率的不同時間不同
void delay_nus(uint16_t n)
{
? uint16_t j;
? while(n--)
? {
??? j=delayAdjustments;//根據不同時鐘頻率的指令周期調整數值
??? while(j--);
? }
}
?
//函數名:延時調整形式的delaynms函數
//描 述:參數1即為1ms,1000即為1s,根據時鐘頻率的不同時間不同
void delay_nms(uint16_t n)
{
? while(n--)
? {
??? delay_nus(1000);
? }
}
4、參考文獻
我們參考了一些經典的手冊以及網絡論壇上的一些討論,無法一一列出,暫列出部分參考文獻:
(1)、《Cortex-M3權威指南》
(2)、《STM32F10x參考手冊》
(3)、《STM32F4參考手冊》
(4)、《STM32F7參考手冊》
(5)、《STM32F10x庫函數說明》
(6)、《STM32F1 HAL庫說明》
(7)、《STM32F4 HAL庫說明》
(8)、《STM32F7 Hal庫說明》
?
總結
以上是生活随笔為你收集整理的STM32学习及应用笔记一:SysTick定时器学习及应用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 人名和成绩一起排序_EXCEL基础知识—
- 下一篇: 一文带你读懂base64编码