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;