Hello, everyone!
I have a task that is to do a 00 to 99 counter, the one I'll have to show in two 7-segment displays, but I'm having big troubles with the 7SD, because I have no idea of how can I control the displays, I've done the counter in the port B, here's the code:
; variable/data section
;
ORG RAMStart ; Insert your data definition here
ExampleVar: DS.B 1
VAR1: EQU $0081
VAR2: EQU $0082
;
; code section
;
ORG ROMStart
; Include device initialization code
INCLUDE 'MCUInit.inc'
_Startup:
LDHX #RAMEnd+1 ; initialize the stack pointer
TXS
; Call generated Device Initialization function
JSR MCU_init
mainLoop:
LIMPIA: MOV #$FF, PTBDD ;LIMPIA PUERTO B
CLR ($83)
CONTADOR: INC PTBD ;INCREMENTO DEL CONTADOR
BSR DELAY
LDA PTBD ;CARGA A ACUMULADOR CON CONTADOR
BRA COMPARADOR ;SE VA AL CONVERSOR (PUEDE SER QUE SE QUITE 'BRA')
DELAY: MOV #$01, VAR1
LOOP2: MOV #$01, VAR2
LOOP1: DBNZ VAR2, LOOP1
DBNZ VAR1, LOOP2
RTS
COMPARADOR:
INC ($83)
CMP #$63
BNE CONTADOR
BRA LIMPIA
NOP
The counter is shown as a binary counter in port B, what can I to make the displays work?
Hello,
I will assume that you require to directly drive each display digit, without multiplexing. You will therefore require a total of 14 pins, or 16 pins if you also requre DP connections. I would suggest to use Port B for one of the digits, and Port C connections for the other digit.
The code will be slightly simpler if you have identical segment layout for each digit, since you will require to have a look-up table to convert the BCD value for each digit to drive the required display segments. With the same segment layout, a single table would cater for both digits. The size of the table will be 10 bytes, to represent the values 0 through 9.
On this basis, you cannot use Port B as a counter register - you will need to define a separate variable in RAM for this purpose. This should preferably be allocated within zero-page RAM, so that the INC instruction can be used to directly increment.
To display the current counter value, you will need to convert the binary counter value to two BCD values, before using the look-up table. Consider the following code snippet -
; 7-segment look-up table
TABLE:
DC.B ...
SHOW_COUNT:
LDA COUNTER
; Commence binary to BCD conversion
CLRH
LDX #10
DIV
PSHH ; Save LS digit to stack
; Display the result
TAX ; MS digit value (0-9)
CLRH
LDA TABLE,X ; Fetch 7-segment value
STA PTCD ; Display MS digit
PULX
LDA TABLE,X ; Fetch 7-segment value
STA PTBD ; Display LS digit
RTS
I have not shown the contents of the look-up table, as this will depend on the allocation of segment, and whether common anode, or common cathode displays are used.
You will require a current limiting resistor in series with each display segment. To prevent over-stressing the device, the current should be limited to 5 mA per segment. If you need greater segment current, external buffers will be needed, possibly using multiple Darlington transistor buffers (with 7 or 8 per package).
The number of MCU pins required can be significantly reduced to about three pins when the display digits are driven by external shift register packages (e.g. 74HC595), but this will require more complex code.
Regards,
Mac
Thanks a lot for your answer, I've been working on the program with the things you explained to me, and I made this code:
; variable/data section
;
ORG RAMStart ; Insert your data definition here
ExampleVar: DS.B 1
VAR1: EQU $0081
VAR2: EQU $0082
COUNTER: EQU $0083
;
; code section
;
ORG ROMStart
; Include device initialization code
INCLUDE 'MCUInit.inc'
_Startup:
LDHX #RAMEnd+1 ; initialize the stack pointer
TXS
; Call generated Device Initialization function
JSR MCU_init
mainLoop:
MOV #$FF, PTBDD
MOV #$FF, PTCDD
CLEAN:
CLR COUNTER
CLR ($84)
COUNT: INC COUNTER ;COUNTER
LDA COUNTER ;LOAD A WITH MEM. $83
BRA COMPARISON ;GO TO COMPARISON
DELAY: MOV #$01, VAR1
LOOP2: MOV #$01, VAR2
LOOP1: DBNZ VAR2, LOOP1
DBNZ VAR1, LOOP2
RTS
COMPARISON:
CMP #$63 ;COMPARE AGAINS #99 DECIMAL
BEQ CLEAN
JSR SHOW_COUNT ;IF NOT EQUAL TO 99 THEN GO TO COUNT
BRA COUNT
SHOW_COUNT:
LDA COUNTER
; Commence binary to BCD conversion
CLRH
LDX #10
DIV
PSHH ; Save LS digit to stack
; Display the result
TAX ; MS digit value (0-9)
CLRH
LDA TABLE,X ; Fetch 7-segment value
STA PTCD ; Display MS digit
PULX
LDA TABLE,X ; Fetch 7-segment value
STA PTBD ; Display LS digit
RTS
TABLE:
What do you think? Am I doing something wrong?
About the table, I'm working with Common Cathode Displays, and I don't seem to understand how am I gonna do the table, I found one it's this one:
TABLE:
DC.B $C0
DC.B $F9
DC.B $A4
DC.B $B0
DC.B $99
DC.B $92
DC.B $82
DC.B $F8
DC.B $80
DC.B $90
DC.B $88
DC.B $83
DC.B $C6
DC.B $A1
DC.B $86
DC.B $8E
which it's supposed to work with common cathode, but at the time I try to debug it seems like the ports make other things but numbers, how can I make a table for this?
thank you a lot!
Regards
Hello Ana!
Was your question solved out? We'd like to know, keep us posted :smileywink:
Monica
Hello,
With common cathode displays, the cathode will be grounded, and each segment will become active when a high logic voltage is applied, i.e. positive logic. Conversely, for common anode displays, the anode would be connected to Vdd, and each segment will become active when a low logic voltage is applied, i.e. negative logic.
Assuming that the 'a' segment connects to bit-0, then sequentially through to the 'g' segment connecting to bit-6, which appears to be the case, the table that you are using would seem to be that required for a common anode display. Thus every segment not required will be lit for the other display type.
This is easy to fix with the following modified code - simply one's complement the table value before writing the display digit.
SHOW_COUNT:
LDA COUNTER
; Commence binary to BCD conversion
CLRH
LDX #10
DIV
PSHH ; Save LS digit to stack
; Display the result
TAX ; MS digit value (0-9)
CLRH
LDA TABLE,X ; Fetch 7-segment value
COMA ; For common cathode display
STA PTCD ; Display MS digit
PULX
LDA TABLE,X ; Fetch 7-segment value
COMA ; For common cathode display
STA PTBD ; Display LS digit
RTS
Regards,
Mac