This sample code demonstrates writing to an 8-digit 7-segment LED display (the HW-179 module) that uses the MAX7219 driver device. The MAX7219 is fully SPI compliant, and as such does not require the bit-banging exercises that were present in my earlier posts on LED displays equipped with the TM1637 and TM1638 drivers. Furthermore, the MAX7219 provides for BCD decoding that eliminates the necessity of code that converts numerical digits into their corresponding 7-segment 8-bit codes (although this mode of operation is possible with the MAX7219). The objective of this code sample is only to illustrate initialization of the MAX7219 display, and to show how the 16-bit address+data sequences can be sent as either 16-bit constants, 8-bit variable + 8-bit constant, or by two 8-bit variables, using PBP's SHIFTOUT command.

The MAX7219 driver provides for cascading configurations, thus allowing the HW-179 modules to be chained together to provide 16, 24, 32, etc. digit displays. An example of this will be provided in a subsequent code sample post.

Code:
'****************************************************************
'*  Name    : MAX7219_8-Digit_7-Segment_Demo.BAS                *
'*  Author  : Roberts                                           *
'*  Notice  : Copyright (c) 2021 Copyright (c) 2019             *
'*          : All Rights Reserved                               *
'*  Date    : 10/6/2021                                         *
'*  Version : 1.0                                               *
'*  Notes   : Developed on Microchip Curiosity Board with       *
'*          : PIC16F183456 uC and the HW-179 8-digit/7-segment  *
'*          : display driven by the MAX7219 driver via 3-wire   *
'*          : SPI interface, set to operate at 5 VDC.           *
'****************************************************************
'
' This brief demo program writes the digits 0 thru 9 and "-" to the HW-179 8-digit 7-segment LED display based on the
' MAX7219 interface driver.  The code includes the initialization sequence that (a) sets the decode mode to BCD,
' (b) sets the LED intensity to half-scale (8/16), (c) sets all 8 digits active, and (d) activates the display.
' After initialization, the code sets the test mode active for 1 second (e.g., all digits and all segments lit).  Then
' all digits are cleared, and counting begins with the right-hand most digit.  Each digit counts from 0 to 9 and then
' "-", and the counting progresses to the left one digit at a time.  Once all 8 digits are showing "-", the program
' cycles back to clearing the display and repeating.
' Data is sent to the display using PBP's SHIFTOUT command.  The code demonstrates how these 16-bit address + data
' commands can be constructed as either a single 16-bit constant, by an 8-bit variable + 8-bit constant, and by two 8-bit
' variables.  While the MAX7219 data registers are blanked upon power on, a microcontroller reset requires a procedure
' that writes 0x0F to all 8 digits in order to blank the digits.
'
'****************************************** PIC16F18346 Initialization *************************************************                                                 
'************************************** Configuration File for the PIC 16F18346 ****************************************
#CONFIG
    __config _CONFIG1, _FEXTOSC_OFF & _RSTOSC_HFINT32 & _CLKOUTEN_OFF & _CSWEN_ON & _FCMEN_ON
    __config _CONFIG2, _MCLRE_ON & _PWRTE_OFF & _WDTE_ON & _LPBOREN_OFF & _BOREN_ON & _BORV_LOW & _PPS1WAY_OFF & _STVREN_ON & _DEBUG_OFF
    __config _CONFIG3, _WRT_OFF & _LVP_OFF
    __config _CONFIG4, _CP_OFF & _CPD_OFF

#ENDCONFIG
@ ERRORLEVEL -306   ; turn off crossing page boundary message

OSCFRQ = 000100    ' Set internal osc to 16MHz
DEFINE OSC 16        ' Tell PBP that the device will clock at 16MHz (necessary for uSec pauses used in bit-banging)

ANSELA = 000000    ' PortA all digital / available pins are A0 through A5 (6 I/O's)
TRISA = 000000   ' PortA all outputs
'
'************************** Initialization and Variable Declarations *****************************************
'
' SPI signals use LATx.x assignments to prevent read/modify/write conflicts on a single I/O port
CS  Var LATA.2  ' uC chip select output pin
SCK Var LATA.4  ' uC clock out pin
SI  Var LATA.5  ' uC data out / LCD Data in pin
'
'
i VAR WORD       ' loop counter variable
j VAR byte       ' loop counter variable
CS = 1           ' Disable SPI device select CS for OLED 
'
'************************* Initialize the display parameters by sending 16-bit constants **********************
'                (See MAX7219 spec sheet for tables listing full range of initialization values)

    CS = 0
    SHIFTOUT SI, SCK, 1, [$0F01\16]         'Test display - illuminate all segments & all digits     
    CS = 1    
    PAUSE 1000                              'hold for 1 second
    
    CS = 0
    SHIFTOUT SI, SCK, 1, [$0F00\16]         'Return to normal display mode
    CS = 1    
    PAUSE 1000                              'Pause 1 second

    CS = 0
    SHIFTOUT SI, SCK, 1, [$09FF\16]         'Set decode mode for BCD
    CS = 1                                  '($0900 for no decoding - see MAX7219 spec sheet)
    PAUSE 10
    
    CS = 0
    SHIFTOUT SI, SCK, 1, [$0A07\16]         'Set display intensity to half scale
    CS = 1                                  '($0A00 for minimum brightness / $0A0F for maximum brightness)
    PAUSE 10
    
    CS = 0
    SHIFTOUT SI, SCK, 1, [$0B07\16]         'All 8 digits active
    CS = 1                                  '($0B01 for only digit 1 active - see MAX7219 spec sheet)
    PAUSE 10
    
    CS = 0
    SHIFTOUT SI, SCK, 1, [$0C01\16]         'Activate display
    CS = 1                                  '($0C00 for powering down the display - see MAX7219 spec sheet)
    PAUSE 10

'********************************************* Main Program ********************************************************** 
main:                                       
  For i = 1 to 8                            'Clear all 8 digit registers to blank
    CS = 0
    Shiftout SI, SCK, 1, [i,$0F]            'Clear each digit "i" by sending the blank character constant 0x0F
    CS = 1
    Pause 10
  Next i                                    'hold the display blank for 1 second
  Pause 1000

 For j = 1 to 8                             'the variable j is the 8-bit digit address register
  For i = 0 to 10                           'the variable i is the 8-bit data register
    CS = 0
    SHIFTOUT SI, SCK, 1, [j,i]              'Display 0 through 9 in digit 1 position (r/h most digit)
    CS = 1
    PAUSE 500                               'pause 1/2 second for counting
  Next i 
 Next j 
                                            
 Pause 2000                                 'hold the display for 2 seconds
                                          
Goto main