C51 延迟函数编写 [李园7舍_404]

背景:STC89C52

 

1_nop_()

功能:_nop_函数用于在代码中产生一条NOP指令。这条指令能被用来延迟一个机器周期的时间。

返回值:无。

头文件:#include <intrins.h>

 

验证

1.      C51工程的主文件的main函数中测试_nop_()函数执行的时间。在测试之前需要选中当前工程,然后project-->Option for target 项目名-->TargetA,将Xtal(MHz)选项改为单片机的晶振频率,我的STC89C5211.0592MHZ。设置好后点击OK

2. 在main函数含简单的以下语句测试_nop_()函数执行时间:

int i;
i = 0;
_nop_();
i++;


       然后根据keil语句延迟时间精确计算的方法(KEIL语句执行时间的计算)确定执行时间,执行_nop_()前的时间为424.26微妙,执行完_nop_()的时间为425.35微妙,则得到执行此条语句的时间为425.35 – 424.26 = 1.09微妙。计算此单片机的机器周期为12 * 1 /11059200=1.085微妙,4舍5入一下即是1.09微妙。得到的结论是_nop_()语句延迟一个机器周期的时间。

 

2 用循环语句延迟

       因为循环语句被执行时本身也要消耗执行时间,所以单纯的将_nop_()循环的执行多少次延迟时间已经不等于循环次数与机器周期相乘了。所以要得到比较准确的延迟时间时还是需要借助keil的仿真一下代码被执行的时间

 

2.1纯循环语句延迟

       对于晶振为11.0592MHZ的单片机来说,郭天祥师兄已经测试出一种较为精确的循环延迟方式。采用两层循环,内层循环的最大值固定为110,则外层循环次数就相当于延迟的毫秒数。用C语言代码表示如下:

unsigned int i, j;
for(i = delay_ms; i > 0; i--)
    for(j = 110; j > 0; j--);


经测试,当delay_ms的值被设为1000ms(即1s时),这段代码被执行的真实时间为965717微妙,差不多就是1秒了。经测试,当delay_ms的值被设为1000ms(即1s时),这段代码被执行的真实时间为965717微妙,差不多就是1秒了。经测试,当delay_ms的值被设为1000ms(即1s时),这段代码被执行的真实时间为965717微妙,差不多就是1秒了。

 

2.2调用_nop_()延迟

       基于_nop_()这么特殊,刚好延迟一个机器周期的时间,不得不想用用它。但是它延迟的时间实在又是太小了,微妙级的。当只需要延迟一两个微妙的调用这个函数最适合不过了,不过如果需要用_nop_()函数来延迟,则需要用keil软件来计算一下循环语句和_nop_()加起来共花多少时间,然后将此部分设为一个延迟函数,再用产生不大误差的循环语句调用。编写8位最大数(unsigned char)255循环函数

unsigned char i;
for(i = 255; i > 0; i--){
		_nop_();
}


测得的延迟时间为-424.26+2915.58=2491.32微妙测得的延迟时间为-424.26+2915.58=2491.32微妙测得的延迟时间为-424.26+2915.58=2491.32微妙。

 

编写1000次循环函数

for(i = 1000; i > 0; i--){
	_nop_();
}


测得的延迟时间为-425.35+10196.40=9771.05近10ms。

 

编写10000次循环循环函数

for(i = 10000; i > 0; i--){
	_nop_();
}


测得的延迟时间为-425.35 + 98126.09=97700.74,约100ms。

循环5000次的延迟时间为:49276.26 – 425.35 = 48850.91,月50ms。

 

3总结

        如果是要进行简单的延迟,比如消除键盘抖动而需要延迟10ms等就可以用以上提到的用循环语句的方法来延迟。因为根据实际情况分析来说,不需要太过于精确。如果需要精确的延迟肯定是需要用定时器/计数器的。

     还有在程序设计过程中弄混淆了两个个概念:计数器加1操作需要一个机器周期和变量++需要的时间。在编写程序的时候把变量++执行时间算成了一个机器周期,这是不对的,因为一条指令执行前还包括取指令等基本操作,而一个机器周期只完成一个基本操作,所以变量++的执行时间大于机器周期。

 

此次笔记记录完毕。

你可能感兴趣的:(C51 延迟函数编写 [李园7舍_404])