51单片机延时软件延时为什么不准确

51单片机程序中加了中断就卡在延时程序中了??? - 知乎1被浏览343分享邀请回答0添加评论分享收藏感谢收起电源网牵头联合芯派实验室和是德科技联手为电源网网友提供的福利...
2017慕尼黑上海电子展在即,跟电源网一起去看展。...
2017年慕尼黑上海电子展,AOS万国半导体专题报道。...
牛逼1000帖
宁波江北华瑞电子有限公司
深圳麦格米特电气股份有限公司
最新技术探讨
阅读两个产品测评进行回帖讨论,每人两个奖品;
会议主题:福禄克热像现场案例及使用技术研讨
会议时间:
主讲嘉宾:
Fluke 技术1
报名人数:600人
晶川专家 陈战国
英飞凌专家宋清亮
会议主题:中国工程师巡回培训会-上海站
会议时间:
会议地点:上海铭德大酒店
报名人数:392
两种单片机定时器延时程序常见问题解答
来源:电源网
作者:柚子
单片机定时器在51单片机的应用过程中,具有控制程序时间的重要作用,一些延时程序或中断程序也都是需要通过单片机定时器来完成操作的。在今天的文章中,我们将会为大家分享两种定时器延时程序的常见问题解答,希望能够对新人工程师的程序学习和实际操作有所帮助。
第一个问题:单片机延时程序的延时时间怎么计算的?
这个问题是很多新手在学习单片机程序时都会遇到的。如果想要用循环语句实现的循环,那是没法计算的,智能通过软件仿真看到具体时间,但是一般精精确延时是没法用循环语句实现的。如果想精确延时,那么就必须合理的利用单片机定时器来完成设置了。通常来说,定时器延时时间与晶振有关系,单片机系统一般常选用11.059,2MHz、12MHz或6MHz晶振。第一种更容易产生各种标准的波特率,后两种的一个机器周期分别为1μs和2μs,便于精确延时。本程序中假设使用频率为12MHz的晶振。最长的延时时间可以达到216=65536
μs。若定时器工作在方式2,则可实现极短时间的精确延时。如使用其他定时方式,则要考虑重装定时初值的时间,这里需要注意一个问题,那就是重装定时器初值占用2个机器周期,计算时需要加以考虑。
第二个问题:有没有可以让单片机89S51,12M定时器延时10分钟、控制1个灯的方法?
这一问题是定时器在进行延时程序的编写时,非常常见的一个基础性问题。面对这种情况时,我们可以设50ms中断一次,定时初值,TH0=0x3c、TL0=0xb0,中断20次为1S。如果需要让定时器延时10分钟的话,那么需要中断12000次。计12000次后,给IO口一个低电平。如功率不够,可再加扩展,这时就可以控制灯了。
在这种单片机定时器程序的计算过程中,工程师需要首先确认一下使用什么语言计算。汇编延时准确,知道单片机工作周期和循环次数即可算出,但不具有可移植性,在不同种类单片机中,汇编不通用。用c的话,由于各种软件执行效率不一样,不会太准,通常用定时器做延时或做一个不准确的延时,延时短的话,在c中使用汇编的nop做延时程序的编写即可。
声明:本网站原创内容,如需转载,请注明出处;本网站转载的内容(文章、图片、视频)等资料版权归原网站所有。如我们采用了您不宜公开的文章或图片,未能及时和您确认,避免给双方造成不必要的经济损失,请电邮联系我们,以便迅速采取适当处理措施;欢迎投稿,邮箱:。
申请条件:企业邮箱注册
申请条件:企业邮箱注册
热门职位平均薪酬职位数
16-01-11 09:20
15-12-10 09:25
15-12-03 09:37
15-11-26 09:41
15-11-19 09:25
电源网牵头联合芯派实验室和是德科技联手为电源网网友提供的福利活动—即“免费带你走进国内最权威的CNAS&ILAC认证实验室—西安功率器件测试应用中心”活动圆满举办成功。
<font color="#17年电源网工程师巡回培训会-上海站于9月16日召开,会议共计6个议题有近230的工程师到场参与,陶显芳陶老师分享了关于"EMI传导干扰滤波电路的设计“议题,将现场工程师交流推向了高潮!
Displaytech 与全球电子元器件分销商 Digi-Key Elec..
在尝试制作这个四旋翼飞控的过程中,我感触颇多,在..
第一层是我来了。处在这一层的典型是可以用C语言写简..
中国电子银行网最新梳理的一周安全要问中,特别提到..
做芯片设计肯定有野心自己做一款处理器,无论市面上..
2017慕尼黑上海电子展
关于电源网
我们的服务
服务时间:周一至周五9:00-18:00
免费技术研讨会
获取一手干货分享
电源网版权
增值电信业务经营许可证:津B2-
网博互动旗下网站:查看: 1037|回复: 1
51单片机在RC522时为什么1602液晶中延时函数多了之后程序执行不对
在RC522时为什么1602液晶中延时函数多了之后程序执行不对
供应13.56M非接芯片,兼容CV520,RC522,RC523,FM17520,FM17522.具有绝对成本优势。有意者可加QQ
Powered by技术小站:
厂商活动:
地点:北京
时间:10月14日 13:00 - 17:30
地点:北京
时间:10月16日 14:00 - 17:00
地点:武汉
时间:10月19日 9:00 - 18:00
地点:深圳
时间:11月8日 13:00 - 17:30
零基础快速成为Android项目开发工程师
ARM裸机开发实战(第1期加强版)
张飞硬件设计与开发视频教程
从0到1自己动手写嵌入式操作系统
张飞电子视频全套共十部
移入鼠标可放大二维码
使用Keil C进行51单片机延时程序编写的几点心得
来源:本站整理
作者:佚名日 14:46
[导读] 应用单片机的时候,经常会遇到需要短时间延时的情况。需要的延时时间很短,一般都是几十到几百微妙(us)。有时候还需要很高的精度,比如用单片机驱动 DS18B20的时候,误差容许的范围在十几us以内,不然很容易出错。
  应用单片机的时候,经常会遇到需要短时间延时的情况。需要的延时时间很短,一般都是几十到几百微妙(us)。有时候还需要很高的精度,比如用单片机驱动 DS18B20的时候,误差容许的范围在十几us以内,不然很容易出错。这种情况下,用计时器往往有点小题大做。而在极端的情况下,计时器甚至已经全部派上了别的用途。这时就需要我们另想别的办法了。
  以前用汇编语言写单片机程序的时候,这个问题还是相对容易解决的。比如用的是12MHz晶振的51,打算延时20us,只要用下面的代码,就可以满足一般的需要:
  mov   r0, #09h
  loop:  djnz  r0, loop
  51 单片机的指令周期是晶振频率的1/12,也就是1us一个周期。mov r0, #09h需要2个极其周期,djnz也需要2个极其周期。那么存在r0里的数就是(20-2)/2。用这种方法,可以非常方便的实现256us以下时间的延时。如果需要更长时间,可以使用两层嵌套。而且精度可以达到2us,一般来说,这已经足够了。
  现在,应用更广泛的毫无疑问是Keil的C编译器。相对汇编来说,C固然有很多优点,比如程序易维护,便于理解,适合大的项目。但缺点(我觉得这是C的唯一一个缺点了)就是实时性没有保证,无法预测代码执行的指令周期。因而在实时性要求高的场合,还需要汇编和C的联合应用。但是是不是这样一个延时程序,也需要用汇编来实现呢?为了找到这个答案,我做了一个实验。
  用C语言实现延时程序,首先想到的就是C常用的循环语句。下面这段代码是我经常在网上看到的:
  void delay2(unsigned char i)
  for(; i != 0; i--);
  到底这段代码能达到多高的精度呢?为了直接衡量这段代码的效果,我把 Keil C 根据这段代码产生的汇编代码找了出来:
  ; FUNCTION _delay2 (BEGIN)
  ; SOURCE LINE # 18
  ;---- Variable &i& assigned to Register &R7& ----
  ; SOURCE LINE # 19
  ; SOURCE LINE # 20
  0000     ?C0007:
  0000 EF        MOV   A,R7
         JZ   ?C0010
  0003 1F        DEC   R7
  0004 80FA       SJMP  ?C0007
  ; SOURCE LINE # 21
  0006     ?C0010:
  0006 22        RET
  ; FUNCTION _delay2 (END)
  真是不看不知道~~~一看才知道这个延时程序是多么的不准点~~~光看主要的那四条语句,就需要6个机器周期。也就是说,它的精度顶多也就是6us而已,这还没算上一条 lcall 和一条 ret。如果我们把调用函数时赋的i值根延时长度列一个表的话,就是:
  i  delay time/us
  0  6
  1  12
  2  18
  因为函数的调用需要2个时钟周期的lcall,所以delay time比从函数代码的执行时间多2。顺便提一下,有的朋友写的是这样的代码:
  void delay2(unsigned char i)
  for(a = a != 0; a--);
  可能有人认为这会生成更长的汇编代码来,但是事实证明:
  ; FUNCTION _delay2 (BEGIN)
  ; SOURCE LINE # 18
  ;---- Variable &i& assigned to Register &R7& ----
  ; SOURCE LINE # 19
  ; SOURCE LINE # 21
  ;---- Variable &a& assigned to Register &R7& ----
  0000     ?C0007:
  0000 EF        MOV   A,R7
         JZ   ?C0010
  0003 1F        DEC   R7
  0004 80FA       SJMP  ?C0007
  ; SOURCE LINE # 22
  0006     ?C0010:
  0006 22        RET
  ; FUNCTION _delay2 (END)
  其生成的代码是一样的。不过这的确不是什么好的习惯。因为这里实在没有必要再引入多余的变量。我们继续讨论正题。有的朋友为了得当更长的延时,甚至用了这样的代码:
  void delay2(unsigned long i)
  for(; i != 0; i--);
  这段代码产生的汇编代码是什么样子的?其实不用想也知道它是如何恐怖的$#^%&%$.。..。.让我们看一看:
  ; FUNCTION _delay2 (BEGIN)
  ; SOURCE LINE # 18
      R   MOV   i+03H,R7
      R   MOV   i+02H,R6
      R   MOV   i+01H,R5
      R   MOV   i,R4
  ; SOURCE LINE # 19
  ; SOURCE LINE # 20
  0008     ?C0007:
  0008 E4        CLR   A
  0009 FF        MOV   R7,A
  000A FE        MOV   R6,A
  000B FD        MOV   R5,A
  000C FC        MOV   R4,A
  000D AB00    R   MOV   R3,i+03H
  000F AA00    R   MOV   R2,i+02H
      R   MOV   R1,i+01H
      R   MOV   R0,i
  0015 C3        CLR   C
     E   LCALL  ?C?ULCMP
  A       JZ   ?C0010
  001B E500    R   MOV   A,i+03H
  001D 24FF       ADD   A,#0FFH
  001F F500    R   MOV   i+03H,A
      R   MOV   A,i+02H
  0023 34FF       ADDC  A,#0FFH
      R   MOV   i+02H,A
      R   MOV   A,i+01H
  0029 34FF       ADDC  A,#0FFH
  002B F500    R   MOV   i+01H,A
  002D E500    R   MOV   A,i
  002F 34FF       ADDC  A,#0FFH
      R   MOV   i,A
         SJMP  ?C0007
  ; SOURCE LINE # 21
  0035     ?C0010:
  0035 22        RET
  ; FUNCTION _delay2 (END)
  呵呵,这倒是的确可以延迟很长时间~~~但是毫无精度可言了。
  那么,用C到底能不能实现精确的延时呢?我把代码稍微改了一下:
  void delay1(unsigned char i)
  while(i--);
  因为根据经验,越简洁的C代码往往也能得出越简洁的机器代码。那这样结果如何呢?把它生成的汇编代码拿出来看一看就知道了。满怀希望的我按下了&Build target&键,结果打击是巨大的:
  ; FUNCTION _delay1 (BEGIN)
  ; SOURCE LINE # 13
  ;---- Variable &i& assigned to Register &R7& ----
  ; SOURCE LINE # 14
  0000     ?C0004:
  ; SOURCE LINE # 15
  0000 AE07       MOV   R6,AR7
  0002 1F        DEC   R7
  0003 EE        MOV   A,R6
  0004 70FA       JNZ   ?C0004
  ; SOURCE LINE # 16
  0006     ?C0006:
  0006 22        RET
  ; FUNCTION _delay1 (END)
  虽说生成的代码跟用for语句是不大一样,不过我可以毫无疑问的说,这两种方法的效率是一样的。似乎到此为止了,因为我实在想不出来源程序还有什么简化的余地。看来我就要得出来这个结论了:&如果需要us级的延时精度,需要时用汇编语言。&但是真的是这样吗?我还是不甘心。因为我不相信大名鼎鼎的 Keil C 编译器居然连 djnz 都不会用???因为实际上程序体里只需要一句 loop: djnz r7, loop。近乎绝望之际(往往人在这种情况下确可以爆发出来,哦呵呵呵~~~),我随手改了一下:
  void delay1(unsigned char i)
  while(--i);
  心不在焉的编译,看源码:
  ; FUNCTION _delay1 (BEGIN)
  ; SOURCE LINE # 13
  ;---- Variable &i& assigned to Register &R7& ----
  ; SOURCE LINE # 14
  0000     ?C0004:
  ; SOURCE LINE # 15
  0000 DFFE       DJNZ  R7,?C0004
  ; SOURCE LINE # 16
  0002     ?C0006:
  0002 22        RET
  ; FUNCTION _delay1 (END)
  天~~~奇迹出现了。..。..我想这个程序应该已经可以满足一般情况下的需要了。如果列个表格的话:
  i  delay time/us
  1  5
  2  7
  3  9
  计算延时时间时,已经算上了调用函数的lcall语句所花的2个时钟周期的时间。
  终于,结果已经明了了。只要合理的运用,C还是可以达到意想不到的效果。很多朋友抱怨C效率比汇编差了很多,其实如果对Keil C的编译原理有一个较深入的理解,是可以通过恰当的语法运用,让生成的C代码达到最优化。即使这看起来不大可能,但还是有一些简单的原则可循的:1.尽量使用unsigned 型的数据结构。2.尽量使用char型,实在不够用再用int,然后才是long。3.如果有可能,不要用浮点型。4.使用简洁的代码,因为按照经验,简洁的C代码往往可以生成简洁的目标代码(虽说不是在所有的情况下都成立)。
