设MCS-51单片机的晶振频率为12MHZ,试编写10ms的延时程序(要求误差不超过0.003ms)。

如题所述

C语言程序:

#include 

void main (void)

{

TMOD = 0x10;

TH1 = (-50000>>8);

TL1 = -50000;

TCON = 0x40;

IE = 0x88;

while(1);

}

void T1_int (void) interrupt 3

{

TH1 = (-50000>>8);

TL1 = -50000;

}

汇编程序如下:

ORG    0000H

AJMP    MAIN

ORG    001BH

AJMP    T1INT

ORG    0100H

MAIN:    

MOV    TMOD, #10H

MOV    TH1, #HIGH(-50000)

MOV    TL1, #LOW(-50000)

MOV    TCON, #40H

MOV    IE, #88H

AJMP    $

T1INT:

PUSH    ACC

MOV TH1, #HIGH(-50000)

MOV TL1, #LOW(-50000)

POP    ACC

RETI

扩展资料:

Keil C51程序设计中几种精确延时方法

延时通常有两种方法:一种是硬件延时,要用到定时器/计数器,这种方法可以提高CPU的工作效率,也能做到精确延时;另一种是软件延时,这种方法主要采用循环体进行。

使用定时器/计数器实现精确延时

单片机系统一般常选用11.059 2 MHz、12 MHz或6 MHz晶振。第一种更容易产生各种标准的波特率,后两种的一个机器周期分别为1 μs和2 μs,便于精确延时。

本程序中假设使用频率为12 MHz的晶振。最长的延时时间可达216=65 536 μs。若定时器工作在方式2,则可实现极短时间的精确延时;如使用其他定时方式,则要考虑重装定时初值的时间(重装定时器初值占用2个机器周期)。

在实际应用中,定时常采用中断方式,如进行适当的循环可实现几秒甚至更长时间的延时。使用定时器/计数器延时从程序的执行效率和稳定性两方面考虑都是最佳的方案。但应该注意,C51编写的中断服务程序编译后会自动加上PUSH ACC、PUSH PSW、POP PSW和POP ACC语句。

执行时占用了4个机器周期;如程序中还有计数值加1语句,则又会占用1个机器周期。这些语句所消耗的时间在计算定时初值时要考虑进去,从初值中减去以达到最小误差的目的。

温馨提示:答案为网友推荐,仅供参考
第1个回答  推荐于2017-11-24
我们用汇编语言写单片机延时10ms的程序(用的是12MHz晶振的 MCS-51),可以编写下面的程序来实现:
MOV R5,#5 ①
D1: MOV R6,#4 ②
D2: MOV R7,#248 ③
DJNZ R7,$ ④
DJNZ R6,D2 ⑤
DJNZ R5,D1 ⑥
RET ⑦
这个延时程序共有七条指令,现在就每一条指令执行的次数和所耗时间进行分析:
第一条, MOV R5,#5 在整个程序中只执行一次,且为单周期指令,所以耗时1μs,
第二条, MOV R6,#4 看⑥的指令可知,只要R5-1不为0,就会返回执行这条指令,共执行了R5次,共耗时5μs,
第三条, MOV R7,#248 同第二条类似,只要R6-1不为0,就会返回执行这条指令,同时受到外部循环R5的控制,共耗时R5*R6*1=20μs,
第四条, DJNZ R7,$ 只要R7-1不为0,就执行这条指令,同时受到外部循环的控制,由于该指令是双周期指令,共耗时为R7*R6*R5*2=9920μs,
第五条, DJNZ R6,D2 只要R6-1不为0,就反复执行此条指令(内循环R6次),又受外循环R7的控制,共耗时R6*R5*2=40μs,
第六条, DJNZ R5,D1 只要R5-1不为0,就反复执行此条指令,耗时为R5*2=10μs,
第七条, RET 此指令为双周期指令,耗时为2μs,
我们也要考虑在调用子程序时用到LCALL指令,耗时2μs,最后可以得到总的延时为:1+5+20+9920+40+10+2=9998μs=10ms
我们可以总结延时总时间的公式:
延时总时间=[(2*一层循环次数+3)*二层循环次数+3]*三层循环次数+3
注意此公式只适用于三层以内的循环本回答被提问者采纳
第2个回答  2022-10-02

设 MCS-51 单片机的晶振频率为 12MHz,试编写 10ms 的延时程序(要求误差不超过 0.003ms)。

要求精确定时,应该采用硬件。

51 单片机有两个定时器,52 的有三个。够你用的了。

用软件编写延时程序,就别要求太高了。

在 10,000us 内,误差不超过 3us!

并不值得费这心思。

第3个回答  2011-06-29
DELY :MOV R7,#10
DELY1:MOV R6,#199
DELY2:NOP
NOP
NOP
DJNZ R6,DELY2
NOP
DJNZ R7,DELY1
NOP
NOP
NOP
NOP
NOP
RET
延时时间:1+10*(199*5+4) +5+2=9998 uS,再加上调用指令2uS,正好10mS。
第4个回答  2011-06-29
汇编指令验证的 所以延时准确

void delay(void) //误差 0us
{
unsigned char a,b,c;
for(c=1;c>0;c--)
for(b=38;b>0;b--)
for(a=130;a>0;a--);
}追问

能不能告诉怎么算啊?要不写个汇编也行啊