您的位置 首页 报告

51单片机的准确延时程序剖析

一、C51程序在晶振为11.0592的情况下,如下程序能实现ms级的比较精确的延时:1voidDelayms(unsignedintn)2{3unsignedint…

一、C51程序

在晶振为11.0592的情况下,如下程序能完成ms级的比较准确的延时:

1 void Delayms(unsigned int n)

2 {

3 unsigned int i,j;

4 for(j=n;j>0;j–)

5 for(i=112;i>0;i–);

6 }

keil能够看出这个延时的时刻,咱们先延时1ms,即Delayms(1)。

进入Delayms前,sec=0.00042209s

延时后,sec=0.00142253s

能够知道Delayms(1)实践延时0.00142253s—0.00042209s=0.00100044s≈1ms

相同假如想延时15ms的话,用Delayms(15),实践延时0.01480903s≈15ms,延时仍是挺准确的。

参阅:www.jiangx.net/post/214.html

以上比方给咱们的启示是,在不确定延时程序延时多少的情况下,能够经过调试的办法检测出来。

——————————————————————————–

二、汇编程序(500ms):

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

延时总时刻 = 三层循环 + 循环外 = 499995+5 = 500000us =500ms

核算公式:延时时刻=[(2*R5+3)*R6+3]*R7+5

汇编指令速查表:http://www.cainiao8.com/embedded/51danpianji/danpianji03_zhiling.html

——————————————————————————–

三、延时程序剖析

用汇编言语写单片机程序的时分,这个问题仍是相对简单处理的。比方用的是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常用的循环句子。下面这段代码是我常常在网上看到的:

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

0001 6003 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

假如你将程序中的(unsigned char i)改为(unsigned int i)的话汇编程序将变得愈加不合你原意。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/ceping/baogao/252429.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部