Keil C相关文章
Keil C相关下载
51单片机相关文章
51单片机相关下载
国际大厂IDT无线接收端芯片出货量达到了3000万颗,随着iPhone8支持无线充电功能,无线充电市场全面启动时间到来。易冲无线推出的无线充电接收端EC4016芯...
厦门新页无线充电芯片的核心优势是什么?新页为何与华强芯城强强联合?华强芯城如何助力新页的市场推进?9月22日,厦门新页董事长林桂江博士和华强...
创新实用技术专题
供应链服务
商务及广告合作
Jeffery Guo
关注我们的微信
供应链服务 PCB/IC/PCBA
版权所有 (C) 深圳华强聚丰电子科技有限公司
电信与信息服务业务经营许可证:粤B2-51单片机C51精确延时
如下程序能实现ms级的比较精确的延时:
void Delayms(unsigned int n)
unsigned int i,j;
for(j=n;j&0;j--)
for(i=112;i&0;i--);
用可以看出这个延时的时间,我们先延时1ms(Delayms(1))。
进入Delayms前,sec=0.s
延时后,sec=0.s
可以知道Delayms(1)实际延时0.s—0..s≈1ms
同样如果想延时15ms的话,用Delayms(15),实际延时0.s≈15ms,延时还是挺精确的。
原文链接:
责任编辑:
声明:本文由入驻搜狐号的作者撰写,除搜狐官方账号外,观点仅代表作者本人,不代表搜狐立场。
今日搜狐热点}

我要回帖

更多关于 单片机延时计算 的文章

更多推荐

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

点击添加站长微信