6538|13

82

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

延时程序不准确.难道真是我的计算方法有问题??? [复制链接]

在Kiel做仿真测试:芯片AT89C51,振荡频率设置为12MHz
一个指令周期为振荡频率的1/12,所以为1MHz,对其取倒数既1*10^-6s为其一个指令执行时间.
我们用DJNZ来做延时,因为指令要消耗2个指令周期,所以指令执行时间是2*10^-6s.
如果要延时10S,做三层循环:250*200*100*(2*10^-6)=10S

代码如下:
     ORG 0000H
     LJMP MAIN
     ORG 0030H            ;程序的开始地址
MAIN: LCALL DEALY          ;延时测试,看是否等待了10s
      MOV R0,#14H          ;程序执行20次
      JB P1.0,SP1          ;如P1.0=1->SP1,将P1.0置反一次,便于查看效果
      SETB P1.0
      LJMP SP2
SP1: CLR P1.0
SP2: DJNZ R0,MAIN
FINISH:SJMP $               

;延时测试程序
;DJNZ为2周期指令,250*200*100次DJNZ指令在*2个指令周期(0.001ms)就可以延迟10S了
DEALY:MOV R5,#100
  DL1:MOV R6,#200
  DL2:MOV R7,#250
      DJNZ R7,$        
      DJNZ R6,DL2        
      DJNZ R5,DL1
RET               

END

这里也达到延迟10s的目的.是我的计算方法有问题吗????????

最新回复

你汇编一下就知道了呵呵。  详情 回复 发表于 2009-11-28 09:41
点赞 关注

回复
举报

74

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
用示波器量 别算了
 
 

回复

68

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
问题是要定时处理事件,一定要延时准确啊.

有人知道我算法那有问题吗?
 
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

4
 
算来,算去.
不知道那算错了。
谁只点下.
 
 
 

回复

83

帖子

0

TA的资源

一粒金砂(初级)

5
 
一般情况下只要资源不到临界情况都不关心汇编。
精确定时要用定时器,至于10S是一个很长的时间了,要溢出好几次才够,精度打折扣。
软件定时省资源,但会被中断打断,造成时间不准,除非楼主的程序里面没用到其它中断。
事实上,既然楼主都用上KEIL了,可以直接用C写,软件仿真设断点看时间。以前我有用过一个WAVE(伟福)的软件,软件仿真时间计算得非常准确,只要使用的是正常12分频的51都可以得到准确的定时时间,不需要汇编这么痛苦。
 
 
 

回复

59

帖子

0

TA的资源

一粒金砂(初级)

6
 
纯粹从理论上讲你的计算式没有错的,大概就是10S了。误差还是肯定有的。
定时处理事件,当然是汇编更加准确了。
但是你用延时是不好的,定时才更加准确的。
 
 
 

回复

90

帖子

0

TA的资源

一粒金砂(初级)

7
 
延时10MS的程序,你的晶振不要用12M的,不准确的,要用标准的11.0592的晶振.
延时控制LED.你先搞定50m的出来,再循环就可以了。


COUNT EQU  9217;对于11.0592的晶振来说,延时10ms
LED  EQU  P1.1
;
  ORG  0000H
  LJMP RESET
  ORG  0003H  ;INT0(外部中断0)
  RETI
  ORG  000BH ;TIMER0(定时器/计数器T0)
  LJMP INT_TIMER0 ;跳转到定时器/计数器中断服务程序中去

  ORG  0030H
RESET: MOV  R0,#00H
  DJNZ R0,$  ;刚开始,先进行少量的延时,是各种工作寄存器准备好
  CLR  LED
  
  MOV  TMOD,#00000001B
  MOV  TH0,#HIGH(65536-COUNT)
   MOV     TL0,#LOW(65536-COUNT)
  
  CLR  TF0   ;先把溢出标志位清零
  SETB TR0   ;开始计时
  SETB EA
  SETB ET0   ;ET0为定时器/计数器T0溢出中断允许位
  
  MOV  IP,#00000010B;设置PT0为高优先级中断(timer0中断)
  MOV  R2,#00H  ;作为定时器累加器使用

