In this project the PIC is used to control the 7-segment LED display directly. The demonstration program is just a counter from 0 to 9 in about 1sec intervals. I use a 2-digit LED display, whose both digits are connected in parallel, so are driven simultaneously. Therefore, the displayed sequence of numbers is 00, 11, 22, ..., 99 repeated periodically.
The LED display I use is HDSP-521E, all whose segments have a common anode. For simplicity I use just one current-limiting resistor of 220 Ohm connected to the common anode of each digit. This is not a very good solution, since the number of highlighted segments for digits varies from 2 to 7 which results in variation of the digit brightness. The digit 8 becomes this way brighter that digit 1, because practically the same current goes through 7 or 2 segments, respectively. However, the dependency of the LED brightness on current is not linear so the difference is not very noticeable. This is particularly true for a dark room. A better solution would be to put a separate resistor between the PIC and LED block, this way raising their count up to 7.
| Schematic | Layout | Segm. codes | ||
![]() |
Taking into account the segments topology, in order to display, say, number 5 we have to connect the segments a,f,g,c,d to the ground. As it follows from the schematic, the following byte has to written to PORTB: 01110110. The program starts with initializing the digit codes for each of 10 digits in the function initSegments(). The ones in each code correspond to segments needed to be on for displaying the corresponding digit. In our application the binary complements of the codes has to be written to portB. This is achieved by applying the instruction xorlw 0xFF. If a LED with common cathodes is used then this instruction should be taken off.
After displaying each of 10 numbers 00, ..., 99 we wait for about 1sec before updating it. The currently displayed number is stored in variable n. If after incrementing n becomes 10 it is reset back to 0 and the sequence starts again over and over.
TITLE "7seg1.asm" ; displaying 0,1,...,9 on a 7-seg LED
List P=16F84a, R=DEC
INCLUDE "p16F84a.inc"
; data segment
CBLOCK 0x00C
n ; the number to display
i,j,k ; variables used in delay()
segments:10 ; storage for segment codes
ENDC
; code segment
PAGE
__CONFIG _CP_OFF & _PWRTE_ON & _WDT_OFF & _XT_OSC
org 0
bsf STATUS, RP0 ; change to BANK 1
movlw 0xFF
movwf PORTB ; turn off all LED segments
clrf TRISB ^ 0x80 ; Enable RB1-RB7 for Output
movlw 0x7F ; Enable Internal Pull-Ups
movwf OPTION_REG ^ 0x80
bcf STATUS, RP0 ; back to BANK 0
; setup codes for the LED segments
call initSegments
clrf n ; start counting with n=0
loop
movf n, w
addlw segments
movwf FSR ; FSR = pointer to digit code
movf INDF, w ; w = code[digit]
xorlw 0xFF ; highlight only segs for bit=0
movwf PORTB ; light on the digit
call delay ; delay
incf n, f ; n++
movf n, w
sublw 10
btfss STATUS, Z ; n == 10?
goto loop ; NO - continue
clrf n ; YES - start from digit 0 again
goto loop
initSegments ; fill the array of segment codes
movlw b'11011110' ; gidit 0
movwf segments+0
movlw b'00011000' ; digit 1
movwf segments+1
movlw b'11101100' ; digit 2
movwf segments+2
movlw b'01111100' ; digit 3
movwf segments+3
movlw b'00111010' ; digit 4
movwf segments+4
movlw b'01110110' ; digit 5
movwf segments+5
movlw b'11110110' ; digit 6
movwf segments+6
movlw b'00011100' ; digit 7
movwf segments+7
movlw b'11111110' ; digit 8
movwf segments+8
movlw b'01111110' ; digit 9
movwf segments+9
return
delay ; a simple delay procedure
movlw 3
movwf k
L1 movlw 200
movwf i
L2 movlw 200
movwf j
L3 decfsz j, f
goto L3
decfsz i, f
goto L2
decfsz k, f
goto L1
return
end
|
Download 7seg1.asm
Last modified:Mon, Jan 23, 2023.