我们如何计算嵌入式C中以下for循环给定的延迟?

问题描述

我试图将LCD(NHD-0240AZ-FL-YBW)连接到TM4C123GH6PMI。这样做时,我应该延迟几毫秒,因此我在Google上进行了搜索。一个人使用以下循环来延迟毫秒。谁能解释它的工作原理?

void DelayMilis(unsigned long ulMilliSeconds)
{
   unsigned long i = 0,j = 0;

   for (i = 0; i < ulMilliSeconds; i++)
   {
     for (j = 0; j < 2000; j++);
   }
}

解决方法

在所有人的应有的尊重下,“这个家伙”在这种实施上做得很糟糕,拖延了时间。

它被认为是如何工作的:
由于嵌套循环,将浪费2000 * ulMilliSeconds个CPU周期,从而延迟了下一次执行。

为什么可能无法这样工作:
因为,编译器会感觉到嵌套循环没有执行任何操作,因此很有可能会优化嵌套循环并从不执行它们。如果您只是执行var = var来欺骗编译器,情况将保持不变。

我很肯定您知道TM4C123GH6PMI是32位ARM Cortex-M4F微控制器,除SysTick之外,数据表中还有6个16/32位定时器模块和6个32/64位定时器模块计时器。

当我是新手时(我想我是!),我将通过以下方式实施延迟。

  • 初始化计时器
  • 在计时器中断处理程序中设置标志和/或增加计数器
  • 在适当的阶段检查应用程序中的标志/计数器

如果我阻止执行,除非计数器达到期望值,则它是基于延迟的实现。如果我让其他应用程序代码在计数器未达到期望值的情况下执行,则它是超时实现。通常优先选择超时而不是延迟,但是超时可能因需求而异。

,

看来,在“这个家伙”的平台上,您提到一个空的for循环,该循环从0到1999(for (j = 0; j < 2000; j++);)大约需要一毫秒。因此,如果您重复ulMilliSeconds次,程序将执行ulMilliSeconds毫秒的延迟。

在您的平台上这可能有所不同,因此您可能需要确定并适应内部for循环,如果您的平台速度是“此人”的两倍,则可能需要for (j = 0; j < 4000; j++);

请注意:

for (j = 0; j < 2000; j++);

与此相同:

for (j = 0; j < 2000; j++)
{
   // do nothing
}

OTOH这种创建延迟的方法可能会失败,因为编译器可能只是优化了空循环。通常,延迟是使用您的微控制器可能具有的计时器进行编程的。

,

在您的解决方案中,控制器将大部分时间浪费在无用的循环中,这浪费了CPU周期和能源。 更好的解决方案是通过频率为t / 2(例如5ms)的定时器中断驱动LCD,将要写入的数据放入环形缓冲区中,或类似地在每个周期发送一次。 只需确定,如果电路未准备好信号,则将其全部保留并在下一个周期写入。 通过这种方法,CPU可以用于计算,并且如果不执行任何操作,则可以完全空闲。 顺便说一句:这种循环经常被优化掉。

@Yunnosch:谢谢您的建议。我希望我的观点现在更加客观和明确。

,

虽然写延迟循环不是更好的方法,但肯定是最简单的设计,尤其是在很短的时间内。另一方面,由于执行时间的不确定性,这些循环通常需要进行一些调整。时间取决于编译器的优化,处理器中的管道和缓存。

一些专门为嵌入式世界设计的编译器可能具有特殊的#pragmas或其他功能,以优化空循环。例如,某些编译器以特殊方式处理NOP指令(插入了诸如__nop()之类的内在函数)。有时NOP也有一定的执行时间。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...