Basically my task is to make the counter on a micro controller board count from 00-99 continuously using assembly language.
because it is not possible to show two 7-Seg to display at the same time, my solution is to display the tens(0), display ones(0), display tens(0), display one(1), display tens(0), display one(2), display tens(0), display one(3), etc. my approach to doing this is to have two loops (one for the tens digit, one for the ones digit) that goes through an array. once the ones digit loop have gone through the entire array, the loop breaks and goes back to the tens digit loop, move the tens digit to the next element, then back to the ones digit loop
MSB_Display equ $0B ; display on 'tens' digit/second most right of 7-Seg
LSB_Display equ $07 ; display on 'ones' digit/most right of 7-Seg
D_1MS equ 24000 / 6
DelayVal equ 35 ; 35 ms delay simulates both Hex Displays on at once
org $1000
; Lookup table for LED segments
array db $3F,$06,$5B,$4F,$66,$6D,$7C,$07,$7F,$6F
; 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9
; Memory Reserved for Delay Routine
DCount ds 1
Counter ds 1
countones db 0
counttens db 0
org $2000 ; Program starts here
lds #$2000 ; Initalize the stack
; Configure Hardware
ldaa #$FF
staa DDRB ; Make PORTB output
staa DDRP ; PTP as Output
start
clr countones ; clear count back to 0
clr counttens
ldx #array
MSB
ldaa 1,x+
staa PORTB
ldaa #MSB_Display
staa PTP ; turn off 7-segment display
bsr Delay_ms
inc counttens
ldaa counttens
cmpa #10
bne LSB
LSB
ldy #array
ldab 1,y+
stab PORTB
ldab #LSB_Display
stab PTP
bsr Delay_ms
inc countones
ldaa countones
cmpa #10
bne LSB
bra MSB
Delay_ms
psha
pshy
ldaa #DelayVal ; Number of msec to delay
staa DCount ; store delay counter
ldaa DCount ; delay Dcount ms
staa Counter
Delay1 ldy #D_1MS ; 6000 x 4 = 24,000 cycles = 1ms
Delay2 dey ; this instruction takes 1 cycle
bne Delay2 ; this instruction takes 3 cycles
dec Counter
bne Delay1 ; not Dcount ms yet, delay again
pula ; Restore contents of ACC A before returning
puly
rts
end
right now it seems like the program enters the ones digit loop (LSB) and sits there, it does not exit that loop nor does it reloop itself. I can't seem to find whats wrong in the logic of my program
Pulling from stack should be done in reverse order from putting on stack. As Ira pointed out you got your counters mixed up...
You should think of 'displaying two digit number' as a separate thing from increasing some counter in a loop. Displaying is simple switching 'active' output with a time delay, and setting correct digit value for each display cycle.
'tens' = 0
loop10 'ones' = 0
loop1 display 'tens'
delay
display 'ones'
delay
inc 'ones'
goto loop1 if 'ones' less than 10
inc 'tens'
goto loop10 if 'tens' less than 10
Here is one way of doing this (adjust delay value - 35ms looks to fast...):
MSB_Display equ $0B ; display on 'tens' digit/second most right of 7-Seg
LSB_Display equ $07 ; display on 'ones' digit/most right of 7-Seg
D_1MS equ 24000 / 6
DelayVal equ 35 ; 35 ms delay simulates both Hex Displays on at once
org $1000
; Lookup table for LED segments
array db $3F,$06,$5B,$4F,$66,$6D,$7C,$07,$7F,$6F
; 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9
; Memory Reserved for Delay Routine
DCount ds 1
Counter ds 1
countones db 0
counttens db 0
org $2000 ; Program starts here
lds #$2000 ; Initalize the stack
; Configure Hardware
ldaa #$FF
staa DDRB ; Make PORTB output
staa DDRP ; PTP as Output
start
clr counttens ; 'tens' = 0
ldx #array ; x will point to 'tens'
MSB clr countones ; 'ones' = 0
ldy #array ; y will point to 'ones'
; at every start of 'tens' cycle
LSB
ldaa x ; Set value of 'tens' display
; Do not use 1,x+ here
; You don't want to increment 'tens'
; every time you display 'ones'
staa PORTB
ldaa #MSB_Display
staa PTP ; turn on 'tens' 7-segment display
bsr Delay_ms ; let it be lit for a while
ldab 1,y+ ; set value of 'ones' display (and increment it)
stab PORTB
ldab #LSB_Display
stab PTP ; turn on 'ones' 7-segment display
bsr Delay_ms ; let it be lit for a while
inc countones
ldaa countones
cmpa #10
bne LSB
inx ; now increment 'tens'
inc counttens
ldaa counttens
cmpa #10
bne MSB
bra start ; start from '00'
Delay_ms
psha
pshy
ldaa #DelayVal ; Number of msec to delay
staa Counter
Delay1 ldy #D_1MS ; 6000 x 4 = 24,000 cycles = 1ms
Delay2 dey ; this instruction takes 1 cycle
bne Delay2 ; this instruction takes 3 cycles
dec Counter
bne Delay1 ; not Dcount ms yet, delay again
puly ; Restore contents of ACC A before returning
pula
rts
end
It would be even better to have display code in a separate routine, and to switch active display more than once per counter increase. That could be a nice exercise for you :)