PIC18F4520 circuit not functioning

Thread Starter

Oniww

Joined Aug 29, 2026
1
why the multiplexed dual 7-segment display only showing 00 - 04 then loop again 00 - 04 until 20 and freeze.


Code:
        LIST    P=18F4520
        #include <P18F4520.INC>

;=========================================================
; CONFIGURATION
;=========================================================

        CONFIG  OSC = HS
        CONFIG  WDT = OFF
        CONFIG  PBADEN = OFF
        CONFIG  LVP = OFF

;=========================================================
; VARIABLES
;=========================================================

        CBLOCK  20H

COUNT
MODE
PAUSE

TENS
UNITS

C1
C2
C3

        ENDC

;=========================================================
; RESET VECTOR
;=========================================================

        ORG     0000H
        GOTO    MAIN

;=========================================================
; MAIN
;=========================================================

MAIN:

; PORTD = 7-segment A-G

        CLRF    TRISD
        CLRF    LATD

; RC0 = tens digit
; RC1 = units digit
; RC2 = UP/DOWN
; RC3 = PAUSE
; RC4 = RESET
; RC5 = BUZZER

        MOVLW   B'11011100'
        MOVWF   TRISC

        CLRF    LATC

; Start at 00

        CLRF    COUNT

; Start UP

        MOVLW   01H
        MOVWF   MODE

; Start RUN

        CLRF    PAUSE

;=========================================================
; MAIN LOOP
;=========================================================

MAIN_LOOP:

; Refresh display

        CALL    DISPLAY
        CALL    DISPLAY
        CALL    DISPLAY
        CALL    DISPLAY

;=========================================================
; RESET SWITCH
; RC4 = 0 when pressed
;=========================================================

        BTFSC   PORTC,4
        GOTO    CHECK_MODE

        CALL    RESET_COUNTER

;=========================================================
; UP / DOWN SWITCH
; RC2 = 1 -> UP
; RC2 = 0 -> DOWN
;=========================================================

CHECK_MODE:

        BTFSC   PORTC,2
        GOTO    SET_UP

; DOWN

        CLRF    MODE
        GOTO    CHECK_PAUSE

; UP

SET_UP:

        MOVLW   01H
        MOVWF   MODE

;=========================================================
; PAUSE SWITCH
; RC3 = 0 when pressed
;=========================================================

CHECK_PAUSE:

        BTFSC   PORTC,3
        GOTO    CHECK_RUNNING

; Debounce

        CALL    SHORT_DELAY

        BTFSC   PORTC,3
        GOTO    CHECK_RUNNING

; Toggle pause

        MOVLW   01H
        XORWF   PAUSE,F

; Wait for release

WAIT_BUTTON_RELEASE:

        BTFSS   PORTC,3
        GOTO    WAIT_BUTTON_RELEASE

        CALL    SHORT_DELAY

;=========================================================
; CHECK RUNNING
;=========================================================

CHECK_RUNNING:

        MOVF    PAUSE,F
        BNZ     MAIN_LOOP

;=========================================================
; CHECK COUNT = 50
;=========================================================

        MOVLW   D'50'
        CPFSEQ  COUNT
        GOTO    BUZZER_OFF

; COUNT = 50

        BSF     LATC,5

; Stop counting at 50

        GOTO    MAIN_LOOP

;=========================================================
; BUZZER OFF
;=========================================================

BUZZER_OFF:

        BCF     LATC,5

;=========================================================
; COUNTING
;=========================================================

        MOVF    MODE,F
        BZ      COUNT_DOWN

;=========================================================
; COUNT UP
;=========================================================

COUNT_UP:

        INCF    COUNT,F

; 100 decimal = 64H

        MOVLW   D'100'
        CPFSEQ  COUNT
        GOTO    COUNT_DELAY

        CLRF    COUNT

        GOTO    COUNT_DELAY

;=========================================================
; COUNT DOWN
;=========================================================

COUNT_DOWN:

        MOVF    COUNT,F
        BZ      SET_99

        DECF    COUNT,F

        GOTO    COUNT_DELAY

;=========================================================
; SET 99
;=========================================================

SET_99:

        MOVLW   D'99'
        MOVWF   COUNT

;=========================================================
; COUNT DELAY
;=========================================================

COUNT_DELAY:

        MOVLW   08H
        MOVWF   C3

COUNT_DELAY_LOOP:

        CALL    DISPLAY
        CALL    DISPLAY
        CALL    DISPLAY
        CALL    DISPLAY

        DECFSZ  C3,F
        GOTO    COUNT_DELAY_LOOP

        GOTO    MAIN_LOOP

;=========================================================
; RESET COUNTER
;=========================================================

RESET_COUNTER:

        CLRF    COUNT
        CLRF    PAUSE

        BCF     LATC,5

        RETURN

;=========================================================
; DISPLAY
;=========================================================

DISPLAY:

;---------------------------------------------------------
; Convert COUNT to TENS and UNITS
;---------------------------------------------------------

        CLRF    TENS

        MOVF    COUNT,W
        MOVWF   UNITS