LOOP: SJMP LOOP

INT_TIMER0:

  INC  R2  ;使R1自增一
  CLR  TF0   ;CLEAR TF0 AGAIN
  MOV  TH0,#(65536-COUNT)/256;取高八位数据
  MOV  TL0,#255   ;取底五位(为最大了)

  CJNE R2,#5,L1 ;不相等则转移指令,这个数可以进行调节
  CPL  LED    ;取反指令
  MOV  R2, #00H
L1:  RETI
  END

 
 
 

回复

79

帖子

0

TA的资源

一粒金砂(初级)

8
 
DEALY:MOV R5,#100   ;1周期
  DL1:MOV R6,#200   ;1周期
  DL2:MOV R7,#250   ;1周期
      DJNZ R7,$     ;2周期   
      DJNZ R6,DL2   ;2周期      
      DJNZ R5,DL1   ;2周期
       RET           ;2周期
总周期 = 1+[1+(1+2*250+2)*200+2]*100+2

 
 
 

回复

54

帖子

0

TA的资源

一粒金砂(初级)

9
 
有人帮我把代码放到Proteus仿真,说在那里面执行情况是10S反相的.

但是在Keil里面仿真(通过看P1.0信号脚),怎么都不准确..

难道是Keil仿真有问题吗???
 
 
 

回复

75

帖子

0

TA的资源

一粒金砂(初级)

10
 
破解版KEIL是不准的,,如果真的要在里面做的话好像还要下插件,是要付费的。
 
 
 

回复

59

帖子

0

TA的资源

一粒金砂(初级)

11
 
肯定会有误差的,直接用定时吧
 
 
 

回复

69

帖子

0

TA的资源

一粒金砂(初级)

12
 
  1. /***************************************************************************************************
  2. 【函数名称】    delay10s()
  3. 【函数功能】    延迟10.000000秒,12M晶振
  4. 【参数简介】    12M,12分频,每周期1us        10S = 10,000,000 us    ,= 200*250*200 /2
  5.                 for--汇编完应为DJNZ结构
  6.                 东狮山
  7. ***************************************************************************************************/
  8. void delay10s(void)
  9. {
  10.     unsigned char i,j,k;
  11.     for(i=99;i>0;i--)                           //10,000,004us
  12.     {
  13.         for(j=250-1;j>0;j--)                    //250*400=100ms
  14.         {
  15.             for(k=200-2,_nop_();k>0;k--);       //减去3个周期 200 -2*2 +1,   200*2=400 us
  16.         }
  17.         for(k=200-3,_nop_(),_nop_();k>0;k--);   //100ms减去3个周期 200 -2*2 +1
  18.     }
  19.     //减去5个周期
  20.     for(j=250-1;j>0;j--)                    //250*400=100ms
  21.     {
  22.         for(k=200-2,_nop_();k>0;k--);       //减去3个周期 200 -2*2 +1,   200*2=400 us
  23.     }
  24.     for(k=200-3-1,_nop_();k>0;k--);
  25. }
  26. /***************************************************************************************************
  27. 【函数名称】    delay10s2()
  28. 【函数功能】    延迟10秒,12M晶振
  29. 【参数简介】    使用LONG类型是为了更简洁些
  30.                 东狮山
  31. ***************************************************************************************************/
  32. void delay10s2(void)
  33. {
  34.     unsigned long i;
  35.     unsigned char j;
  36.     for(i=71428;i>0;i--);            //9,999,926 us
  37.     for(j=34;j>0;j--);               //69        us
  38.     _nop_();                         //1         us
  39. }
复制代码

只要程序中没有中断,软件延时也是没有问题的.
两个都可以精确定到10.000000s,KEIL编译.
习惯写C,可以看汇编后的结果,其实for(x--)汇编完就是DJNZ,效率也是很高的.
谁说C不行?第一个是为了说明初偿的,否则程序可以写得非常简洁的.
 
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

13
 
while(--i)汇编完才是DJNZ.
 
 
 

回复

63

帖子

0

TA的资源

一粒金砂(初级)

14
 
你汇编一下就知道了呵呵。
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表