头文件delay.h, delay_basic.h

来源:互联网 发布:qq三国js带什么宠物 编辑:程序博客网 时间:2024/05/22 10:56

第一次深入到编译器的底层,虽然深度很浅,但是一次不错的尝试。

 

延时函数的好处是:提供延时的时间,而不是循环次数或时钟周期。当然,程序在后台将前者转换为后者。

 

之所以要使用编译器提供的延时函数,是因为在编译时,编译器会将常量表达式优化掉,比如说while(i),而浮点表达式不会被优化掉,delay.h提供的就是浮点表达式控制的延时函数。

原文:The idea behind is that compile-time constant expressions will be eliminated by compiler optimization so floating-point expressions can be used to calculate the number of delay cycles needed based on the CPU frequency passed by the macro F_CPU.

 

延时函数要正常工作要满足以下2个条件:

  1. 允许编译器进行优化;
  2. 延时的时间在编译时必须是一个确定的量,而不是依赖于其它变量的表达式;

否则,延时的时间会比预期的要长,并且应用程序的代码会急剧地膨胀(因为链接了浮点库函数)。

注:当毫秒延时超过最大值时,有一条语句_delay_loop_2(((F_CPU) / 4e3) / 10),如果不进行优化,每过0.1ms,重复的浮点运算便会被执行一次。

注:延时与优化之间的关系可以通过示波器确定。

 

先说delay.h,刚开始的几段是关于权利说明的,希望有一天自己也能为开源软件做一分贡献。

汗,刚开始的这两个宏就看不懂,以后补上:

#ifndef _UTIL_DELAY_H_
#define _UTIL_DELAY_H_ 1

 

这两个文件包含是delay.h的基础:

#include <inttypes.h>
#include <util/delay_basic.h>

 

使用宏定义F_CPU(单位为Hz,可以使用科学计数法,如#define F_CPU 14.7456E6),否则延时函数会提出警告并将F_CPU设置为默认的1000000UL。

 

_delay_ms()使用的底层函数是_delay_loop_2(),后者每迭代一次需要4个时钟周期。

The maximal possible delay is 262.14 ms / F_CPU in MHz.给出了延时的范围,当晶振频率为1MHz时,最大时间为262.14 ms,当频率增大时,相应减小,反之亦然。这是由counter的字长决定的。

当所需延时超过允许的最大值时,_delay_ms()会以1/10 ms的分辨率进行延时,最长延时可以达到6.5535 seconds。

 

_delay_ms()函数,关键的一句是__tmp = ((F_CPU) / 4e3) * __ms。

F_CPU/1000得到的是每ms的时钟数,再除以4得到的是每ms需要迭代_delay_loop_2()的次数,最后乘以__ms,得到的就是延时相应时间所需的迭代次数。

如果迭代次数大于65535,则将__tmp除以10。得到每0.1ms所需的迭代数,范围仍在65535内,可以正确调用_delay_loop_2()函数,用ms乘10作为counter。

如果迭代次数小于65535,则用__tmp作为counter。

 

_delay_us()函数与_delay_ms()函数类似,只是当迭代次数大于255时,调用_delay_ms()函数函数。

_delay_us()使用的底层函数是_delay_loop_1(),后者每迭代一次需要3个时钟周期。

 

_delay_loop_1(),_delay_loop_2()

被设计用来执行较短的忙等待,在延时的时候,为了确保准确性,不应该有其他的处理发生,但它们并不禁止中断,这意味着中断可能会导致延时不准确。

对于较长的延时,用硬件上的定时器比较合适,因为定时器并不占用CPU,而且能够使用预分频器以获得较长的延时。但是,对于较短的延时来说,会频繁地设定硬件定时器,“经常开销”相对于总的延时时间来说会比较多,意即延时不准确。

 

理解到此,暂时不懂内联函数,也不清楚这两个函数的执行周期是如何计算的,好象是汇编语言。

原创粉丝点击