目录
前言
延时函数是嵌入式中最常用到的测试手段,发现有许多方式可以达到延时的目的,所以这里做一点小总结。
一、
1.for/while循环延时
代码如下:
#define SystemCoreClock (26000000U) //时钟频率26M
void delay(int time)
{
for (int i = 0; i < time; i--);
}
时间公式:延时 = time * 2 * 机器周期 * 指令周期 *(1/26M)
链接:*2的原因
2.汇编延时
代码如下:
/*汇编延时*/
#define SystemCoreClock (26000000U) //时钟频率26M
__asm void
SysCtlDelay(unsigned long ulCount)
{
subs r0,#1;
bne SysCtlDelay;
bx lr;
}
//us级延时,延时n微秒
SysCtlDelay(n*(SystemCoreClock/(3*1000000)))
SystemCoreClock: 为单片机时钟频率,使用时需要更改。(一般System_CMSDK_CMx.h里已经设置好了)
SysCtlDelay:ulCount = n*(SystemCoreClock/(3*1000000))
SystemCoreClock/(3*1000000)是因为SysCtlDelay内有3条指令,公式结果为1us。
3.SYSTICK定时器延时
代码如下:
/*SYSTICK定时器延时*/
#define SystemCoreClock (26000000U) //这里是系统时钟,需要根据芯片进行修改
#define MS_DELAY (1000U)
#define US_DELAY (1000000U)
void delay_ms(uint8_t ms) //ms延时函数
{
/* systick delay ms*/
SysTick->CTRL = (1 << 2);
SysTick->LOAD = SystemCoreClock / MS_DELAY * ms;
SysTick->VAL = 0;
SysTick->CTRL = (1 << 2) | (1 << 0);
while ((SysTick->CTRL & (1 << 16)) == 0);
SysTick->CTRL = (1 << 2);
}
SYSTICK相关寄存器
SysTick控制和状态寄存器(STK_CTRL)
一般用来控制systick定时器的开关,使用时需要根据相应的芯片更改相应的位操作。
位 | 寄存器 | 作用 |
16 | COUNFLAG | 定时器倒计数到0时,该为由硬件自动置1 |
2 | CLKSOURCE | 选择时钟分频:1:AHB 0:AHB/(8 or 2) |
1 | TICKINT | 定时器异常请求使能:0:不产生中断,1:产生中断 |
0 | TICKINT | 使能计数器 0:失能,1:使能 |
SysTick自动重装载值寄存器(STK_LOAD)
计数器初始值,自定义,需要自己计算,公式一般如上所示。LOAD的值决定一个时钟频率内产生的中断次数,中断次数为MS_DELAY。
范围一般为:0x00000001~0x00FFFFFF。
SysTick当前值值寄存器(STK_VAL)
每次从LOAD中获取值,直到为0。
相比起前两种,定时器的延时更准确,但是,由于是系统时钟控制,记得使用前保证系统时钟的频率准确。
总结
前两种时钟是CPU时钟,后一个为系统时钟,一般情况下CPU时钟是等于系统时钟的,但当系统时钟出错时,两者便不相等了。写这篇BLOG的目的是在工作中凑巧碰到了需要测量时钟是否准确的情况,所以写了下来分享给其他需要的伙伴。
PS:本人第一篇BLOG 2023/06/10 ----BeMi·Aino