呵呵,您能知道51单片机的精确延时吗?
点击“ Bigfish Robot”在上方,选择“顶级/星级官方帐户”;干货为福利,他们将尽快交付!前言对于某些需要较高时间精度的程序,用c编写延迟似乎有些无能为力,因此需要汇编器。
我通过了测试,并总结了51个精确的延迟函数(嵌入在C语言的汇编语言中)与您分享。
至于如何在c中嵌入程序集,您可以在线检查。
这个区域有许多简单的材料。
以一个12MHz的晶体振荡器为例,一个12MHz的晶体振荡器的机器周期为1us,因此执行单周期指令(如NOP指令)所花费的时间为1us。
让我在下面详细解释。
如果要延迟1us,可以调用_nop_();。
函数,此函数为c函数,等效于NOP指令。
使用它时,必须包含头文件intrins.h。
例如:#include #include void main(void){P1 = 0x0; _nop_(); //延迟1us P1 = 0xff;}延迟5us,则可以编写一个delay_5us()函数delay_5us(){#pragma asm nop#pragma endasm}这是一个延迟为5us的函数,只需要调用此函数当您需要延迟5us。
有人可能会问,只有一条NOP指令时5us的延迟如何?答案是:调用此函数时,需要一条调用指令,该指令消耗2个周期(即2us)。
要在函数执行后返回调用函数,需要一条返回指令,该指令消耗2个周期(2us)。
通话和返回成本2us + 2us = 4us。
然后,添加NOP命令会消耗1us,不是5us吗?延迟10us。
我们编写了一个delay_10us()函数delay_10us(){#pragma asmnopnopnopnopnopnop#pragma endasm}这是一个延迟为10us的函数。
像延迟5us函数一样,调用和返回消耗4us,加上函数6us中的6条NOP指令,恰好是10us。
目前,有些人不禁要问,那么该函数应如何写一微秒呢?慢慢地看着我:首先,我不希望延迟任何微秒,但是我可以延迟任何微秒或延迟。
任何奇数个微秒,即需要两个函数,一个函数专用于实现任何偶数个微秒的延迟,而另一个功能专用于实现任何奇数个微秒的延迟。
只要有这两个功能,您可以延迟任何微秒吗?首先,让我们实现任何偶数微秒的延迟:void delay_even_us(unsigned char even){//任何偶数微秒的延迟#pragma asm1 mov a,r7 //为什么使用r7,因为在r7中安装了什么是函数的参数! ! ! // ^ _ ^这个句子消耗1个周期2 subb a,#10H //这个句子消耗1个周期3 mov b,在阅读程序之后,我将解释这句话句子消耗2个周期4 div a ///这个句子的意思是a / b,商放在a中,余数放在b中。
解释这个语句消耗4个周期5 mov r0,a //这个语句消耗1个周期6 nop //这个语句消耗1个周期7循环:8 djnz r0,循环//不等于0跳转指令,也就是说,如果r0中的值不为0,则跳转到循环。
这句话耗时2个周期#pragma endasm}接下来,让我们分析为什么这样写:为方便分析,我给句子编号。
让我们以100us的延迟为例(delay_even_us(100))。
首先减去调用的4个周期(4us)并返回。
然后减去参数传输消耗的2个周期。
因为c函数参数被传递给程序集,所以需要周期。
总共消耗了6个周期。
也就是说,消耗了6us,剩下了100us-6us = 94us。
然后查看对我的程序进行注释的每个语句所消耗的时间:从1个句子到5个句子,总共消耗了10个周期(不要相信您数^ _ ^)。
剩下94us-10us = 84us。
现在来看第八句,该句应消耗84个周期才能达到100us的延迟。
并且该语句的每次执行都消耗2个周期,这意味着r0的值应为84/2 = 42。
那么,如何实现r0 = 42?让我们从第一句话开始分析:在第一句话中,r7是c传递的参数,在此示例中为100。
执行完此语句后,a的值为100;在第二句中,a = a-16 = 100-16 = 84。
在此句子结尾之后,a的值为84;在第三句中,将值2分配给b;在第四句中,将a除以b。
结果商存储在a中,余数存储在b中。
在该句子的结尾之后,a的值是a = a / b = 84/2 = 42;在第五句中,将a的值分配给r0。
在该句子结尾之后,r0的值为:The value is42。
从那时起,r0的值为42。
此目标得以实现。
结合之前的分析,此程序是否延迟了100us?我的答案