Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

8051 time delays (PLEASE HELP ME)

[b][red]This message was edited by the sureshot3000 at 2002-4-11 4:51:56[/red][/b][hr]
just wondering if SOMEONE can help.i am looking for an assembler code that produces an exact 1 second time delay using an intel 8051 from the address org 8000.
also i am looking for a code using the same language and chip to control the sequence of a set of traffic lights with the following sequence

red red 4 seconds
red & amber red 2 seconds
green red 10 seconds
amber red 2 seconds
red red 4 seconds
red red & amber 2 seconds
red green 7 seconds
red amber 2 seconds

the interface between the lights and the 8051 require a logic 1 to turn the light on
thanks for any help
steve.

Comments

  • CytCyt Member Posts: 557
    First of all: I cannot test this as I don't have a 8051 assembler (or even a 8051) by me. Use this solely as a pointer in some(!) direction.

    As for the first question, I'd advice you to use a timer instead... But if you want to do it the hardcoded way, you'll need to find out:
    - CPU Clock Frq / Cycle Frq.
    - Cycles per Instructions.

    Say that the frq is 8 MHZ. Then you'd need to make a loop that waited for 8000000 cycles (minus loop setup time).

    The function could look like this:
    [code]
    WaitSeconds: // NumSeconds in a (Note: 0 means 65536!!)
    mov r2,#160 ; 12 cycles
    l3: mov r1,#200 ; 12 cycles
    l2: mov r0,#256 ; 12 cycles
    l1: djnz r0,l1 ; 24 cycles
    djnz r1,l2 ; 24 cycles
    djnz r2,l3 ; 24 cycles
    dec a ; 12 cycles
    jnz WaitSeconds ; 24 cycles
    ret
    [/code]

    So, the inner loop uses 24*256 = 6144 cycles
    together with the next loop : (6144+12)*100 = 615600 cycles
    together with the next loop : (615600+12)*13 = 8002956 cycles

    So, this will wait for 8002956/8000000=1,0004 seconds, or 1 second and 40 milliseconds. It's very hard to get closer than that.

    The bad thing about this approach is of course, that an upgrade of the CPU to a faster one will give you too short waiting times...

    : red red 4 seconds
    : red & amber red 2 seconds
    : green red 10 seconds
    : amber red 2 seconds
    : red red 4 seconds
    : red red & amber 2 seconds
    : red green 7 seconds
    : red amber 2 seconds

    You'd be better off by explaining it like this:
    [code]
    Duration | Red | Amber | Green
    ---------+-----+-------+-------
    4 | X | |
    2 | X | X |
    10 | | | X
    2 | | X |
    4 | X | |
    2 | X | X |
    7 | | | X
    2 | | X |
    [/code]

    (This is my interpretation of your text)

    One could make a small table that consisted of "structs":
    [code]
    {
    BYTE Seconds;
    BYTE BitCode;
    };
    [/code]

    Where bit code is simply the byte to write to the port (or external bus). I'm simply assuming that you're writing a byte to the LED at address 0x4000, where the three LSBs are bits for Red, Amber and Green.

    In ASM it would look like this:
    [code]
    RED_BIT .equ 1
    AMBER_BIT .equ 2
    GREEN_BIT .equ 4
    LED_ADDRESS .equ 0x4000

    LightTable:
    .db 4,RED_BIT
    .db 2,RED_BIT|AMBER_BIT
    .db 10,GREEN_BIT
    .db 2,AMBER_BIT
    .db 4,RED_BIT
    .db 2,RED_BIT|AMBER_BIT
    .db 7,GREEN_BIT
    .db 2,AMBER_BIT
    .db 0 ; End of table...
    [/code]

    We could then have a routine that expects dptr to point to a valid entry in the table:

    [code]
    LEDOut: ; dptr pointing to valid entry (BYTE Seconds,BYTE BitCode)
    clr a
    movc a,@a+dptr ; Get Seconds
    mov r0,a ; Store Seconds in r0
    inc dptr
    clr a
    movc a,@a+dptr ; Get BitCode
    mov dptr,#LED_ADDRESS ; Setup Port Address
    movx @dptr,a ; Write Bit To Port
    mov a,r0 ; Restore Seconds
    lcall WaitSeconds
    ret
    [/code]

    And a function calling this routine:

    [code]
    LEDSequence: ; Loops forever!!
    mov dptr,#LightTable ; Point to start of table
    loop: clr a
    movc a,@a+dptr ; Get First entry
    jz LEDSequence ; If 0, we've reached the end of the table, so restart...
    push dptr ; Save dptr
    lcall LEDOut
    pop lptr ; Restore dptr
    inc dptr ; Point
    inc dptr ; to next address in table
    sjmp loop ; Next address loop
    [/code]

    HTH


  • ggillggill Member Posts: 2
    Excellent reply - I have an 80C320 and could not have put it any better. But I would also agree that the built in timers are the way to go.
    Regards,
    Geof
Sign In or Register to comment.