编写一个延时子程序? [英] Writing a delay subroutine?

查看:362
本文介绍了编写一个延时子程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要写一个延时子程序。它应该延迟约1秒。它必须是8051的环境中,DS89C430 micrcontroller(11.0592兆赫XTAL)。我怎么能写这个子程序?

  Delay1sec:...
....
...
....
...


解决方案

要得到一个确切的延迟1秒的中断期间也正常,你需要使用一个硬件定时器,而不是一个软件定时器。我会建议你使用现有的车载计时器之一杰里·科芬的建议

下面是涉及内置定时器计数定时器溢出的方法。由于运行的定时器被默认每12个时钟周期更新,以保持与8051兼容,它会被更新每秒921,600次。乘法的位告诉我们,它需要50毫秒数从0到46080,这也告诉我们,我们可以在19456启动一个16位定时器,等待它溢出20次,1秒延迟*

在code可能是这个样子:

  CLR T0M;设置定时器0使用除以12
                             ;晶振频率(默认)        MOV R0,TMOD;设置定时器0到16位模式下无
        ORL R0,#01H;影响定时器1的设置
        MOV TMOD,R0        LCALL Delay1sec;调用延时子程序Delay1sec:
        MOV R0,#20D;集循环计数为20循环:CLR TR0;开始计时每次循环停止
        CLR TF0;和溢出标志清晰。建立
        MOV TH0,#4CH;定时器0到50毫秒溢出,开始
        MOV TL0,#00H;计时器,等待溢出,然后重复
        SETB TR0;直到循环计数耗尽
        JNB TF0,$
        DJNZ R0,环
        RET

<分> 注意:从例子排除指令执行时间开销
结果
<子> *数学如何分解:结果
十二分之一千一百零五万九千二百= 921600结果
0.05 * 921600 = 46080结果
65536 - 46080 = 19456 = 0x4C00


软件延迟循环垃圾处理器时间和中断的干扰。话虽这么说,你可以做硬codeD的方式。

一种方法涉及知道每个机器周期的时钟周期的数目与机器周期的各种指令的执行时间的数目。按照数据表的DS89C430通常使用一个机器周期对于每一个指令字节,并且需要执行一个周期。在提供周期每条指令数的超高 - 速度闪存微控制器用户指南

由于您的晶振频率为11.0592 MHz时,你的日常需要为11059200个时钟周期的延时。这通常是通过已知长度的嵌套循环,然后包括任何额外的循环设置和可能的子程序调用和返回指令完成 *

该功能可能看起来是这样的:

  Delay1sec:; &LT; ------------------------------ +
; LCALL Delay1sec; 3个周期|
        MOV R2,#42D; 2个周期|
        MOV R1,#00D; 2个周期|
        MOV R0,#00D; 2个周期|
循环:DJNZ R0,循环; 4个周期&LT; - L1&LT; - 12&LT; - 13 Delay1sec
        DJNZ R1,循环; 4个循环LT; --------- + | |
        DJNZ R2,循环; 4个循环LT; --------------- + |
        RET; 3个周期&LT; --------------------- +

让我们看看如何数学分解 **

L1 = 4 * 256 = 1024个周期结果
12 =(1024 + 4)* 256 = 263168个周期结果
13 =(263168 + 4)* 42 = 11053224个周期结果
Delay1sec = 11072668 + 3 + 2 + 2 + 2 + 3 = 11053236次搜索

11053236周期*一千一百零五万九千二百分之一秒/循环= 999.461毫秒搜索

<子> *子程序调用和返回指令可以省略必要的。结果
<子> **我使用Microsoft Excel的协助与确定循环计数器计算。

I need to write a delay subroutine. It should delay about 1 second. It has to be for 8051 environment, DS89C430 micrcontroller ( 11.0592 MHz XTAL). How can I write this subroutine?

Delay1sec: ...
....
...
....
...

解决方案

To get an exact 1 second delay that also works during interrupts, you need to use a hardware timer, not a software timer. I would advise you to use one of the available on-board timers as suggested by Jerry Coffin.

Here's an approach involving a built-in timer and counting timer overflows. Since the running timer is updated every 12 clock cycles by default to maintain compatibility with the 8051, it will be updated 921,600 times per second. A bit of multiplication tells us that it takes 50 ms to count from 0 to 46080, which also tells us that we can start a 16-bit timer at 19456 and wait for it to overflow 20 times to delay for 1 second*.

The code could look something like this:

        CLR     T0M          ; set timer 0 to use a divide-by-12 of
                             ; the crystal frequency (default)

        MOV     R0,TMOD      ; set timer 0 to 16-bit mode without
        ORL     R0,#01h      ; affecting the setup of timer 1
        MOV     TMOD,R0

        LCALL   Delay1sec    ; call the delay subroutine

Delay1sec:
        MOV     R0,#20d      ; set loop count to 20

loop:   CLR     TR0          ; start each loop with the timer stopped
        CLR     TF0          ; and the overflow flag clear. setup
        MOV     TH0,#4Ch     ; timer 0 to overflow in 50 ms, start the
        MOV     TL0,#00h     ; timer, wait for overflow, then repeat
        SETB    TR0          ; until the loop count is exhausted
        JNB     TF0,$
        DJNZ    R0,loop
        RET   

Note: Overhead of instruction execution time excluded from example.
* How the math breaks down:
11059200 / 12 = 921600
0.05 * 921600 = 46080
65536 - 46080 = 19456 = 0x4C00


Software delay loops waste processor time and are disturbed by interrupts. That being said, you can do it the hardcoded way.

One approach involves knowing the number of clock cycles per machine cycle and the number of machine cycles various instructions take to execute. According to the data sheet, the DS89C430 usually uses one machine cycle for each instruction byte and requires one cycle for execution. The number of cycles for each instruction is provided in the Ultra-High-Speed Flash Microcontroller User's Guide.

Since your crystal frequency is 11.0592 MHz, your routine will need to delay for 11,059,200 clock cycles. This is often accomplished via nested loops of known length and then including any extra loop setup and possibly subroutine call and return instructions*.

The function could look something like this:

Delay1sec:                   ; <------------------------------+
;       LCALL   Delay1sec    ; 3 cycles                       |
        MOV     R2,#42d      ; 2 cycles                       |
        MOV     R1,#00d      ; 2 cycles                       |
        MOV     R0,#00d      ; 2 cycles                       |
loop:   DJNZ    R0,loop      ; 4 cycles <-- l1 <- l2 <- l3    Delay1sec
        DJNZ    R1,loop      ; 4 cycles <---------+     |     |
        DJNZ    R2,loop      ; 4 cycles <---------------+     |
        RET                  ; 3 cycles <---------------------+

Let's see how the math breaks down**:

l1 = 4 * 256 = 1024 cycles
l2 = (1024 + 4) * 256 = 263168 cycles
l3 = (263168 + 4) * 42 = 11053224 cycles
Delay1sec = 11072668 + 3 + 2 + 2 + 2 + 3 = 11053236 cycles

11053236 cycles * 1/11059200 seconds/cycle = 999.461 ms

* The subroutine call and return instructions may be omitted as necessary.
** I used Microsoft Excel to assist with calculations related to determining loop counters.

这篇关于编写一个延时子程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