单片机延时程序有参数延时函数在使用时需要注意哪些问题?

2223人阅读
标题:【转】关于nop()函数
nop函数可以用来延时,请问1个NOP延时多少时间,怎么计算?&附一段说明:void _nop( void );A NOP instruction is generated, before and behind the nop instruction the peephole is flushed. Code generation for _nop() is exactly the same as thefollowing inline assembly.#pragma asm inline nop instruction#pragma endasmReturns nothing.value = P0; /* read from port P0 */MOV R12,P0_nop(); /* delay for one cycle */NOPP1 = /* write to port P1 */MOV P1,R12
单片机c语言中nop函数的使用方法和延时计算默认分类
15:39:40 阅读41 评论0&& 字号:大中小 订阅 .
标准的C语言中没有空语句。但在单片机的C语言编程中,经常需要用几个空指令产生短延时的效果。这在汇编语言中很容易实现,写几个nop就行了。
在keil C51中,直接调用库函数:#include&intrins.h&&&&&&&&&& // 声明了void _nop_(void);
_nop_();&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& // 产生一条NOP指令
&&& 作用:对于延时很短的,要求在us级的,采用&_nop_&函数,这个函数相当汇编NOP指令,延时几微秒。&&&& NOP指令为单周期指令,可由晶振频率算出延时时间,对于12M晶振,延时1uS。
对于延时比较长的,要求在大于10us,采用C51中的循环语句来实现。&在选择C51中循环语句时,要注意以下几个问题&第一、定义的C51中循环变量,尽量采用无符号字符型变量。&第二、在FOR循环语句中,尽量采用变量减减来做循环。&第三、在do&while,while语句中,循环体内变量也采用减减方法。&这因为在C51编译器中,对不同的循环方法,采用不同的指令来完成的。
下面举例说明:&unsigned char I;&for(i=0;i&255;i++);&&&unsigned char I;&for(i=255;i&0;i--);&其中,第二个循环语句C51编译后,就用DJNZ指令来完成,相当于如下指令:&MOV 09H,#0FFH&LOOP:&&&&&&&&&&& DJNZ 09H,LOOP&指令相当简洁,也很好计算精确的延时时间。&同样对do&while,while循环语句中,也是如此&例:&&n=255;&do{n--}&while(n);&或&n=255;&while(n)&{n--};&这两个循环语句经过C51编译之后,形成DJNZ来完成的方法,故其精确时间的计算也很方便。
其三:对于要求精确延时时间更长,这时就要采用循环嵌套的方法来实现,因此,循环嵌套的方法常用于达到ms级的延时。&对于循环语句同样可以采用for,do&while,while结构来完成,每个循环体内的变量仍然采用无符号字符变量。&unsigned char i,j&for(i=255;i&0;i--)&for(j=255;j&0;j--);&或&unsigned char i,j&i=255;&do{j=255;&&&& do{j--}&&&& while(j);&&&& i--;&&&& }&while(i);&或&unsigned char i,j&i=255;&while(i)&{j=255;&while(j)&{j--};&i--;&}&这三种方法都是用DJNZ指令嵌套实现循环的,由C51编译器用下面的指令组合来完成的&MOV R7,#0FFH&LOOP2:&&&&&&& MOV R6,#0FFH&LOOP1:&&&&&&& DJNZ R6,LOOP1&DJNZ R7,LOOP2&这些指令的组合在汇编语言中采用DJNZ指令来做延时用,因此它的时间精确计算也是很简单,假上面变量i的初值为m,变量j的初值为n,则总延时时间为:m&(n&T+T),其中T为DJNZ指令执行时间(DJNZ指令为双周期指令)。这里的+T为MOV这条指令所使用的时间。&同样对于更长时间的延时,可以采用多重循环来完成。只要在程序设计循环语句时注意以上几个问题。
下面给出有关在C51中延时子程序设计时要注意的问题&1、在C51中进行精确的延时子程序设计时,尽量不要或少在延时子程序中定义局部变量,所有的延时子程序中变量通过有参函数传递。&2、在延时子程序设计时,采用do&while,结构做循环体要比for结构做循环体好。&3、在延时子程序设计时,要进行循环体嵌套时,采用先内循环,再减减比先减减,再内循环要好。&unsigned char delay(unsigned char i,unsigned char j,unsigned char k)&{unsigned char b,c;&&&& b="j";&&&& c="k";&&&& do{&do{&&&& do{k--};&&&& while(k);&&&& k="c";&&&& j--;};&while(j);&j=b;&i--;};&&&& while(i);&}&这精确延时子程序就被C51编译为有下面的指令组合完成&delay延时子程序如下:&&&&&&&&&&&&&&&& MOV&&&&& R6,05H&&&&&&&&&&&&&&&& MOV&&&&& R4,03H&C0012:&&&&&&& DJNZ&&&&& R3, C0012&&&&&&&&&&&&&&&& MOV&&&&& R3,04H&&&&&&&&&&&&&&&& DJNZ&&&&& R5, C0012&&&&&&&&&&&&&&&& MOV&&&&& R5,06H&&&&&&&&&&&&&&&& DJNZ&&&&& R7, C0012&&&&&&&&&&&&&&&& RET&&&&假设参数变量i的初值为m,参数变量j的初值为n,参数变量k的初值为l,则总延时时间为:l&(n&(m&T+2T)+2T)+3T,其中T为DJNZ和MOV指令执行的时间。当m=n=l时,精确延时为9T,最短;当m=n=l=256时,精确延时到T,最长。&&&-----------------------------------------------------------------------------------------
采用软件定时的计算方法
利用指令执行周期设定,以下为一段延时程序:&&&&&&指令&&&&&&&&&&& 周期&&MOV&&&&&&&&&&& 1DJNZ&&&&&&&&&&& 2NOP&&&&&&&&&&& 1采用循环方式定时,有程序:&&&&&&&&&&& MOV&&&&& R5,#TIME2&&&&&&&&& ;周期1LOOP1:&&&&& MOV&&&&& R6,#TIME1&&&&&&&&& ; 1LOOP2:&&&&& NOP&&&&&&&&&&&&&&&&&&&&&&& ; 1&&&&& NOP&&&&&&&&&&&&&&&&&&&&&&& ; 1&&&&& DJNZ&&& R6,LOOP2&&&&&&&&&&&&& ; 2&&&&&&&&&&& DJNZ&&&&& R5,LOOP1&&&&&&&&&&& ; 2定时数=(TIME1*4+2+1)*TIM2*2+4
刚刚又学了一条,用_nop_();时记得加上#include& &intrins.h&& 头文件
如://==================#include& &intrins.h&& //包含库函数&&&&&&& ......&&&&&&& ......//============&&&&& ......&&&&& ......&&& _nop_();&&&&&&&&& //引用库函数
敬礼。我一直都是借助仿真软件编。一点一点试时间。
C语言最大的缺点就是实时性差,我在网上到看了一些关于延时的讨论,其中有篇文章
&& 51单片机 Keil C 延时程序的简单研究,作者:InfiniteSpace Studio/isjfk
写得不错,他是用while(--i);产生DJNZ 来实现精确延时,后来有人说如果while里面不能放其它语句,否则也不行,用do-while就可以,具体怎样我没有去试.所有这些都没有给出具体的实例程序来.还看到一些延时的例子多多少少总有点延时差.为此我用for循环写了几个延时的子程序贴上来,希望能对初学者有所帮助.(晶振12MHz,一个机器周期1us.)
&&& 一. 500ms延时子程序
&&& void delay500ms(void)
&&&&&& unsigned char i,j,k;
&&&&&&& for(i=15;i&0;i--)
&&&&&&& for(j=202;j&0;j--)
&&&&&&& for(k=81;k&0;k--);
产生的汇编:
&&& C:0x0800&&& 7F0F&&&& MOV&&&&& R7,#0x0F
&&& C:0x0802&&& 7ECA&&&& MOV&&&&& R6,#0xCA
&&& C:0x0804&&& 7D51&&&& MOV&&&&& R5,#0x51
&&& C:0x0806&&& DDFE&&&& DJNZ&&&& R5,C:0806
&&& C:0x0808&&& DEFA&&&& DJNZ&&&& R6,C:0804
&&& C:0x080A&&& DFF6&&&& DJNZ&&&& R7,C:0802
&&& C:0x080C&&& 22&&&&&& RET&&&&&
&&& 程序共有三层循环
&&& 一层循环n:R5*2 = 81*2 = 162us&&&&&&&&&&&&&&&&& DJNZ& 2us
&&& 二层循环m:R6*(n+3) = 202*165 = 33330us&&&&&&&&& DJNZ& 2us + R5赋值 1us = 3us
&&& 三层循环: R7*(m+3) = 15*33333 = 499995us&&&&&&& DJNZ& 2us + R6赋值 1us = 3us
&&& 循环外:&& 5us&&&&&&&&&&& 子程序调用 2us + 子程序返回 2us + R7赋值 1us& = 5us
&&& 延时总时间 = 三层循环 + 循环外 =
= 500000us =500ms
计算公式:延时时间=[(2*R5+3)*R6+3]*R7+5
&&& 二. 200ms延时子程序
void delay200ms(void)
&&&&&& unsigned char i,j,k;
&&&&&&& for(i=5;i&0;i--)
&&&&&&& for(j=132;j&0;j--)
&&&&&&& for(k=150;k&0;k--);
产生的汇编
C:0x0800&&& 7F05&&&& MOV&&&&& R7,#0x05
C:0x0802&&& 7E84&&&& MOV&&&&& R6,#0x84
C:0x0804&&& 7D96&&&& MOV&&&&& R5,#0x96
C:0x0806&&& DDFE&&&& DJNZ&&&& R5,C:0806
C:0x0808&&& DEFA&&&& DJNZ&&&& R6,C:0804
C:0x080A&&& DFF6&&&& DJNZ&&&& R7,C:0802
C:0x080C&&& 22&&&&&& RET
&&& 三. 10ms延时子程序
void delay10ms(void)
&&&&&& unsigned char i,j,k;
&&&&&&& for(i=5;i&0;i--)
&&&&&&& for(j=4;j&0;j--)
&&&&&&& for(k=248;k&0;k--);
产生的汇编
C:0x0800&&& 7F05&&&& MOV&&&&& R7,#0x05
C:0x0802&&& 7E04&&&& MOV&&&&& R6,#0x04
C:0x0804&&& 7DF8&&&& MOV&&&&& R5,#0xF8
C:0x0806&&& DDFE&&&& DJNZ&&&& R5,C:0806
C:0x0808&&& DEFA&&&& DJNZ&&&& R6,C:0804
C:0x080A&&& DFF6&&&& DJNZ&&&& R7,C:0802
C:0x080C&&& 22&&&&&& RET&&&&&
&&& 四. 1s延时子程序
void delay1s(void)
&&&&&& unsigned char h,i,j,k;
&&&&&&& for(h=5;h&0;h--)
&&&&&&& for(i=4;i&0;i--)
&&&&&&& for(j=116;j&0;j--)
&&&&&&& for(k=214;k&0;k--);
产生的汇编
C:0x0800&&& 7F05&&&& MOV&&&&& R7,#0x05
C:0x0802&&& 7E04&&&& MOV&&&&& R6,#0x04
C:0x0804&&& 7D74&&&& MOV&&&&& R5,#0x74
C:0x0806&&& 7CD6&&&& MOV&&&&& R4,#0xD6
C:0x0808&&& DCFE&&&& DJNZ&&&& R4,C:0808
C:0x080A&&& DDFA&&&& DJNZ&&&& R5,C:0806
C:0x080C&&& DEF6&&&& DJNZ&&&& R6,C:0804
C:0x080E&&& DFF2&&&& DJNZ&&&& R7,C:0802
C:0x0810&&& 22&&&&&& RET
在精确延时的计算当中,最容易让人忽略的是计算循环外的那部分延时,在对时间要求不高的场合,这部分对程序不会造成影响.
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:43663次
排名:千里之外
原创:32篇
(1)(1)(3)(8)(2)(3)(7)(9)(4) 上传我的文档
 下载
 收藏
