PIC Projects

Driving multiple 7-segment LED displays

In this project the PIC is used to control a block of two7-segment LED displays directly. The demonstration program is just a counter from 00 to 99 in about 500msec intervals. Therefore, the displayed sequence of 100 numbers is 00, 01, 02, ..., 99 repeated periodically.

The LED display I use is HDSP-521E, all whose segments have a common anode. As in the last experiment on driving a single-digit LED, I use just one current-limiting resistor of 220 Ohm connected to the common anode of each digit. A better solution would be to put a separate resistor between the PIC and LED block.

Schematic Layout Segm. codes
matrix

Because of a limited number of PIC pins, we cannot display each of the digits at the same time. A practical solution is to alternate displaying them starting with the left one, then followed by the right one periodically. This way one digit will be displayed in each moment, but due to the human eye ability to "remember" am image for about 25 msec we will have an impression of displaying both digits simultaneously.

In the sample program below each digit on the LED display is active for 10msec which eliminates flickering. To switch between the digits we use PNP transistors controlled by the PORTA of PIC. The codes at pins RA0 and RA1 alternate between 1 and 2 (01 and 10 in binary) resulting in displaying the left and the right digit, respectively (the displayed digit corresponds to 0 at the corresponding pin of PORTA).

Displaying a digit is implemented in function displayDigit. This function starts with flipping the state of PORTA to display the corresponding digit. This is controlled by the variable d alternating between 1 and 2 as described above. After that the code corresponding to the digit n (passed as a parameter) is output to PORTB as in the last experiment. The function completes by calling a 10msec delay() function. The delay() function takes a parameter del as a number of milliseconds. The del-loop of this function consists of 5 instructions and executes in 5 CPU cycles (the goto instruction takes 2 cycles). Thus, each iteration of this loop takes 5μs for PIC1684A @ 4Mhz. This loop is repeated 200 times providing a delay of 5μs·200=1msec. Therefore, id the parameter del is 10, this code provides a 10msec delay.

The variable s is used to control the update speed of the counter. It is decremented from the initial value of 25 after each loop through the display digits, i.e. once in about 20msec. This results in updating the number on the display after every 20*25=500msec. The variables n1 and n0 control the digits currently displayed on the left and the right LED display, respectively. As soon as the variable s reaches the value 0, n0 is incremented on 1. If n0 reaches 10 it is reset back to 0 and n1 is incremented. When n1 reaches 10 it is reset back to 0 and the entire sequence of numbers 00, 01, ..., 99 will be repeating over and over.

 TITLE  "7seg2.asmt"    ; displaying 0,1,...,99 on a double digit LED
 List P=16F84a, R=DEC
 INCLUDE "p16F84a.inc"

; data segment
 CBLOCK 0x00C                   
 del, n					; variables for passing the parameters
 delTMP					; local var for the delay function 
 n1, n0					; digits to display on LEDs (left,right)
 d					; currently processing digit (1 or 2) 
 s					; counter update speed (500 ms)
 segments:10				; 7-seg codes array
 ENDC

; code segment
 PAGE
 __CONFIG _CP_OFF & _PWRTE_ON  & _WDT_OFF & _XT_OSC

  org 0                      		; start program at the beginning of mem
  	bsf    	STATUS, RP0      	; change to BANK 1
	movlw	3
	movwf	PORTA			; turn off all digits	
	
  	clrf    TRISB ^ 0x80      	; enable RB1-RB7 for output
  	movlw	0x1C
  	movwf	TRISA ^ 0x80		; enable RA0 and RA1 for output 
  	
  	movlw  	0x7F              	; enable internal Pull-Ups
  	movwf  	OPTION_REG ^ 0x80
  	bcf    	STATUS, RP0        	; back to BANK 0

; initialization
	call 	initSegments
    	clrf	n1          		; start counting with 00
    	clrf	n0 
   	movlw	1           		; start displaying the left digit
	movwf	d			; this number will flip between 2 and 1
	movlw	25			; set up counter update speed 500ms
	movwf	s			; 2*10*25 = 500ms 

; main loop
loop
	movf	n1, w       		; display the left digit n1
	movwf	n			; pass n1 to displayDigit as n
	call	displayDigit		; update the left digit

	movf	n0, w			; display the left digit n0
	movwf	n			; pass n0 to displayDigit
	call	displayDigit		; update the right digit

	decfsz	s, f			; time to update the counter?
	goto 	loop			; NO - display same digits n1,n0 again

; update the counter digits n1 and n0
	movlw	25			; YES - update n0 (and n1)
	movwf	s			; restore s

	incf	n0, f			; n0++ (the right digit)	
 	movf	n0, w
	sublw	10	   
	btfss	STATUS, Z		; n0 == 10?	
	goto	loop			; NO - continue

	clrf 	n0 			; YES - reset n0 to 0
	incf	n1, f			; increment the right digit
	movf	n1, w
	sublw	10
	btfss	STATUS, Z		; n1 == 10?
	goto 	loop			; NO - digits update is done
	clrf	n1			; YES - reset n1 to 0
	goto 	loop

; procedures
displayDigit   				; display digit n at position d
  	movf	d, w
	movwf	PORTA			; start displaying the digit #d
	xorlw	3           		; flip d
	movwf	d			; save it

	movfw	n			; get parameter to w
	addlw	segments
	movwf	FSR         		; FSR is a pointer to the digit code
	movf	INDF, w			; w = segments[digit]
	xorlw	0xFF			; invert the code for a common anode LED
	movwf	PORTB       		; light on the digit
	
	movlw	10			; a 10ms delay
	movwf	del
	call 	delay				
	return

initSegments				; set up 7-seg digit 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 delay for del milliseconds
	movlw 	200
	movwf	delTMP

delL	nop				; this loop takes 5us*200 = 1ms
	nop				; for PIC16F84A @ 4 Mhz
	decfsz	delTMP, f
	goto 	delL

	decfsz	del
	goto 	delay
	return

 end

Download 7seg2.asm


Last modified:Mon, Jan 23, 2023.

08616