Wednesday, 28 September 2011

24. Homebrew Hex to 7 segment display drivers working.

Yes I did it. I wrote PIC machine code to program the PIC16F505 Microcontrollers to perform the function of Hex to 7 segment Display Drivers.

I started writing the code before I even had the PIC Programmer or PIC chips. On the first run, I found I had an issue with the inputs not being grounded with pull-down resistors, causing the inputs to fluctuate randomly, but some 10K resistors on the inputs connected to ground sorted that. If you have a switch, when its on its fine, a voltage goes to set the pin high or 1. When the switch is off the pull-down resistors connect the pin to ground giving a low or 0 input.

I did initially opt to use one pin on the PIC16F505 as a latch, so it would only display the input when a button was pressed. I decided it wasn't necessary and the program loops around reading the inputs and setting the outputs to light up the LEDs.

Hers's a pic of the setup with annotation.

The PIC assembly code is here:

; include file with config bit definitions
 include "" ;

; config - enable internal OSC and allow use of RB4
;        - disable MCLRE and allow use of RB3 (input only)
;        - disable Watchdog Timer, we don't use it.
 __config _IntRC_OSC_RB4EN & _MCLRE_OFF & _WDT_OFF

; local regsiters
INB equ 0x08
INC equ  0x09
INPUT equ  0x0A
OUTB equ 0x0B
OUTC equ 0x0C
PWRSTS equ  0x0D
SEGDATA equ 0x10

SEG0 equ 0x10
SEG1 equ 0x11
SEG2 equ 0x12
SEG3 equ 0x13
SEG4 equ 0x14
SEG5 equ 0x15
SEG6 equ 0x16
SEG7 equ 0x17
SEG8 equ 0x18
SEG9 equ 0x19
SEGA equ 0x1A
SEGB equ 0x1B
SEGC equ 0x1C
SEGD equ 0x1D
SEGE equ 0x1E
SEGF equ 0x1F

; start here 
 org 000
 movf STATUS,PWRSTS ; Save Power on status

; Port configuration
;                                        a
;              +-----+                 ---
;         VCC [|     |] GND           f| g |b
;  D3 --> RB5 [|     |] RB0 --> a ---
;  D2 --> RB4 [| PIC |] RB1 --> b     e|   |c
;  D1 --> RB3 [| 16F |] RB2 --> c       ---
;  D0 --> RC5 [| 505 |] RC0 --> d        d
;  NC     RC4 [|     |] RC1 --> e
;   g <-- RC3 [|     |] RC2 --> f
;              +-----+

;                 RRRRRR
;                 BBBBBB
;                 543210
init movlw b'111000' ; Set PORTB Pins
 tris PORTB

;                 RRRRRR
;                 CCCCCC
;                 543210
 movlw b'100000' ; Set PORTC Pins
 tris PORTC

; Load Segment values into memory.
;Digit gfedcba abcdefg a b c d e f g
;0 0x3F 0x7E on on on on on on off
;1 0x06 0x30 off on on off off off off
;2 0x5B 0x6D on on off on on off on
;3 0x4F 0x79 on on on on off off on
;4 0x66 0x33 off on on off off on on
;5 0x6D 0x5B on off on on off on on
;6 0x7D 0x5F on off on on on on on
;7 0x07 0x70 on on on off off off off
;8 0x7F 0x7F on on on on on on on
;9 0x6F 0x7B on on on on off on on
;A 0x77 0x77 on on on off on on on
;b 0x7C 0x1F off off on on on on on
;C 0x39 0x4E on off off on on on off
;d 0x5E 0x3D off on on on on off on
;E 0x79 0x4F on off off on on on on
;F 0x71 0x47 on off off off on on on

 movlw 0x3F
 movwf SEG0

 movlw 0x06
 movwf SEG1

 movlw 0x5B
 movwf SEG2

 movlw 0x4F
 movwf SEG3

 movlw 0x66
 movwf SEG4

 movlw 0x6D
 movwf SEG5

 movlw 0x7D
 movwf SEG6

 movlw 0x07
 movwf SEG7

 movlw 0x7F
 movwf SEG8

 movlw 0x6F
 movwf SEG9

 movlw 0x77
 movwf SEGA

 movlw 0x7C
 movwf SEGB

 movlw 0x39
 movwf SEGC

 movlw 0x5E
 movwf SEGD

 movlw 0x79
 movwf SEGE

 movlw 0x71
 movwf SEGF

; End of initialisation

; To here 37 Instructions @ 4MHz = 37uS

; Main Program Starts here.
poweron clrf OUTB  ; Clear output Register B
 clrf OUTC  ; Clear output Register C
 btfss PWRSTS,RBWUF; Check Power-On Status
 goto display  ; blank if power on

; Reset output values and indexes
loop clrf OUTB  ; Clear output Register B
 clrf OUTC  ; Clear output Register C
 movlw SEGDATA  ; Load W with SEG DATA base
 movwf FSR  ; Save to FSR

; read value from PORTs
 movf PORTB,W      ; Read PORTB
 movwf INB  ; Save PORTB
 movf PORTC,W  ; Read PORTC
 movwf INC  ; Save PORTC

; combine port reads into a nibble in W register
 clrf INPUT  ; Clear INPUT register
 btfsc INB,RB5  ; Test RB5 (D3)
 bsf INPUT,3  ; Set D0
 btfsc INB,RB4  ; Test RB4 (D2)
 bsf INPUT,2  ; Set D1
 btfsc INB,RB3  ; Test RB3 (D1)
 bsf INPUT,1  ; Set D2
 btfsc INC,RC5  ; Test RC5 (D0)
 bsf INPUT,0  ; Set D3
 movf INPUT,W  ; Move value to W

; add value to index register and fetch segment value
 addwf FSR,F  ; Add index to FSR pointer

; prepare register output bits
 btfsc INDF,0  ; Test for 'a' segment
 bsf OUTB,RB0 ; Set 'a' segment
 btfsc INDF,1  ; Test for 'b' segment
 bsf OUTB,RB1 ; Set 'b' segment
 btfsc INDF,2  ; Test for 'c' segment
 bsf OUTB,RB2 ; Set 'c' segment
 btfsc INDF,3  ; Test for 'd' segment
 bsf OUTC,RC0 ; Set 'd' segment
 btfsc INDF,4  ; Test for 'e' segment
 bsf OUTC,RB1 ; Set 'e' segment
 btfsc INDF,5  ; Test for 'f' segment
 bsf OUTC,RB2 ; Set 'f' segment
 btfsc INDF,6  ; Test for 'g' segment
 bsf OUTC,RB3 ; Set 'g' segment

; move output to ports
display movf OUTB,W  ; Get values to send to PORTB
 movwf PORTB  ; Send to PORTB
 movf OUTC,W  ; Get values to send to PORTC
 movwf PORTC  ; Send to PORTC

; around again
 goto loop  ; go back to loop - 50uS loop


  1. hey!!!! I badly need this. can you share your codes? :(((

  2. Hi, I've post the code. Enjoy!

    1. wow! thank you so much sir dave!!!! thanks thanks thanks!!!!!!!!!!!!!!!
      so you've received my first and last tweet. haha

  3. Thanks for posting this up - I had been searching the web for a bin -> 7-seg display that shows 0-9,A-F and stumbled the same road block as you (the 74 series only did 0-9). I might have a look at this solution and build it.