您的位置:首页 > 其它

【记录】实现delay

2016-07-02 11:06 274 查看

1. 实现方法

处理器有一个24位的系统定时器,SysTick。该定时器向下计数。计数到0后,重新从STK_LOAD寄存器中重载计数值,继续向下计数。使用SysTick的优点是,不用占用中断和定时器资源。

2. 相关寄存器

STK_CTRL:

0-bit,计数器使能位;

1-bit,选择时钟源

16-bit,计数到0后,该标志位被置1

STK_LOAD

计数值重载寄存器,当计数值计数到0后,将从该寄存器中重新加载计数值。

STK_VAL

保存当前计数值



#include "delay.h"

static u8 fac_us = 0;
static u16 fac_ms = 0;

void delay_init(u8 sys_clock)
{
SysTick->CTRL &= ~(1<<2);  //external clock
fac_us = sys_clock/8;       //AHB/8
fac_ms = (u16)fac_us*1000;
}

//n < 2^24/fac_us
//sys_clock = 168MHz, fac_us=21MHz, 2^24/fac_us=798915
void delay_us(u32 n)
{
u32 temp;
SysTick->LOAD = n*fac_us;       //connter
SysTick->VAL = 0;               //clear current value
SysTick->CTRL = 0x01;           //start timer

do
{
temp = SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //16-bit will be set 0 when current value is 0

SysTick->CTRL = 0x00;   //stop timer
SysTick->VAL = 0x00;    //clear current value
}

//@sys_clock=168MHz, n < 798
void delay_ms(u16 n)
{
u32 temp;
SysTick->LOAD = (u32)n*fac_ms;
SysTick->VAL = 0x00;
SysTick->CTRL = 0x01;

do
{
temp = SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //16-bit will be set 0 when current value is 0

SysTick->CTRL = 0x00;   //stop timer
SysTick->VAL = 0x00;    //clear current value
}


实现更长的延时(超过798.915ms)。方法是多次调用上面实现的delay_ms。如果需要延时5s。5000ms>798.915ms,所以无法使用delay_ms。按照delay_long_ms的方法,每一个repeat可以延时540ms,repeat=5000/540=9, remain = 5000%540=140。对于用户而言,直接调用

delay_long_ms(5000);


程序中使用540的原因。理论上这个数值越接近798.915越好,但是我们要注意,798915这个值是按照系统时钟168MHz下计算出来的。

2^24*8/clock

而有些时候,系统可以工作在248MHz频率下,超频使用。此时2^24*8/248=541200。考虑到驱动的兼容性,选择540作为单次最大延时时间。

void delay_long_ms(u16 n)
{
u8 repeat = n / 540;
u16 remain = n % 540;

while(repeat)
{
delay_ms(540);
repeat--;
}
if(remain)  delay_ms(remain);
}


参考

STM32F3与 F4 系列 Cortex M4 内核编程手册

STM32F4 开发指南(寄存器版)

STM32F4xxx中文参考手册
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: