0%

基于STM32实现系统精确延时与获取micro时间函数的实现

在编程中经常需要精确的延时,或者需要精确的统计一段代码的执行时间,亦或者是需要精确的保证某段代码被调用的频率。比如需要统计某个函数的执行时间,从而判断开销,又比如在飞控中需要精确的保证每隔 2m 调用一次读取传感器的函数,可以使用定时器去实现。在 STM32 平台上,我们可以充分的利用 systick 去实现。

下边是源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
static volatile uint32_t sysTickMillis = 0;
static uint32_t sysTickPerUs = 72; /* 系统时钟频率 - 72MHz */

/* 检查是否溢出 */
static int systick_check_underflow(void)
{
return SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk;
}

/* systick 中断服务程序 */
void SysTick_Handler(void)
{
__disable_irq();
systick_check_underflow();
sysTickMillis++;
__enable_irq();
}

/* systick 初始化 */
void systick_init(void)
{
sysTickPerUs = SystemCoreClock / 1000000;
SysTick_Config(SystemCoreClock / 1000);
}

/* 获取系统当前的 micro 数值 */
uint32_t micros(void)
{
uint32_t cycle, timeMs;

do{
timeMs = sysTickMillis;
cycle = SysTick->VAL;
__ASM volatile("nop");
}while (timeMs != sysTickMillis);

if (systick_check_underflow())
{
timeMs++;
cycle = SysTick->VAL;
}

return (timeMs * 1000) + (SysTick->LOAD + 1 - cycle) / sysTickPerUs;
}


uint32_t millis(void)
{
return sysTickMillis;
}

/* 微秒延时函数 */
void delay_us(u32 us)
{
static int currentTime, lastTime = 0;
lastTime= micros();

while(1)
{
currentTime= micros();
if ( currentTime - lastTime >= us )
{
break;
}
}
}

/* 毫秒延时函数 */
void delay_ms(u32 ms)
{
static int currentTime, lastTime = 0;
lastTime= millis();

while(1)
{
currentTime= millis();
if( currentTime - lastTime >= ms )
{
break;
}
}
}

使用方法 :
在 main 函数中调用 systick_init() 进行初始化
调用 delay_us 函数实现 us 级延时
调用 delay_ms 函数实现 ms 级延时

计算代码的执行时间 :

1
2
3
4
last = micro();
... /* 需要被统计的代码/函数 */
cur = micro();
usetime = cur - last;

在 FreeRTOS 下的移植

由于在 FreeRTOS 下,systick 被系统占用,因此不能直接使用该方式去实现,需要稍作修改。

A、 将原来的 sysTickMillis变量声明为全局变量, 以便于在其他地方可以调用

B、 将 systick_check_underflow();函数声明为外部,可以在port.c 中被调用

C、 删除原来的 Systick中断处理函数,并将函数中的处理代码添加到 port.c 的 xPortSysTickHandler 函数中即可

1
2
systick_check_underflow();
sysTickMillis++;

D、删除 systick_init 函数

E、 micros 以及 delay_ms 等函数保持不变即可
————————————————
原文链接:https://blog.csdn.net/zhou0842/article/details/53574093