1. 程式人生 > 實用技巧 >淺析STM32 中常用的三個函式(sys.c,delay.c,usart.c)之二

淺析STM32 中常用的三個函式(sys.c,delay.c,usart.c)之二

2.delay函式也是非常常用的函式

  提到delay延時,我就想到了STM32裡面專門用來延時的systick定時器,常用 ck定時器是一個24位倒計數定時器,當計到0時,將從RELOAD暫存器重新自動裝載初值。只要不把Systick的控制使能位及狀態暫存器中的使能位清除,就會永不停息的工作。這個定時器的優點如下:

  1)不佔用中斷 2)也不佔用系統定時器

#include "delay.h"
#include "stm32f10x.h"
void delay_init()
{

    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);    
//選擇外部時鐘 HCLK/8 fac_us=SystemCoreClock/8000000; //為系統時鐘的1/8 f=72000000/8/(10^6)=9 t=(1/9)/10^6s =(1/9)us                              //因此,時基fac_us=9,因為9*(1/9us)=1us,使滴答定時器計數9次就是1us fac_ms=(u16)fac_us*1000;            //fac_us*1000就是9000,9000*(1/9us)=1000us=1ms //延時nus //nus為要延時的us數.
void delay_us(u32 nus) { u32 temp; SysTick->LOAD=nus*fac_us; //時間載入 SysTick->VAL=0x00; //清空計數器 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //開始倒數 do { temp=SysTick->CTRL; }
while((temp&0x01)&&!(temp&(1<<16))); //等待時間到達 SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //關閉計數器 SysTick->VAL =0X00; //清空計數器 } //延時nms //注意nms的範圍 //SysTick->LOAD為24位暫存器,所以,最大延時為: //nms<=0xffffff*8*1000/SYSCLK //SYSCLK單位為Hz,nms單位為ms //對72M條件下,nms<=1864 void delay_ms(u16 nms) { u32 temp; SysTick->LOAD=(u32)nms*fac_ms; //時間載入(SysTick->LOAD為24bit) SysTick->VAL =0x00; //清空計數器 SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //開始倒數 do { temp=SysTick->CTRL; }while((temp&0x01)&&!(temp&(1<<16))); //等待時間到達 SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //關閉計數器 SysTick->VAL =0X00; //清空計數器 }

此時,沒有什麼比一個權威的M3中文手冊來說明更合適的了!!!

這個是CTRL暫存器,即SysTick->CTRL所指向的暫存器,他是SysTick控制及狀態暫存器。

其中值得一提的是位0(使能位)以及位16(COUNTFLAG)

  SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //開始倒數

  在延時函式裡面SysTick_CTRL_ENABLE_Msk的定義是#define SysTick_CTRL_ENABLE_Msk (1ul << 0)

  其實就是把CTRL暫存器的位0(開始計數使能位)置1,方式是|=0x01.

  SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //關閉計數器


關閉計數器函式,通過把除使能位之外的位置1,使能位清零,即&=(~0x01)

位16是SysTick定時器中的一個計數完成一週期的標誌位,當SysTick定時器從裝載值計到0時,讀取該位就是1,讀取該位之後該位置0.
常用於等待計數程式中,當作計數結束標誌位,表明已經計時規定時間。
 do
    {
        temp=SysTick->CTRL;
    }while((temp&0x01)&&!(temp&(1<<16)));        //等待時間到達



SysTick->LOAD=(u32)nms*fac_ms;                //時間載入(SysTick->LOAD為24bit)
SysTick->LOAD所指向的就是SysTick重灌載數值暫存器,他的作用如他的描述所述,就是當SysTick定時器計數到0時,自動裝載RELOAD
SysTick重灌載數值暫存器裡面的值。



SysTick->VAL =0x00;                            //清空計數器
SysTick->VAL所指向的就是SysTick當前數值暫存器,他儲存的是計數器當前的值,會隨著倒計數一直不斷變小。




注意:
fac_us 微妙級時基是計數到一微妙所要計數的次數
f=72*(10^6)/8=9*(10^6)HZ=9MHZ    //SysTick 定時器的計數頻率
t=1/f=1/9us              //SysTick 定時器的計數時間
fac_us=1us/t=1us/(1/9us)=9 //即9為微妙級時基
而fac_us毫秒級時基是計數到一毫秒所要計數的次數
fac_ms=1000*fac_us

最大計時時間T
SysTick->LOAD為24位暫存器,因此,最大裝載值是0xFFFFFF,
而T=0xFFFFFF*1/9us=1864135us=1864ms;