利用STM32的SysTick设计精确延时函数

在项目中使用I2C接口传感器时要求有比较精确的延时,在网上搜了下,如果不想用中断SysTick定时器可以做到,找到如下资料:

主要仿照原子的《STM32不完全手册》。SYSTICK 的时钟固定为HCLK 时钟的1/8,在这里我们选用内部时钟源72M,所以SYSTICK的时钟为9M,即SYSTICK定时器以9M的频率递减。SysTick 主要包含CTRLLOADVALCALIB 个寄存器,

SysTick->CTRL

位段

名称

类型

复位值

描述

16

COUNTFLAG

R

0

如果在上次读本寄存器后systick已为0,则该位为1,若 读该位自动清零

2

CLKSOURCE

RW

0

0:外部时钟源 1:内部时钟

1

TICKINT

RW

0

0:减到0无动作;1:减到0产生systick异常请求

0

ENABLE

RW

0

systick定时器使能位

    

SysTick-> LOAD

位段

名称

类型

复位值

描述

23:0

RELOAD

RW

0

减到0时被重新装载的值

SysTick-> VAL

位段

名称

类型

复位值

描述

23:0

CURRENT

RW

0

读取时返回当前倒计数的值,写则清零,同时还会清除在systick控制及状态寄存器中的COUNTFLAG 标志

SysTick-> CALIB 不常用,在这里我们也用不到,故不介绍了。


/*定时器初始化函数*/
void Delay_Init(u8t SYSCLK) //SYSCLK为系统时钟频率除以1000000后的值,例:如果系统时钟频率为72MHz,则调用该函数时此处的实参为72
{
	SysTick->CTRL&=0xFFFFFFFB;
	fac_us=SYSCLK/8;
	fac_ms=(u16t)(fac_us*1000);		
}

/*1微秒延时函数*/
void Delay_us(u32t nus)
{
	u32t temp;
	SysTick->LOAD=nus*fac_us;
	SysTick->VAL=0x00;
	SysTick->CTRL=0x01;
	do
	{
		temp=SysTick->CTRL;
	}
	while(temp&0x01&&!(temp&0x10000));
	SysTick->CTRL=0x00;
	SysTick->VAL=0x00;	
}

/*1毫秒延时函数*/
void Delay_ms(u16t nms)
{
	u32t temp;
	SysTick->LOAD=(u32t)(nms*fac_ms);
	SysTick->VAL=0x00;
	SysTick->CTRL=0x01;
	do
	{
		temp=SysTick->CTRL;
	}
	while(temp&0x01&&!(temp&0x10000));
	SysTick->CTRL=0x00;
	SysTick->VAL=0x00;	
}


你可能感兴趣的:(嵌入式)