CONVERT_NUMBER:

        MOVLW   D'10'
        SUBWF   UNITS,W

        BTFSS   STATUS,C
        GOTO    CONVERSION_DONE

        MOVWF   UNITS

        INCF    TENS,F

        GOTO    CONVERT_NUMBER

;=========================================================
; TENS DIGIT
;=========================================================

CONVERSION_DONE:

; Turn both digits OFF

        BCF     LATC,0
        BCF     LATC,1

; Get tens pattern

        MOVF    TENS,W
        CALL    SEVEN_SEGMENT

        MOVWF   LATD

; Turn ON tens

        BSF     LATC,0

        CALL    REFRESH_DELAY

; Turn OFF tens

        BCF     LATC,0

;=========================================================
; UNITS DIGIT
;=========================================================

        MOVF    UNITS,W
        CALL    SEVEN_SEGMENT

        MOVWF   LATD

; Turn ON units

        BSF     LATC,1

        CALL    REFRESH_DELAY

; Turn OFF units

        BCF     LATC,1

        RETURN

;=========================================================
; 7-SEGMENT LOOKUP TABLE
; COMMON CATHODE
;=========================================================

        ORG     0100H

SEVEN_SEGMENT:

        ADDWF   PCL,F

        RETLW   3FH         ; 0
        RETLW   06H         ; 1
        RETLW   5BH         ; 2
        RETLW   4FH         ; 3
        RETLW   66H         ; 4
        RETLW   6DH         ; 5
        RETLW   7DH         ; 6
        RETLW   07H         ; 7
        RETLW   7FH         ; 8
        RETLW   6FH         ; 9

;=========================================================
; SHORT DELAY
;=========================================================

SHORT_DELAY:

        MOVLW   05H
        MOVWF   C1

SHORT_LOOP1:

        MOVLW   0FFH
        MOVWF   C2

SHORT_LOOP2:

        DECFSZ  C2,F
        GOTO    SHORT_LOOP2

        DECFSZ  C1,F
        GOTO    SHORT_LOOP1

        RETURN

;=========================================================
; DISPLAY REFRESH DELAY
;=========================================================

REFRESH_DELAY:

        MOVLW   02H
        MOVWF   C1

REFRESH_LOOP1:

        MOVLW   0FFH
        MOVWF   C2

REFRESH_LOOP2:

        DECFSZ  C2,F
        GOTO    REFRESH_LOOP2

        DECFSZ  C1,F
        GOTO    REFRESH_LOOP1

        RETURN

;=========================================================
; END
;=========================================================

        END
屏幕截图 2026-08-30 014812.png
Moderator edit: Added CODE tags
 

MrChips

Joined Oct 2, 2009
35,046
You need to learn how to apply debugging techniques.

1) Rather than trying to get the entire program to work successfully, learn to test segments of the code, one segment at a time.

2) Use the debugger to watch registers and variables and see that they progress as expected.

3) Use breakpoints in strategic locations to observe the state of the machine, registers and memory.
 

joeyd999

Joined Jun 6, 2011
6,447
Is this homework? If so, it's in the wrong forum.

If not, are you trying to learn assembly or do you have a larger project in mind?

One big main loop is not the right way to code assembly. Yes, it might work for a trivial project like this, but it is completely inextensible, difficult to read and debug, and, since every part of the code runs sequentially you'll eventually get to the point were things that need to run fast get starved of CPU time (like LED display multiplexing).

If this were my project, I'd look at the specification and break it down in to modules I need, and write them as separate, stand alone .inc files, and include them in the main project file. This way, I could independently test each module to insure it performs as expected, greatly increasing the probability that your code will run correctly when assembled into a complete project. Further, those code modules can be included in other projects, greatly reducing development time in the future.

In this immediate case, I see a need for:

1) an interrupt driven master timer -- interrupt code plus the userspace subroutines.

2) an interrupt driven hardware driver for the LED numeric display (human eyes are sensitive to multiplexed displays that don't have exact and continuous timing between the digits). Again, interrupt code + userspace. The master timer could drive the multiplexing instead of separate interrupt code.

3) a userspace keypress module for key debouncing and decoding, using the master timer for debouncing, thereby avoiding blocking.

4) a counter module that implements the functionality, using the master timer as a time base, and the output(s) of the keypress module. Counting data is stored for use by the display module.

5) a main program that is a simple loop that sequentially calls the above userspace code.

It sounds complicated, but breaking the code down by modules will make your life much easier if you intend to write .asm code in the future.
 

atferrari

Joined Jan 6, 2004
5,021
In line with the above I suggest you implement the most basic and shortest possible piece of code to test.

Once this is tested and found OK, and NOT BEFORE, add another one which should be tested before adding the next.

Sure you could consider this too much work but, it's the quickest way to get a full piece of code doing what you intend do do.
 

joeyd999

Joined Jun 6, 2011
6,447
In line with the above I suggest you implement the most basic and shortest possible piece of code to test.
I always start with the master clock, which is about 10 lines of code.

This ensures the MCU is running, Fosc is correct, and interrupts are working as expected. That covers many of the CONFIG directives and FSRs required for basic operation.
 
Top