一、实现延时的两种方法
1、硬件延时
优点:用到/计数器,这种方法可以提高CPU的工作效率,也能做到;
缺点:往往在精度要求不是很高时,会使定时器/计数器大材小用,而且很极端时,定时器根本不够的。
2、软件延时
优点:节省的同时,只要正确使用可接近要求的精度,这种方法主要采用循环体进行;
缺点:精度不高,对编程者经验要求甚高。
二、硬件延时
1、常用:11.059 2 MHz(容易各种标准的波特率)、12 MHz或6 MHz(机器周期
分别为1 μs和2 μs,便于精确延时)。
2、本程序中假设使用频率为12 MHz的晶振。最长的延时时间可达2的16次方=65 536 。若定时器工作在方式2,则可实现极短时间的精确延时;如使用其他定时方式,则要考
虑重装定时初值的时间(重装定时器初值占用2个机器周期)。
3、在实际应用中,定时常采用中断方式,如进行适当的循环可实现几秒甚至更长时间的延
时。使用定时器/计数器延时从程序的执行效率和两方面考虑都是最佳的方案。但应该注意,编写的中断服务程序编译后会自动加上PUSH ACC、PUSH PSW、POP PSW和POP ACC语句,执行时占用了4个机器周期;如程序中还有计数值加1语句,则又会占用1个机器周期。这些语句所消耗的时间在计算定时初值时要考虑进去,从初值中减去以达到最小误差的目的。
三、软件延时(通过调用延时函数)
1、调用延时函数三要素:
入口周期Te、返回周期Tr、内部代码执行周期Ti
则:该函数总执行周期Tf=Te+Tr+Ti;其中:Ti=循环次数*循环周期N
2、短暂延时
如Delay10us( ):总执行高峰期为10us=2us+6us+2us.
Delay10us()
{
_nop_;
_nop_;
_nop_;
_nop_;
_nop_;
_nop_;
}
说明:不宜嵌套调用,嵌套次数越多误差越大。
3、在C51中嵌套段实现延时
在C51中通过预处理指令#asm和#pragma endasm可以嵌套汇编语言语句。用户编写的汇编语言紧跟在#pragma asm之后,在#pragma endasm之前结束。
如:#pragma asm
…
汇编语言程序段
…
#pragma endasm
延时函数可设置入口参数,可将参数定义为unsigned char、int或g型。根据参数与返回值的传递规则,这时参数和函数返回值位于R7、R7R6、R7R6R5中。在应用时应注意以下几点:
◆ #pragma asm、#pragma endasm不允许嵌套使用;
◆ 在程序的开头应加上预处理指令#pragma asm,在该指令之前只能有注释或其他预处理指令;
◆ 当使用asm语句时,编译系统并不输出目标模块,而只输出汇编源文件;
◆ asm只能用小写字母,如果把asm写成大写,编译系统就把它作为普通变量;
◆ #pragma asm、#pragma endasm和 asm只能在函数内使用。
说明:将汇编语言与C51结合起来,充分发挥各自的优势,无疑是人员的最佳选择。
4、使用确定延时时间
熟悉硬件的开发人员,也可以利用示波器来测定延时程序执行时间。方法如下:编写一个实现延时的函数,在该函数的开始置某个I/O口线如P1.0为高电平,在函数的最后清P1.0为。在主程序中循环调用该延时函数,通过示波器测量P1.0引脚上的高电平时间即可确定延时函数的执行时间。方法如下:
把P1.0接入示波器,运行上面的程序,可以看到P1.0输出的波形为周期是3 ms的方波。其中,高电平为2 ms,低电平为1 ms,即for循环结构“for(j=0;j<124;j++) {;}”的执行时间为1 ms。通过改变循环次数,可得到不同时间的延时。当然,也可以不用for循环而用别的语句实现延时。
说明:这里讨论的只是确定延时的方法。
5、使用计算延时时间
对于不熟悉示波器的开发人员可用C51中的反计算延时时间,在反汇编窗
口中可用和汇编程序的混合代码或汇编代码显示目标应用程序。但要求对于汇编的要熟悉。
说明:此种方法如果你熟悉周期是比较简单的,这里不作详细讨论。
6、使用性能分析器计算延时时间(即:Keil C51的debug技巧)
A51的程序执行时间可能通过指令周期计算出来,而C51的却无从下手,很多程序员为了得到精确的执行时间而研读反汇编代码,何等的悲哀。巧妙的使用Keil中的debug功能,问题就迎刃而解了。
下面举例说明:
该程序为一个延时程序,在12M的晶振下,调用一次的时间为16uS ,执行一次循环的时间为9uS(延时范围(25us~589.831ms))。这样来,假设有语句Delay(N);那么该语句的精确延时的计算公式就是(9*N+16)uS了.这个公式可以理解吧!
如何得到程序的调用时间和执行一次循环的时间了。接着看下面:
在主程序MAIN()函数下添加上面两条语句,当前的SEC栏为执行到DELAY(1);语句所花的时间。T(0-)
上面的SEC栏为执行完DELAY(1)所花的时间,这样就可以得到DEALY(1)这条语句的执行时间为-570=25uS.
上面的SEC栏为执行完DELAY(2)所花的时间,这样就可以得到DEALY(2)这条语句的执行时间为629-595=34uS.
结果不就出来了嘛,T[DELAY(2)]-T[DELAY(1)]不就是执行一次循环的时间嘛,
|