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.