前面我們講過,因為在STM32上沒有系統時間的接口,因此無法調用sleep函數,在本文中,筆者將利用滴答計時器實現精准延時。
查閱技術手冊,滴答計時器依賴於一個SysTick_Type類型寄存器,定義如下
typedef struct { vu32 CTRL; vu32 LOAD; vu32 VAL; vuc32 CALIB; } SysTick_TypeDef;
四個成員分別意義是控制和狀態,重裝載值,當前值,校准值。
滴答計時器的原理很簡單,就是利用系統時鍾信號,每接到一個時鍾信號計數器加一,和校准值相等時就自動歸零。
指向SysTick 外設的指針被如下聲明:
#define SysTick ((SysTick_TypeDef *) SysTick_BASE)
要使用滴答計時器時,調用此指針即可。
首先,我們用SysTick_CLKSourceConfig函數初始化systick
void systick_configer(){ SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); }
注意,我這里給的參數是SysTick_CLKSource_HCLK_Div8,就是時鍾信號八分頻,每接到8個時鍾信號才讓計數器+1,因為systick外設時鍾頻率是72MHz,也就是每秒要跳72M次,如果試圖用此信號記錄1秒的時間,就會爆計數器,因為計數器只有24位,只能存儲16M的數字。
void Delay_ms(int ms){ while(ms--){ SysTick->LOAD=9000; SysTick->VAL=0; SysTick->CTRL|=1; while(!(SysTick->CTRL&(1<<16))); SysTick->VAL=0; SysTick->CTRL&=0xfffffffe; } }
時鍾頻率是72MHz,八分頻就是9MHz,因此每毫秒就是計數9000次。
首先清空計數器,然后將重裝載值設置為9000,一旦計數器達到此值,控制寄存器的第16位就會變成1;
最后,將控制寄存器最后一位置為1,此位是時鍾使能開關,若為1則時鍾開始計數。
然后等待並判斷控制寄存器的第16位是否為1,若此條件達成,重置。
由於systick寄存器每一位都有不同的功能,需要分別操作,甚至有些位無法訪問,因此要善於使用位運算。
#ifndef _SYSTICK_H #define _SYSTICK_H void systick_configer(); void Delay_ms(int ms); #endif //systick.h
至此,我們利用滴答計時器實現了類似於sleep的功能。