当使用单片机时,我们经常遇到需要短时间延迟的情况。所需的延迟时间非常短,通常为数十到数百微秒(us)。有时需要高精度。例如,当使用单片机驱动DS18B20时,允许的误差范围在十几码之内,否则很容易出错。在这种情况下,使用计时器通常很麻烦。在极端情况下,计时器甚至被用于其他目的。这时,我们需要考虑其他方式。以前使用汇编语言编写MCU程序时,此问题相对容易解决。例如,使用12MHz的晶体振荡器51,打算延迟20us,只要以下代码可以满足一般需要:51单片机的指令周期是晶体振荡器频率的1/12,即, 1us的周期。 mov r0,#09h需要2个极限周期,而djnz也需要2个极限周期。那么,存储在r0中的数字为(20-2)/ 2。使用这种方法,可以非常方便地实现小于256us的延迟。如果需要更长的时间,则可以使用两个级别的嵌套。而且精度可以达到2us,一般来说,这就足够了。现在,毫无疑问,Keil的C编译器得到了更广泛的使用。与汇编相比,C当然具有许多优点,例如程序易于维护,易于理解,适用于大型项目。但是缺点(我认为这是C的唯一缺点)是无法保证实时性能,并且无法预测代码执行的指令周期。因此,在实时性要求较高的场合,还需要组合件和C的联合应用。但是是否需要使用汇编程序来实现这样的延迟程序?为了找到这个答案,我做了一个实验。要使用C语言实现延迟程序,首先想到的是C中常用的loop语句。以下代码是我在Internet上经常看到的代码:该代码的准确性如何?为了直接衡量此代码的效果,我发现了Keil C基于此代码生成的汇编代码:我真的不知道~~~我可以看到这个延迟程序有多不准确~~~在这四个主要语句中,需要6个机器周期。换句话说,它的准确度最高为6us,其中不包括lcall和ret。如果我们列出调用函数时分配的i值的根延迟长度,则为:因为函数调用需要2个时钟周期的lcall,所以延迟时间比从函数代码的执行时间长2倍。顺便说一句,有些朋友写了这段代码:有些人可能认为它将生成更长的汇编代码,但事实证明生成的代码是相同的。但这确实不是一个好习惯。因为实际上没有必要在此处引入额外的变量。我们继续讨论这个话题。一些朋友甚至使用此代码来获得更长的延迟:此代码生成的汇编代码是什么?实际上,您不必考虑它就知道$#^%&%$有多可怕。 ....让我们看看:呵呵,这确实可以延迟很长时间~~~但是根本没有精度。那么,使用C可以实现准确的延迟吗?我对代码进行了一些更改:因为根据经验,更简洁的C代码通常可以导致更简洁的机器代码。这是什么结果?取出它生成的汇编代码并对其进行查看。希望我按了“构建目标”按钮,结果是沉重的打击:尽管生成的代码与使用for语句不同,但是我可以毫无疑问地说这两种方法的效率是相同的。 。似乎到此结束,因为我真的想不出任何简化源程序的空间。看来我即将得出这个结论:“如果您需要我们级别的延迟精度,请在需要时使用汇编语言。”但这是真的吗?我仍然不甘心。因为我不相信著名的Keil C编译器甚至不能使用djnz? ? ?因为实际上在程序主体中仅需要一个句子循环:djnz r7,循环。几乎是绝望的(在这种情况下人们通常会爆发,哦哈哈哈~~~),我只是更改了它:不在意地编译,请看源代码:天堂~~~出现了奇迹。 .....我认为该程序应该已经能够满足一般需求。如果创建表:计算延迟时间时,已计算调用函数的lcall语句的2个时钟周期。最后,结果很明显。只要合理使用,C仍然可以达到意想不到的结果。许多朋友抱怨C的效率比汇编的要差得多。实际上,如果您对Keil C的编译原理有更深入的了解,则可以通过适当的语法用法来优化生成的C代码。前夕