前言
如果项目中需要实现us级延时,可以使用_nop_()函数来实现,同时补充一下关于指令周期,机器周期,时钟周期的相关理解。
一、nop指令
_nop_() 函数产生的是 NOP 指令。
NOP指令是编程语言中一个经常用到的指令,它的全称是 No Operation,即无操作指令。
1. NOP 指令的作用
延时:通过 NOP 指令产生一定的延迟,这与CPU的频率有关系,适用于一些频率低的单片机场合。可以产生us级延时。指令对齐:我们知道,指令、数据对齐可以有效地提高程序的性能, 使用 NOP 指令,可以使得指令按字对齐,从而提高效率 。
比如一条指令占用 3 个字节,再加上一个 NOP 指令,就使得指令 4 字节对齐了。计算机在输入或者输出的过程中,使用 NOP 指令可可以很好的等待计算机缓冲区清空,等待总线恢复正常,其实也算是延时的一种了
二、NOP延时
1. 使用方法
我们主要使用nop指令进行us级延时,使用方法为:
__NOP(); //HC32单片机
以上方式实际上是通过内嵌汇编的方式进行调用,其具体语法如下:
__asm volatile ("NOP");
2. 时间计算
一个 nop 表示一个机器周期,而机器周期与系统时钟频率有关。
时钟频率机器周期8KHz1/8 us=125ns72MHz1/72 us = 13.89ns3. 使用NOP延时注意事项
NOP指令不能保证延迟时间,其执行时间受到多种因素的影响,如系统时钟频率、芯片负载等;在需要高精度延迟时,推荐使用定时器;NOP指令使用不当会导致CPU空转,浪费资源,因此应尽量减少NOP指令的使用。
三、函数调用对延时的影响
void delay_us(uint32_t Delay)
{
uint32_t cnt = Delay * 8;// 8Mhz,8*1000*125=1000000ns = 1000us
uint32_t i = 0;
for(i = 0; i < cnt; i++)__NOP();
}
调用函数会占用时间,结果远超过想要的nop延时数倍,例如延时10us,结果可能达到 ms 级。
实际应该减少for循环的函数调用,例如下面这样:
void delay_us(uint32_t Delay)
{
uint32_t cnt = Delay * 8;// 8Mhz,8*1000*125=1000000ns = 1000us
uint32_t i = 0;
for(i = 0; i < cnt; i+=10) //注意 i+=10
{
__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();
//8个__nop()相当于执行了10个__nop();
}
}
结语
_NOP()延时在程序中其实是比较少用到的,在软件IIC等不需要精准us延时的情况下可以使用。
要实现精准的us级延时,还是要使用定时器。