STM32精確延時(shí)(非中斷,非ST庫(kù)函數(shù))
前天學(xué)了下stm的systick,發(fā)現(xiàn)還滿(mǎn)好用的,可以用來(lái)精確定時(shí).以前在用CVAVR的時(shí)候發(fā)現(xiàn)里面的delay.h非常好用.于是,利用stm32的SysTick做了個(gè)精確的延時(shí)頭函數(shù).
SysTick的配置在void delay_init(u8 SYSCLK);里面輸入的參數(shù)SYSCLK是你配置的系統(tǒng)時(shí)鐘,比如72M,我就調(diào)用delay_init(72);然后就完成了對(duì)SysTick的初始化設(shè)置.在后面調(diào)用delay_ms(u32 Nms);delay_us(u32 Nus);就可以得到很準(zhǔn)確的延時(shí).
注意:
1,delay_us(u32 Nus);在Nus值很小的時(shí)候,誤差比較大,我仿真的時(shí)候delay_us(1);實(shí)際上得到的是延時(shí)了1.5us左右.理論上Nus的值越大,越準(zhǔn)確.
2,delay_ms(u32 Nms);的參數(shù)不能太大!更具你系統(tǒng)時(shí)鐘來(lái)確定.72M的時(shí)候Nms的最大值是1864.在其他晶振(<72M)條件下,該值會(huì)變大.計(jì)算方法:Nms<=0xffffff*8/SYSCLK.
在包括了這個(gè)頭函數(shù)之后可以得到很準(zhǔn)確的延時(shí),也不會(huì)產(chǎn)生中斷,其他中斷可以打斷delay_us,delay_ms的執(zhí)行.
#ifndef __DELAY_H
#define __DELAY_H
//使用SysTick的普通計(jì)數(shù)模式對(duì)延遲進(jìn)行管理
//包括delay_us,delay_ms
//正點(diǎn)原子@SCUT
//2008/12/13
static u8 fac_us=0;//us延時(shí)倍乘數(shù)
static u16 fac_ms=0;//ms延時(shí)倍乘數(shù)
//初始化延遲函數(shù)
void delay_init(u8 SYSCLK)
{
SysTick->CTRL&=0xfffffffb;//選擇內(nèi)部時(shí)鐘 HCLK/8
fac_us=SYSCLK/8;
fac_ms=(u16)fac_us*1000;
}
//延時(shí)Nms
//注意Nms的范圍
//Nms<=0xffffff*8/SYSCLK
//對(duì)72M條件下,Nms<=1864
void delay_ms(u16 nms)
{
SysTick->LOAD=(u32)nms*fac_ms; //時(shí)間加載
SysTick->CTRL|=0x01; //開(kāi)始倒數(shù)
while(!(SysTick->CTRL&(1<<16))); //等待時(shí)間到達(dá)
SysTick->CTRL&=0XFFFFFFFE; //關(guān)閉計(jì)數(shù)器
SysTick->VAL=0X00000000; //清空計(jì)數(shù)器
}
//延時(shí)us
void delay_us(u32 Nus)
{
SysTick->LOAD=Nus*fac_us; //時(shí)間加載
SysTick->CTRL|=0x01; //開(kāi)始倒數(shù)
while(!(SysTick->CTRL&(1<<16)));//等待時(shí)間到達(dá)
SysTick->CTRL=0X00000000; //關(guān)閉計(jì)數(shù)器
SysTick->VAL=0X00000000; //清空計(jì)數(shù)器
}
#endif
另外的一種方法 :
/*---------------------------------
延時(shí)模塊函數(shù)
說(shuō)明:只需在工程中加入delay.c和delay.h
文件,即可用 Delayms(__IO uint32_t nTime);
Delayus(__IO uint32_t nTime)
-----------------------------------*/
#ifndef __DELAY_H
#define __DELAY_H
#include "stm32f10x.h"
/*---------------------------------
描 述:參數(shù)1即為1ms,1000即為1s;只有幾
us的誤差;
-----------------------------------*/
extern void Delayms(__IO uint32_t nTime);
/*---------------------------------
描 述:參數(shù)1即為1us,1000即為1ms;只有幾
us的誤差;
-----------------------------------*/
extern void Delayus(__IO uint32_t nTime);
/*---------------------------------
函數(shù)名:延時(shí)調(diào)整形式的delaynus函數(shù),
描 述:參數(shù)1即為1us,1000即為1ms;
-----------------------------------*/
extern void delay_nus(unsigned long n);
/*---------------------------------
函數(shù)名:延時(shí)調(diào)整形式的delaynms函數(shù),
描 述:參數(shù)1即為1ms,1000即為1s;
-----------------------------------*/
extern void delay_nms(unsigned long n);
#endif
C 函數(shù)
/*---------------------------------
延時(shí)模塊函數(shù)
說(shuō)明:只需在工程中加入delay.c和delay.h
文件,即可用 Delayms(__IO uint32_t nTime);
Delayus(__IO uint32_t nTime)
-----------------------------------*/
#include"delay.h"
static __IO uint32_t TimingDelay;
/* Private function prototypes -----------------------------------------------*/
/*---------------------------------
函數(shù)名:ms延時(shí)函數(shù)
描 述:參數(shù)1即為1ms,1000即為1s;只有幾
us的誤差;
-----------------------------------*/
void Delayms(__IO uint32_t nTime)
{
while(SysTick_Config(SystemCoreClock/1000));
TimingDelay = nTime;
while(TimingDelay != 0);
SysTick->CTRL=0x00; //關(guān)閉計(jì)數(shù)器
SysTick->VAL =0X00; //清空計(jì)數(shù)器
}
/*---------------------------------
函數(shù)名:us延時(shí)函數(shù)
描 述:參數(shù)1即為1us,1000即為1ms;只有幾
us的誤差;
-----------------------------------*/
void Delayus(__IO uint32_t nTime)
{
while(SysTick_Config(SystemCoreClock/1000000));
TimingDelay = nTime;
while(TimingDelay != 0);
SysTick->CTRL=0x00; //關(guān)閉計(jì)數(shù)器
SysTick->VAL =0X00; //清空計(jì)數(shù)器
}
/*---------------------------------
函數(shù)名:延時(shí)輔助函數(shù)
描 述:
-----------------------------------*/
void TimingDelay_Decrement(void)
{
if (TimingDelay != 0x00)
{
TimingDelay--;
}
}
/*---------------------------------
函數(shù)名:systick的中斷函數(shù)
描 述:參數(shù)1即為1us,1000即為1ms;只有幾
us的誤差;
-----------------------------------*/
void SysTick_Handler(void)
{
TimingDelay_Decrement();
}
/*---------------------------------
函數(shù)名:延時(shí)調(diào)整形式的delaynus函數(shù),
描 述:參數(shù)1即為1us,1000即為1ms;
-----------------------------------*/
void delay_nus(unsigned long n)
{
unsigned long j;
while(n--)
{
j=12;
while(j--);
}
}
/*---------------------------------
函數(shù)名:延時(shí)調(diào)整形式的delaynms函數(shù),
描 述:參數(shù)1即為1ms,1000即為1s;
-----------------------------------*/
void delay_nms(unsigned long n)
{
while(n--)
delay_nus(1030);
}