该文档贡献者很忙,什么也没留下。
 下载此文档
正在努力加载中...
单片机编程实例--单片机C51延时时间怎样计算
下载积分:1000
内容提示:单片机编程实例--单片机C51延时时间怎样计算
文档格式:DOCX|
浏览次数:207|
上传日期: 09:42:38|
文档星级:
该用户还上传了这些文档
单片机编程实例--单片机C51延时时间怎样计算
官方公共微信  很多初学者对于程序中ms级延时函数的编写方法比较疑惑,其原理和方式虽然简单,但是却没有相关资料。这里用一个例程详细介绍一下。
  过程参考如下:
  在编译器下建立一个新项目,也可以利用已有项目。此过程中需要注意,的选择,因为for循环里指令的执行时间和晶振有直接关系,本例中晶振使用11.0592M。
&& & 编写一段关于延时的函数,主要利用for循环,代码如下:void delay_ms(unsigned int ms){& & for(i=0;i&i++)& & {& & & & for(j=0;j&200;j++);& & & & for(j=0;j&102;j++);& & }
& & &其中ms是输入参数,如果输入1,就是要求程序延时1ms。
  j变量是调整程序运行的时间参数。调整j的数值,使1次循环的时间在1ms。
  将此程序编译通过,然后利用软件仿真,调整时间。
两次时间差就是延时函数使用的时间,如果与1ms相差比较多,用户可以调整j参数的值,使延时时间尽量接近1ms。如增大j的值for(j=0;j&105;j++);
  此方法得出延时函数,在晶振不同的情况下,延时时间会不准。另外这种方法不是完全精确的延时,所以不要太深研究误差的问题。软件调试结果,这个程序的延时时间为:1.01779ms,一般的单片机系统中都可以应用。
本网站试开通微、小企业商家广告业务;维修点推荐项目。收费实惠有效果!欢迎在QQ或邮箱联系!
试试再找找您想看的资料
资料搜索:
查看相关资料 & & &
   同意评论声明
   发表
尊重网上道德,遵守中华人民共和国的各项有关法律法规
承担一切因您的行为而直接或间接导致的民事或刑事法律责任
本站管理人员有权保留或删除其管辖留言中的任意内容
本站有权在网站内转载或引用您的评论
参与本评论即表明您已经阅读并接受上述条款
copyright & &广电电器(中国梧州) -all right reserved& 若您有什么意见或建议请mail: & &
地址: 电话:(86)774-2826670&}

我要回帖

更多关于 单片机延时函数 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信