Ken Mathis of ASC shares this code:
;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