 
stm32內核里面有一個很棒的定時器,可以在不占用CPU資源呢的前提下,完成定時的功能。從51單片機過來的時候,使用延時的辦法就是CPU一直進行空語句的執行,即for(i=100;i>0;i--)。這樣進行延時的辦法,在初學階段是比較好用的,但是深入學習到UCOSII/III這種操作系統之后,這種簡單的延時,就只會占用CPU。讓該運轉的指令得不到及時的執行。(定時器也可以解決這個問題,但是CortexM3/M4內核里面有這個玩意,自然要用上)為了解決這種問題,SysTick定時器應運而生。
SysTick定時器的內容在《Cortex M3與M4權威指南》里面才被提到,而《STM32F4xx英文參考手冊》里面卻沒有。作者也是看《Cortex M3與M4權威指南》學習的。只需要掌握關于 SysTick里面的3個寄存器,即可隨心所欲的使用延時功能啦。
我先將這幾個定時器貼出來:
systick.PNG (71.86 KB, 下載次數: 59)
下載附件
2020-2-22 14:03 上傳
- SysTick->CTRL : SysTick Control and Status Register(systick控制與狀態寄存器)
- SysTick->LOAD SysTick Reload Value Register (systick 重裝裝載值寄存器)
- SysTick->VAL SysTick Current Value Register(systick當前值寄存器)
(51過來的同學,systick定時器和51的定時0差不多的理解 (The counter inside the SysTick is a 24-bit decrement counter)SysTick內部的計數器是一個24位遞減計數器 。只需要將SysTick從一數到零需要多少時間弄明白即可。
systick定時器初始化
- static u8 time_us=0; //用來存儲定時1us需要計數個數
- static u16 time_ms=0; //用來存儲定時1ms需要計數個數
-
- void systick_init(void)
- {
- SysTick->CTRL &=~(1<<2); // 8分頻 選擇將系統時鐘進行8分頻 168M/8 = 21M 這個意思就是systick定時器從1->0數一下需要1/21us
- time_us=21; //168/8 延時1us需要計數21次
- time_ms=(u16)time_us*1000; // 延時1ms需要計數21*1000次
- }
復制代碼 舉個例子,如果我們想要延時100us 那么 以systick_init(); 進行初始化 我們只需要將計數次數計算出來 count = time_us * 100us 再將count裝載進如systick->load 寄存器里面就可以,然后開啟定時器 ,判斷是否從count數到0,如果沒有,繼續檢測,反之,則退出,并關閉定時器。即可以完成定時的功能。(不需要systick定時中斷)
延時1us代碼
捕獲.PNG (29.15 KB, 下載次數: 64)
下載附件
2020-2-22 15:06 上傳
延時1ms代碼
- /*
- u16 t_ms 最大為65535
- 65535 * 2100 = 1376235000 >> 16777216超出24位寄存器的值
- 在不超出 24位寄存器的前提下 t_ms最大為 16777216/2100 = 798.9150476
- 也就是最大延時 798.9150476ms
- */
- void systick_delay_ms(u16 t_ms)
- {
- u8 res = 0;
- SysTick->LOAD = t_ms * time_ms; //SysTick->LOAD 24位的寄存器 最大值是16777216
- SysTick->CTRL |= 1<<0; //打開滴答定時器
- SysTick->VAL = 0;
- do { res = (u8)(SysTick->CTRL>>16); }while(!(res&1)); //判斷延時是否結束的標志
- SysTick->CTRL &= ~(1<<0); //關閉滴答定時器
- }
復制代碼
捕獲3.PNG (38.08 KB, 下載次數: 70)
下載附件
2020-2-22 15:07 上傳
systick_delay_ms這個函數最大只能延時798.9150476ms,如果我們想要延時更多的時間,我們怎么辦? 最通俗的辦法就是systick_delay_ms(500);systick_delay_ms(500);這樣即可。請看代碼
- /*獲取更多延時
- 思想就是:重復幾次 systick_delay_ms這個函數(最大延時 798.9150476ms)
- 獲取更多延時*/
- void delay_100ms(u8 t_100ms)
- {
- u8 res = 0;
- while(t_100ms--)
- {
- SysTick->LOAD = time_ms * 100; //100ms需要的節拍數
- SysTick->CTRL |= 1<<0; //打開滴答定時器
- SysTick->VAL = 0;
- do { res = (u8)(SysTick->CTRL>>16); }while(!(res&1)); //判斷延時是否結束的標志
- }
- }
復制代碼 void delay_100ms(u8 t_100ms) 這個函數還是有問題的,就是我們想要延時更長時間,同時也想要把這個函數延時時間降到100ms以內,這樣的話,那么這個函數就做不到啦,于是繼續改唄,怎么才能延時更長的時間,而減小間隔呢?
- void delay_ms(u16 t_ms)
- {
- u8 t_l = t_ms%255;
- u8 t_h = t_ms/255;
- while (t_h--)
- {
- systick_delay_ms(255);
- }
- if(t_l) systick_delay_ms(t_l);
- }
復制代碼 關于systick定時器的學習,就到這里啦。我自己本身還是有很多不足的,其實關于STM32F4的時鐘頻率是需要配置的,才能為168M。如果沒有將這些宏定義改為下面的,時鐘頻率不為168Mhz,就達不到你想要的延時時間了。
system_stm32f4xx.c 文件 宏定義PLL_M 改為8 即: #define PLL_M 8 uint32_t SystemCoreClock = 168000000;
stm32f4xx.c 文件 即: #define HSE_VALUE ((uint32_t)8000000)
學無止境,繼續努力
代碼工程奉上!
全部資料51hei下載地址:
STM32F407 systick 定時器延時.zip
(454.94 KB, 下載次數: 32)
2020-2-22 15:05 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|