Name: | Mr. Ken Mathis |
Company: | ASC |
Web Site: | |
;FILE NAME:MAX7219
;Date:June 16, 2004
;Programmer:Ken Mathis
;Purpose of this program is to control several seven segment displays using the MAX7219
;seven segment display driver IC. The seven segment displays are multiplexed with the
;7219 and are commone cathode type displays.
;This test code controls only 3 seven segment displays. The code can easily be expanded
;for the max7219 to control up to 8 seven segment displays while consuming only 3 SX
;output pins
;Where appropriate, explanations are provided to account for more than 3 seven segment displays
;This configuration uses the SX internal oscillator as the timimg for shifting data
;out is not critical
;-----[Assembler directives]---------------------------------------
ifdef __SASM
DEVICE SX18L, STACKX, OPTIONX
IRC_CAL IRC_FAST
FREQ 4_000_000
else
DEVICE SX18AC, OPTIONX
endif
DEVICE TURBO, OSC4MHZ
RESET START
;-----[Define variables and constants]------------------------------
org $07 ;$07 is first free variable space
Decode ds 2 ;assign 2 bytes of space for Decode - 7 & 8
ShtDn ds 2 ;assign 2 bytes of space for Shutdown - 9 & A
ScnLmt ds 2 ;assign 2 bytes of space for Scan Limit - B & C
Inten ds 2 ;assign 2 bytes of space for Intensity - D & E
bitcnt ds 1 ;assign 1 byte of space for bit counter - F
;dig0, dig1, & dig2 represent three 7 segment displays with a common cathode and
;dig0 is the least significant display
dig0 ds 2 ;assign 2 bytes of space for Digit 0 - 10 & 11
dig1 ds 2 ;assign 2 bytes of space for Digit 1 - 12 & 13
dig2 ds 2 ;assign 2 bytes of space for Digit 2 - 14 & 15
;To display more digits variable manes MUST be added here sequentially
;after dig2 for the code to properly work.
; !!! IF 8 SEVEN SEGMENT DISPLAYS ARE USED, there will be no more room
;for the word counter (wrdcnt) in bank one. To avoid switching banks in
;this circumstance, the upper or lower byte of any of the initialization
;words (Decode, ShtDn, ScnLmt, or Inten) can be reused/reloaded with
;the appropriate value after the initialization if finished. A comment
;will be shown where to reload Decode if needed
wrdcnt ds 1 ;assign 1 byte of space for word counter - 16
;----[Define symbolic pin names]---------------------------------------
data EQU rb.1 ;data pin connects to pin 1 of 7219
clock EQU rb.2 ;clock pin connects to 13 of 7219
load EQU rb.3 ;load pin connects to 12 of 7219
;-----[calls should be placed on first page between org $000 and org $100]--
org $000
;5uS delay - generated using the delay code generator at sxlist.com
del_5uS
jmp $+1
jmp $+1
jmp $+1
jmp $+1
nop
nop
ret
;sub to shift out msbit of each byte into carry
rotate
rl ind ;move msbit into carry
jc high ;if carry is high jump to high
clrb data ;if carry is low ensure data pin is low
jmp $+2 ;jump 2 lines
high
setb data ;make data pin high
nop ;no operation
ret
;clock pulse generation to shift data out of SX into max 7219
shiftout
call del_5uS ;5 uS set-up time
setb clock ;make clock (rb.2) high
call del_5uS ;5 uS hold time
clrb clock ;make clock low
ret ;return
;-----[MAIN PROGRAM]------------------------------------------------------------
org $100
Start ;reset point
;-------[I/O port setting]------------------------------------------------------
mode $0f ;set mode for port direction
mov w,#$0
mov !ra,w ; all ra ports output
mov w,#$00
mov !rb,w ;all rb ports output
;-------[prepare variables for initialization of max7219]-----------------------
;mov w,#$XX loads the w register with hex value
;mov NAME,w loads value of w into variable name
;Later in this program the initiazation is explained in detail
mov w,#$09
mov Decode,w
mov Inten+1,w
mov w,#$0f
mov Decode+1,w
mov w,#$10
mov bitcnt,w
mov w,#$0c
mov shtdn,w
mov w,#$01
mov shtdn+1,w
mov dig0,w
mov w,#$0b
mov scnlmt,w
mov w,#$02
mov scnlmt+1,w
mov dig1,w
mov w,#$0a
mov inten,w
mov w,#$03
mov dig2,w
mov w,#$04
mov wrdcnt,w
;point to first register that will hold data to shift out which
;is Decode at address $07. NOTE that this is a SX18 and does not have an RC
;port.
mov w,#$07
mov fsr,w
;-------[The program currently causes display to load 4 to each digit. To test a
;different value, change four to any digit 0 to 9. Your actual program will load
;dig0+1, dig1+1 and dig2+1 with some dynamic data.
mov w,#$04
mov dig0+1,w
mov dig1+1,w
mov dig2+1,w
;------[MAX7219 Operation]----------------------------------------------------
;The 7219 must first be initialized. Initialization is done by sending serial
;data to the IC. Four 16 bit values sent will complete the initialization.
;To send a 16 bit value load is brought LOW, then each of 16 bits (msb 1st) is
;clocked into the IC, and load is then brought HIGH to complete the shifting
;of 16 bits into the device
;For each word sent to the IC, the most significant byte is the address and the
;lower byte sets the option for each particular function.
;For the descriptions that follow values will be shown as $Xx. The upper case x
;represents the upper nibble and the value is "don't care"
;DECODE MODE - Address $X9
;Options $X0 = No decoding
; $X1 = Decode digit 0 (BCD)
; $XF = Decode digits 0-3
; $FF = Decode digits 0-7
;Sending $090F sets decode mode to enable digits 0-3 and unstucts that the least
;sig nibble is BCD
;SHUTDOWN MODE - Address $XC
;Options $X0 = Shutdown
; $X1 = Normal Operation
;Sending $0C01 sets the IC for normal operation
;SCANLIMIT - Address $XB
;Options $Xx where the least significant nibble sets the number of digits
; to enable. digit 0, x = 0. digits 0 & 1 x = 1. digits 0, 1, & 2 x = 2
;Sending $0B02 enbables digts 0, 1 & 2
;Sending $0B07 enables all 8 digits
;INTENSITY - Address $XA
;Options $00 = minimum intensity
; $FF = maximum intensity
; See MAX7219 data sheet for resistor selection and current
;----[set up SX controll pins]--------------------------------------------------------
clrb data ;make data pin low
clrb clock ;make clock pin low
setb load ;make load pin high
call del_5uS ;wait 5 uS
;----[Start of routine to send out first 16 bits]-------------------------------------
clrb load ;enable 7219 to start accepting serial data.
j1
call rotate ;call routine to move msbit into carry and set data pin
;high or low depending on state of bit carried out
call shiftout ;call routine to shift data bit to 7219
dec bitcnt ;decrement bit counter
cjne bitcnt,#8,j2 ;check if 8 bits have been sent out
inc fsr ;if 8 bits were sent, increment fsr to point to next
;register
jmp $-8 ;move back up to call rotate
j2
cja bitcnt,#0,j1 ;check of bit counter is at zero (16 bits shifted out?)
setb load ;if 16 bits shifted out, load them into the 7219
dec wrdcnt ;check if the 4 initialization words shifted out
cja wrdcnt,#0,j3 ;if word counter is above 0, jump to j3
jmp $+5 ;if the 4 initialization words shifted out jump down 5 lines
j3
mov w,#$10 ;reload bit counter with 16
mov bitcnt,w ;reload bit counter with 16
inc fsr ;increment fsr to point to the next register
jmp $-$18 ;jump up to the "clrb load" instruction to start another
;sequence of shifting out 16 more bits
;-----[shift actual data into max7219]---------
;Data is sent to the 7219 in the same manner as the initialization described above.
;load is brought LOW, 16 bits clocked into device and load is brought HIGH to complete
;the loading of one digit.
;For each digit, the upper byte of 16 bits is the address of the digit and the lower
;byte is the value sent to the 7 segment. This value is either BCD or the "word" to control
;each of the 8 segments (decimal point). Remember that DECODE MODE determines how to
;use the lower byte
;For digit 0 the address is $01
; digit 1 the address is $02
; digit 2 the address is $03
;If decode mode was selected sending the 16 bit value of $0207 will tell the IC that
;digit number 1 gets a value of 7
mov w,#$10
mov fsr,w ;point to first address of digit 0 holding the most sig byte
mov bitcnt,w ;load the bit counter with 16
;If using 8 seven segment displays as decribed above, comment out the next two lines
mov w,#$03 ;since three digits are used in this example, wrdcnt is loaded w/3
mov wrdcnt,w
;Use these next two lines if 8 seven segments are used.
; mov w,#$08
; mov Decode,w
;----[Start of routine to send out first 16 bits of TEST data]-------------------------------------
;The rest of this code is exactly the same as the initialization code, so no comments added here.
;see initialzation above for comments.
clrb load
j4
call rotate
call shiftout
dec bitcnt
cjne bitcnt,#8,j5
inc fsr
jmp $-8
j5
cja bitcnt,#0,j4
setb load
;If using 8 seven segment displays as decribed above, comment out the next two lines
dec wrdcnt
cja wrdcnt,#0,j6
;Use these next two lines
; dec Decode
; cja Decode,#0,j6
jmp $+5
j6
mov w,#$10
mov bitcnt,w
inc fsr
jmp $-$18
setb load
sleep
END
Interested: