How do I read the state of the switch bank (p2) and display the corresponding (*) value as a 2-digit hexadecimal number on the rightmost two digits of the quad 7-segment LED display? I know that when I display the first digit, I need to wait for approximately 200 instructions, then display the second digit and wait for approximately 200 instructions. A closed switch produces a 0 bit on P2, but I want to interpret a closed switch as a 1.

This is what I have so far:

; Count in binary on the bank of 8 LEDs
MOV A, #0

again:
INC A
CPL A
MOV P1, A
CPL A
JMP again

; Count from 0 to 9 repeatedly and
; display on first digit of the
; quad 7-seg display

MOV R4, #0
MOV DPTR, #0x0070  ; 16-bit register!

loop:
MOV A, R4
MOVC A, @A+DPTR
MOV P1, A
INC R4
CJNE R4, #10, loop
MOV R4, #0
JMP loop

ORG 0x0070 ; Following data will be placed starting at 0x0070

digit_codes:
; Table of digit codes
; for 7-segment display
DB 11000000b ; 0
DB 11111001b ; 1
DB 10100100b ; 2
DB 10110000b ; 3
DB 10011001b ; 4
DB 10010010b ; 5
DB 10000010b ; 6
DB 11111000b ; 7
DB 10000000b ; 8
DB 10010000b ; 9
1

There are 1 best solutions below

0
old_timer On

So there are multiple questions going on here. First off you state this is a quad 7 segment display. But that is not enough information and you have not provided a schematic. So this implies either 11 or 12 signals between the mcu and the display if you want to use all four digits. If you only want the two right most digits on the display this means either 9 or 10 signals between the mcu and the display.

7 segment often has a period/decimal point so is often 8 segments actually, but you only need 7 of them for digits. and then is your display common anode or cathode? Do you drive the LEDs high with a common per digit and sink with the 7 or 8 others or do you have four common grounds and then drive the LEDs from the other 7 or 8 pins?

DB 11000000b ; 0
DB 10000000b ; 8

That implies to me that you are sinking not sourcing so you have a common signal for that digit that you drive high and then these either turn on 6 or 7 segments depending on if it is a 0 or a 8, and the msbit I assume is the decimal point which you want off.

So if you want to put something on the right two digits of the display then you drive the common for the right most digit high, and the commons for the other three low or float them (often done by making those pins inputs). and then you drive these 8 with the value in your table. hold that state for some period of time fast enough to see. then drop the common for the rightmost digit or float it and then assert the value from the table you want for the second digit and then drive the common for the second digit, blink that for some period of time.

You have to blink them long enough to see but overall blink all the digits so fast that we perceive them as being on at the same time (persistence of vision).

Until you can put digits on these rightmost displays then you cannot move forward with using the display (necessarily). Try for example counting from 0 to 99 (counting ones from 0-9 then increment tens, and repeat) and put ones on the right most display and tens on the second. Repeat each "number" thousands of times so that it as a number remains visible (set 00 on the display for a thousand loops, within each loop blink the right and next segment for 200 instructions).

Next and a separate topic you are interested in a switch state. It is not uncommon for a switch to be pulled high and the switch closure indicates grounds the input pin. so a pressed is a 0 and a not pressed is a 1. simply invert that either xor the value read with the pin with a 1 (anything xored with one inverts it).

00 0
01 1 <- zero is inverted to a one
10 1 
11 0 <- one is inverted to a zero

or do an if-then-else:

if pin == 0 then display 1
else             display 0

And you can do this with a single segment on the display, drive the common for one segment and then use the pattern for 0 or 1 based on what you see, you don't need to blink:

drive common high for one or all digits
loop
read input pin port
isolate pin
if pin==0 write DB 11111001b ; 1 to port
else    write 11000000b ; 0 to port
uncondintional jump/branch to  loop

Then press and release the switch and see if the numbers change on whichever segments you are driving.

Then combine the knowledge gained from both experiments. bare-metal is 99% reading and experiments. almost all of the work done bare-metal programming is throwaway code used to learn the thing you are trying to program. And you should design the code as throwaway not try to make some big one size fits all thing. do the separate learning experiences. and then make a third program that combines the knowledge from the prior two parts needed to learn.

Yet another experience here is that switches bounce, do not use an interrupt for this task, almost never, if not always never, hook a button up to an interrupt as that can just fail to work. at best you set a timer up to interrupt and then sample the button(s) in the timer interrupt not in a pin based edge interrupt. The experiment here would be to say have a loop tightly polls the switch input and counts the state changes, after some number say 20 state changes then display something or change the display, you should find that it takes less than 10 button presses if even more than one to get 20 state changes on the switch depending on how bad it is bouncing.

For the stated desire of displaying a 00 or 01 then you poll the input pin, determine the desired output if pin==0 then I want to display 01, else 00. then blink each digit once.

You said hexadecimal but you only have a table to cover 0-9 fortunately a hexadecimal 00 vs 01 you always drive the second digit a 0 and the lower digit is either 0 or 1 so you can do that with what you have.