nop指令和nop延时计算

前言

如果项目中需要实现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级延时,还是要使用定时器。