Search code examples
assemblypicledlightblink

How to fix PIC assembly program to blink LEDs designated amount of times (i.e. 10 times)?


I'm trying to write a program that blinks LEDs in a pattern. The pattern is P0, P0 and P1, P1 and P2, etc... until it gets to P6 and P7. Each set of LEDs is supposed to blink 10 times and then move on to the next set in the pattern. It works fine the first time through, but when it returns to P0 after P6 and P7, P0 blinks 20 times. The rest of the LEDs blink 10 times, so I am confused as to why it does this for P0. Can someone explain why or help me fix it?

In the code the semicolon (;) means it's a comment. Here is the code:

#include <p16F887.inc>
__CONFIG    _CONFIG1, _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
__CONFIG    _CONFIG2, _WRT_OFF & _BOR21V

cblock  0x20            ;start of general purpose registers
    count1          ;used in delay routine
    counta          ;used in delay routine 
    countb          ;used in delay routine
    count2
    Num1
    Num2
    Num3
    Num4
    Num5
    Num6
    Num7
    Num8
endc

LEDPORT Equ PORTD       ;set constant LEDPORT = 'PORTB'
LEDTRIS Equ TRISD       ;set constant for TRIS register

org 0x0000          ;org sets the origin, 0x0000 for the 16F628,
                ;this is where the program starts running   
movlw   0x07

bsf     STATUS,     RP0 ;select bank 1
movlw   b'00000000'     ;set PortB all outputs
movwf   LEDTRIS
bcf STATUS,     RP0 ;select bank 0
clrf    LEDPORT         ;set all outputs low    

Loop    
    movlw   d'10'
    movwf   Num1
    movlw   d'10'
    movwf   Num2
    movlw   d'10'
    movwf   Num3
    movlw   d'10'
    movwf   Num4
    movlw   d'10'
    movwf   Num5
    movlw   d'10'
    movwf   Num6
    movlw   d'10'
    movwf   Num7
    movlw   d'10'
    movwf   Num8

    call    LOOP1
    call    LOOP2
    call    LOOP3
    call    LOOP4
    call    LOOP5
    call    LOOP6
    call    LOOP7
    call    LOOP8

LOOP1: 
     movlw  b'00000001'
     movwf  LEDPORT
     call   Delay           ;this waits for a while!
     movlw  b'00000000'
     movwf  LEDPORT
     call   Delay
     DECFSZ Num1,1
     goto   LOOP1
     clrf   Num1
     movlw  d'10'
     movwf  Num1
     return

LOOP2: 
     movlw  b'00000011'
     movwf  LEDPORT
     call   Delay           ;this waits for a while!
     movlw  b'00000000'
     movwf  LEDPORT
     call   Delay
     DECFSZ Num2,1
     goto   LOOP2
     ;clrf  Num2
     movlw  d'10'
     movwf  Num2
     return 

LOOP3: 
     movlw  b'00000110'
     movwf  LEDPORT
     call   Delay           ;this waits for a while!
     movlw  b'00000000'
     movwf  LEDPORT
     call   Delay
     DECFSZ Num3,1
     goto   LOOP3
     ;clrf  Num3
     movlw  d'10'
     movwf  Num3
     return 

LOOP4: 
     movlw  b'00001100'
     movwf  LEDPORT
     call   Delay           ;this waits for a while!
     movlw  b'00000000'
     movwf  LEDPORT
     call   Delay
     DECFSZ Num4,1
     goto   LOOP4
     movlw  d'10'
     movwf  Num4
     return     

LOOP5: 
     movlw  b'00011000'
     movwf  LEDPORT
     call   Delay           ;this waits for a while!
     movlw  b'00000000'
     movwf  LEDPORT
     call   Delay
     DECFSZ Num5,1
     goto   LOOP5
     movlw  d'10'
     movwf  Num5
     return     

LOOP6: 
     movlw  b'00110000'
     movwf  LEDPORT
     call   Delay           ;this waits for a while!
     movlw  b'00000000'
     movwf  LEDPORT
     call   Delay
     DECFSZ Num6,1
     goto   LOOP6
     movlw  d'10'
     movwf  Num6
     return   

LOOP7: 
     movlw  b'01100000'
     movwf  LEDPORT
     call   Delay           ;this waits for a while!
     movlw  b'00000000'
     movwf  LEDPORT
     call   Delay
     DECFSZ Num7,1
     goto   LOOP7
     movlw  d'10'
     movwf  Num7
     return   

LOOP8: 
     movlw  b'11000000'
     movwf  LEDPORT
     call   Delay           ;this waits for a while!
     movlw  b'00000000'
     movwf  LEDPORT
     call   Delay
     DECFSZ Num8,1
     goto   LOOP8
     movlw  d'10'
     movwf  Num8
     return     

Delay   ;movlw  d'4'
        ;movwf  count2
        movlw   d'250'          ;delay 250 ms (4 MHz clock)
        movwf   count1
    d1  movlw   0xC7
        movwf   counta
        movlw   0x01
        movwf   countb
Delay_0
        decfsz  counta, f
        goto    $+2
        decfsz  countb, f
        goto    Delay_0

        decfsz  count1  ,f
        goto    d1
        ;decfsz count2  ,f
        ;goto   d1
        retlw   0x00

end 

Solution

  • Your last led blink

        call    LOOP8
    
    LOOP1: 
    

    falls through into LOOP1: but it should jump back to Loop. This causes the execution to reach return at the end of LOOP1: function, but as there is no return address on the internal call stack, the device places the reset address in the program counter. Thus, LOOP1 appears to execute twice. You should have

        call    LOOP8
        goto    Loop
    
    LOOP1: