MAX7221
MAX7219.MAX7221 History
Show minor edits - Show changes to output
Changed line 48 from:
* Author : Ahmed Lazreg (octal@pocketmt.com) *
to:
* Author : Ahmed Lazreg (ahmed.lazreg@pocketmt.com) *
Changed line 122 from:
* Author : Ahmed Lazreg (octal@pocketmt.com) *
to:
* Author : Ahmed Lazreg (ahmed.lazreg@pocketmt.com) *
Changed line 211 from:
* Author : Ahmed Lazreg (octal@pocketmt.com) *
to:
* Author : Ahmed Lazreg (ahmed.lazreg@pocketmt.com) *
Changed line 106 from:
WriteValue(DecToStr(i))
to:
WriteValue(DecToStr(i)) ' use FloatToStr(..) for floating point values
Changed line 1 from:
to:
!!!Maxim Integrated(tm) MAX7219/MAX7221
Changed line 12 from:
!!!Main Features of Swordfish MAX7219/MAX7221 module :'''
to:
!!!Main Features of Swordfish MAX7219/MAX7221 module :
Changed lines 11-12 from:
to:
!!!Main Features of Swordfish MAX7219/MAX7221 module :'''
Changed lines 40-41 from:
!!!Example Code
!!!Example Code
to:
!!!Example Code for single MAX7219 module
Added lines 112-113:
!!!Example Code two (02) cascaded MAX7219 modules
Changed line 11 from:
'''Main Features:'''
to:
'''Main Features of Swordfish MAX7219/MAX7221 module :'''
Added line 1:
'''Maxim Integrated(tm) MAX7219/MAX7221'''
Added lines 9-10:
http://www.pocketmt.com/images/max7219.png
Deleted lines 35-36:
Changed lines 38-40 from:
!!!Module Code
to:
??? diagram (coming soon)
!!!Example Code
!!!Example Code
This program uses 2 MAX7219 modules, each handling 8 7Seg display module.
!!!Example Code
!!!Example Code
This program uses 2 MAX7219 modules, each handling 8 7Seg display module.
Changed lines 55-58 from:
* Modified: *
* Notes : This module handles Maxime Integrated(TM) MAX7219/MAX7221 *
* Serially Interfaced, 8-Digit LED Display Drivers *
* It can be used via Hardware or Software SPI modules *
*
*
* It can be used via Hardware or Software SPI modules
to:
* Desc. : Test program for MAX7219 module *
* *
* *
Changed lines 60-62 from:
Module MAX7219
to:
Program Max7219_test
Device = 18F452
Clock = 20
Include "utils.bas"
Device = 18F452
Clock = 20
Include "utils.bas"
Changed lines 67-135 from:
// Number of cascaded display modules
#if IsOption(MAX7219_DISP_COUNT) And Not (MAX7219_DISP_COUNT > 0)
#error MAX7219_DISP_COUNT, "Invalid option, must be > 0"
#endif
#option MAX7219_DISP_COUNT = 1
Const MAX7219_DISPLAY_COUNT = MAX7219_DISP_COUNT
// hardware or software SPI...
#if IsOption(MAX7219_SPI_SOFTWARE) And Not (MAX7219_SPI_SOFTWARE in (true, false))
#error MAX7219_SPI_SOFTWARE, "Invalid option, must be TRUE or FALSE."
#endif
#option MAX7219_SPI_SOFTWARE = false
#if MAX7219_SPI_SOFTWARE = true // use software SPI...
Include "sspi.bas"
#else // use hardware SPI...
Include "SPI.BAS"
#EndIf
#Option MAX7219_CS = PORTC.1
// validate SCK pin...
#If IsOption(MAX7219_CS) And Not IsValidPortPin(MAX7219_CS)
#Error MAX7219_CS, "Invalid option. MCP_CS must be a valid port pin."
#EndIf
Public Dim
CS As MAX7219_CS.MAX7219_CS@ // Chip select
' To be used with WriteDigit(...) subroutine
' for digits (0..9) just send the digit itself
' for non-digits, use codes below as pValue param in WriteDigit(...)
Public Const
SYMB_DASH As Byte = $A, ' displays "-" symbol
SYMB_E As Byte = $B, ' displays "E" symbol
SYMB_H As Byte = $C, ' displays "H" symbol
SYMB_L As Byte = $D, ' displays "L" symbol
SYMB_P As Byte = $E, ' displays "P" symbol
SYMB_BLANK As Byte = $F ' blanks the digit
' Internal registers of the MAX7219
Private Const
REG_NO_OP As Byte = $00,
REG_DIGIT(8) As Byte = ($01, $02, $03, $04, $05, $06, $07, $08),
REG_DECODE_MODE As Byte = $09,
REG_INTENSITY As Byte = $0A,
REG_SCAN_LIMIT As Byte = $0B,
REG_SHUTDOWN As Byte = $0C,
REG_DISP_TEST As Byte = $0F
Private Dim fSelectedDisp As Byte
{
****************************************************************************
* Name : SelectDisplay *
* Purpose : Selects active display *
* param : pDisplayIndex = display index. *
* - First display module = 0 *
* - pDisplayIndex must be < MAX7219_DISP_COUNT *
****************************************************************************
}
Public Sub SelectDisplay(pDisplayIndex As Byte)
If pDisplayIndex >= MAX7219_DISPLAY_COUNT Then
pDisplayIndex = MAX7219_DISPLAY_COUNT
EndIf
fSelectedDisp = pDisplayIndex
to:
//#option MAX7219_SPI_SOFTWARE = true
Include "Max7219.bas"
Dim RED_LED As PORTB.1
Dim i As Word
Sub Init_MCU()
PORTA = %00000000
TRISA = %11111100
PORTB = %00000000
TRISB = $00
SetAllDigital()
Added lines 83-116:
Init_MCU()
High(RED_LED)
// main program loop
SetDisplayTestMode(true)
DelayMS(300)
SetDisplayTestMode(false)
WriteDigit(6, SYMB_E)
WriteDigit(7, SYMB_P)
DelayMS(1000)
BlankDisplay()
WriteValue("HELP-. ")
DelayMS(1000)
BlankDisplay()
WriteDigit(7, SYMB_H)
i = 0
While (true)
Toggle(RED_LED)
DelayMS(800)
WriteValue(DecToStr(i))
i = i +1
End While
End Program
=]
This program uses 2 cascaded MAX7219 modules, each handling 8 7Seg display module.
=code [=
High(RED_LED)
// main program loop
SetDisplayTestMode(true)
DelayMS(300)
SetDisplayTestMode(false)
WriteDigit(6, SYMB_E)
WriteDigit(7, SYMB_P)
DelayMS(1000)
BlankDisplay()
WriteValue("HELP-. ")
DelayMS(1000)
BlankDisplay()
WriteDigit(7, SYMB_H)
i = 0
While (true)
Toggle(RED_LED)
DelayMS(800)
WriteValue(DecToStr(i))
i = i +1
End While
End Program
=]
This program uses 2 cascaded MAX7219 modules, each handling 8 7Seg display module.
=code [=
Changed lines 118-152 from:
****************************************************************************
* Name : GetSelectedDisplay() *
* Purpose : returns actually selected Max7219 module *
****************************************************************************
}
Public Function GetSelectedDisplay() As Byte
result = fSelectedDisp
End Function
' MAX7219 command format is
' [D15][D14][D13][D12] [D11 - D8] [D7 - D0]
' [ x ][ x ][ x ][ x ] [ REG_ADDR] [msb DATA lsb]
{
****************************************************************************
* Name : WriteReg *
* Purpose : Writes pData byte to register address given by pRegAddress *
****************************************************************************
}
Public Sub WriteReg(pRegAddress As Byte, pData As Byte)
Dim i, count As Byte
CS = 0 ' must be set here mainly because of Max7221
count = MAX7219_DISPLAY_COUNT-fSelectedDisp-1
For i = 1 To count
WriteByte(REG_NO_OP)
WriteByte($00)
Next
WriteByte(pRegAddress)
WriteByte(pData)
count = fSelectedDisp
For i = 1 To count
WriteByte(REG_NO_OP)
WriteByte($00)
Next
CS = 1
*
* Purpose : returns actually selected Max7219 module
***************
}
End Function
' MAX7219 command format is
' [ x ][ x ][ x ][ x ] [ REG_ADDR] [msb DATA lsb]
{
* Name
* Purpose : Writes pData byte to register address given by pRegAddress *
****************************************************************************
}
Public Sub WriteReg
Dim i, count As Byte
CS = 0 ' must be set here mainly because of Max7221
count = MAX7219_DISPLAY_COUNT-fSelectedDisp-1
For i = 1 To count
WriteByte(REG_NO_OP)
WriteByte($00)
Next
WriteByte(pRegAddress)
WriteByte(pData)
count = fSelectedDisp
For i = 1 To count
WriteByte(REG_NO_OP)
WriteByte($00)
Next
CS = 1
to:
*************************************************************************
* Name : MAX7219.BAS *
* Author : Ahmed Lazreg ([email protected]) *
* http://www.pocketmt.com *
* http://www.microcodeproject.com *
* Notice : Copyright (c) 20015 Pocket MicroTechnics *
* : All Rights Reserved *
* Date : 01/01/2015 *
* Version : 1.0 *
* Desc. : Test program for MAX7219 module *
* *
*************************************************************************
}
Program Max7219_test
Device = 18F452
Clock = 20
Include "utils.bas"
Include "convert.bas"
//#option MAX7219_SPI_SOFTWARE = true
#option MAX7219_DISP_COUNT = 2
Include "Max7219.bas"
Dim RED_LED As PORTB.1
Dim i, j As Word
Dim k As Float
Sub Init_MCU()
PORTA = %00000000
TRISA = %11111100
PORTB = %00000000
TRISB = $00
SetAllDigital()
* Name : MAX7219.BAS *
* Author : Ahmed Lazreg ([email protected]) *
* http://www.pocketmt.com *
* http://www.microcodeproject.com *
* Notice : Copyright (c) 20015 Pocket MicroTechnics *
* : All Rights Reserved *
* Date : 01/01/2015 *
* Version : 1.0 *
* Desc. : Test program for MAX7219 module *
* *
*************************************************************************
}
Program Max7219_test
Device = 18F452
Clock = 20
Include "utils.bas"
Include "convert.bas"
//#option MAX7219_SPI_SOFTWARE = true
#option MAX7219_DISP_COUNT = 2
Include "Max7219.bas"
Dim RED_LED As PORTB.1
Dim i, j As Word
Dim k As Float
Sub Init_MCU()
PORTA = %00000000
TRISA = %11111100
PORTB = %00000000
TRISB = $00
SetAllDigital()
Added lines 156-205:
Init_MCU()
High(RED_LED)
// main program loop
SelectDisplay(0)
SetDisplayTestMode(true)
DelayMS(300)
SetDisplayTestMode(false)
SelectDisplay(0)
WriteDigit(6, SYMB_E)
WriteDigit(7, SYMB_P)
DelayMS(1000)
SelectDisplay(0)
BlankDisplay()
WriteValue("HELP-. ")
SelectDisplay(1)
WriteValue("-41.73")
DelayMS(1000)
SelectDisplay(0)
BlankDisplay()
WriteValue("HELP ")
SelectDisplay(1)
BlankDisplay()
WriteDigit(7, SYMB_L)
i = 0
j = 0
k = 0.0
While (true)
Toggle(RED_LED)
DelayMS(800)
SelectDisplay(0)
WriteValue(DecToStr(i))
SelectDisplay(1)
WriteValue(FloatToStr(k))
i = i +1
k = k + 0.2
End While
End Program
=]
!!!Module Code
=code [=
Added lines 207-282:
*************************************************************************
* Name : MAX7219.BAS *
* Author : Ahmed Lazreg ([email protected]) *
* http://www.pocketmt.com *
* http://www.microcodeproject.com *
* Notice : Copyright (c) 20015 Pocket MicroTechnics *
* : All Rights Reserved *
* Date : 01/01/2015 *
* Version : 1.0 *
* Modified: *
* Notes : This module handles Maxime Integrated(TM) MAX7219/MAX7221 *
* Serially Interfaced, 8-Digit LED Display Drivers *
* It can be used via Hardware or Software SPI modules *
*************************************************************************
}
Module MAX7219
Include "convert.bas"
Include "string.bas"
// Number of cascaded display modules
#if IsOption(MAX7219_DISP_COUNT) And Not (MAX7219_DISP_COUNT > 0)
#error MAX7219_DISP_COUNT, "Invalid option, must be > 0"
#endif
#option MAX7219_DISP_COUNT = 1
Const MAX7219_DISPLAY_COUNT = MAX7219_DISP_COUNT
// hardware or software SPI...
#if IsOption(MAX7219_SPI_SOFTWARE) And Not (MAX7219_SPI_SOFTWARE in (true, false))
#error MAX7219_SPI_SOFTWARE, "Invalid option, must be TRUE or FALSE."
#endif
#option MAX7219_SPI_SOFTWARE = false
#if MAX7219_SPI_SOFTWARE = true // use software SPI...
Include "sspi.bas"
#else // use hardware SPI...
Include "SPI.BAS"
#EndIf
#Option MAX7219_CS = PORTC.1
// validate SCK pin...
#If IsOption(MAX7219_CS) And Not IsValidPortPin(MAX7219_CS)
#Error MAX7219_CS, "Invalid option. MCP_CS must be a valid port pin."
#EndIf
Public Dim
CS As MAX7219_CS.MAX7219_CS@ // Chip select
' To be used with WriteDigit(...) subroutine
' for digits (0..9) just send the digit itself
' for non-digits, use codes below as pValue param in WriteDigit(...)
Public Const
SYMB_DASH As Byte = $A, ' displays "-" symbol
SYMB_E As Byte = $B, ' displays "E" symbol
SYMB_H As Byte = $C, ' displays "H" symbol
SYMB_L As Byte = $D, ' displays "L" symbol
SYMB_P As Byte = $E, ' displays "P" symbol
SYMB_BLANK As Byte = $F ' blanks the digit
' Internal registers of the MAX7219
Private Const
REG_NO_OP As Byte = $00,
REG_DIGIT(8) As Byte = ($01, $02, $03, $04, $05, $06, $07, $08),
REG_DECODE_MODE As Byte = $09,
REG_INTENSITY As Byte = $0A,
REG_SCAN_LIMIT As Byte = $0B,
REG_SHUTDOWN As Byte = $0C,
REG_DISP_TEST As Byte = $0F
Private Dim fSelectedDisp As Byte
{
* Name : MAX7219.BAS *
* Author : Ahmed Lazreg ([email protected]) *
* http://www.pocketmt.com *
* http://www.microcodeproject.com *
* Notice : Copyright (c) 20015 Pocket MicroTechnics *
* : All Rights Reserved *
* Date : 01/01/2015 *
* Version : 1.0 *
* Modified: *
* Notes : This module handles Maxime Integrated(TM) MAX7219/MAX7221 *
* Serially Interfaced, 8-Digit LED Display Drivers *
* It can be used via Hardware or Software SPI modules *
*************************************************************************
}
Module MAX7219
Include "convert.bas"
Include "string.bas"
// Number of cascaded display modules
#if IsOption(MAX7219_DISP_COUNT) And Not (MAX7219_DISP_COUNT > 0)
#error MAX7219_DISP_COUNT, "Invalid option, must be > 0"
#endif
#option MAX7219_DISP_COUNT = 1
Const MAX7219_DISPLAY_COUNT = MAX7219_DISP_COUNT
// hardware or software SPI...
#if IsOption(MAX7219_SPI_SOFTWARE) And Not (MAX7219_SPI_SOFTWARE in (true, false))
#error MAX7219_SPI_SOFTWARE, "Invalid option, must be TRUE or FALSE."
#endif
#option MAX7219_SPI_SOFTWARE = false
#if MAX7219_SPI_SOFTWARE = true // use software SPI...
Include "sspi.bas"
#else // use hardware SPI...
Include "SPI.BAS"
#EndIf
#Option MAX7219_CS = PORTC.1
// validate SCK pin...
#If IsOption(MAX7219_CS) And Not IsValidPortPin(MAX7219_CS)
#Error MAX7219_CS, "Invalid option. MCP_CS must be a valid port pin."
#EndIf
Public Dim
CS As MAX7219_CS.MAX7219_CS@ // Chip select
' To be used with WriteDigit(...) subroutine
' for digits (0..9) just send the digit itself
' for non-digits, use codes below as pValue param in WriteDigit(...)
Public Const
SYMB_DASH As Byte = $A, ' displays "-" symbol
SYMB_E As Byte = $B, ' displays "E" symbol
SYMB_H As Byte = $C, ' displays "H" symbol
SYMB_L As Byte = $D, ' displays "L" symbol
SYMB_P As Byte = $E, ' displays "P" symbol
SYMB_BLANK As Byte = $F ' blanks the digit
' Internal registers of the MAX7219
Private Const
REG_NO_OP As Byte = $00,
REG_DIGIT(8) As Byte = ($01, $02, $03, $04, $05, $06, $07, $08),
REG_DECODE_MODE As Byte = $09,
REG_INTENSITY As Byte = $0A,
REG_SCAN_LIMIT As Byte = $0B,
REG_SHUTDOWN As Byte = $0C,
REG_DISP_TEST As Byte = $0F
Private Dim fSelectedDisp As Byte
{
Changed lines 284-298 from:
* Name : SetDecodeMode *
* Purpose :Sets de Max7219 decode mode for each digit *
* param : pDecodeMask = a 8 bit value. Setting bit to 0/1 *
* disables/enables the B-Decoding for concerned digit *
*
When the code B decode mode is used, the decoder *
looks only at the lower nibble of the data in the digit *
registers (D3–D0), disregarding bits D4–D6. D7, which *
sets the decimal point (SEG DP), is independent of the *
decoder and is positive logic (D7 = 1 turns the decimal *
point on). *
When no-decode is selected, data bits D7–D0 correspond *
to the segment lines of the MAX7219/MAX7221. *
Table 6 shows the one-to-one pairing of each data bit *
to the appropriate segment line. *
* Purpose :
* param
*
When the code B decode mode is used, the decoder *
looks only at the lower nibble of the data in the digit *
registers (D3–D0), disregarding bits D4–D6. D7, which *
sets the decimal point (SEG DP), is independent of the *
decoder and is positive logic (D7 = 1 turns the decimal *
point on). *
When no-decode is selected, data bits D7–D0 correspond *
to the segment lines of the MAX7219/MAX7221. *
Table 6 shows the one-to-one pairing of each data bit *
to the appropriate segment line.
to:
* Name : SelectDisplay *
* Purpose : Selects active display *
* param : pDisplayIndex = display index. *
* - First display module = 0 *
* - pDisplayIndex must be < MAX7219_DISP_COUNT *
* Purpose : Selects active display *
* param : pDisplayIndex = display index. *
* - First display module = 0 *
* - pDisplayIndex must be < MAX7219_DISP_COUNT *
Changed lines 291-292 from:
Public Inline Sub SetDecodeMode(pDecodeMask As Byte)
WriteReg(REG_DECODE_MODE, pDecodeMask)
to:
Public Sub SelectDisplay(pDisplayIndex As Byte)
If pDisplayIndex >= MAX7219_DISPLAY_COUNT Then
pDisplayIndex = MAX7219_DISPLAY_COUNT
EndIf
fSelectedDisp = pDisplayIndex
If pDisplayIndex >= MAX7219_DISPLAY_COUNT Then
pDisplayIndex = MAX7219_DISPLAY_COUNT
EndIf
fSelectedDisp = pDisplayIndex
Changed lines 300-301 from:
* Name : DisplayOn *
* Purpose : Enables the display *
* Purpose : Enables the display
to:
* Name : GetSelectedDisplay() *
* Purpose : returns actually selected Max7219 module *
* Purpose : returns actually selected Max7219 module *
Changed lines 304-307 from:
Public Inline Sub DisplayOn()
WriteReg(REG_SHUTDOWN, $1)
End Sub
End Sub
to:
Public Function GetSelectedDisplay() As Byte
result = fSelectedDisp
End Function
' MAX7219 command format is
' [D15][D14][D13][D12] [D11 - D8] [D7 - D0]
' [ x ][ x ][ x ][ x ] [ REG_ADDR] [msb DATA lsb]
result = fSelectedDisp
End Function
' MAX7219 command format is
' [D15][D14][D13][D12] [D11 - D8] [D7 - D0]
' [ x ][ x ][ x ][ x ] [ REG_ADDR] [msb DATA lsb]
Changed lines 314-315 from:
* Name : DisplayOff *
* Purpose :Shuts down the display *
* Purpose :
to:
* Name : WriteReg *
* Purpose : Writes pData byte to register address given by pRegAddress *
* Purpose : Writes pData byte to register address given by pRegAddress *
Changed lines 318-319 from:
Public Inline Sub DisplayOff()
WriteReg(REG_SHUTDOWN, $0)
WriteReg(REG_SHUTDOWN, $0
to:
Public Sub WriteReg(pRegAddress As Byte, pData As Byte)
Dim i, count As Byte
CS = 0 ' must be set here mainly because of Max7221
count = MAX7219_DISPLAY_COUNT-fSelectedDisp-1
For i = 1 To count
WriteByte(REG_NO_OP)
WriteByte($00)
Next
WriteByte(pRegAddress)
WriteByte(pData)
count = fSelectedDisp
For i = 1 To count
WriteByte(REG_NO_OP)
WriteByte($00)
Next
CS = 1
Dim i, count As Byte
CS = 0 ' must be set here mainly because of Max7221
count = MAX7219_DISPLAY_COUNT-fSelectedDisp-1
For i = 1 To count
WriteByte(REG_NO_OP)
WriteByte($00)
Next
WriteByte(pRegAddress)
WriteByte(pData)
count = fSelectedDisp
For i = 1 To count
WriteByte(REG_NO_OP)
WriteByte($00)
Next
CS = 1
Changed lines 338-353 from:
* Name : SetNumberOfDigits *
* Purpose : Sets the number of digits availble in the display *
* param : pNumberOfDigits = value from 1 to 8 *
* *
* WARNING:::: DANGEOUROUS !!!!! *
* *
* If the scan-limit register is set for three digits or less, *
* individual digit drivers will dissipate excessive amounts *
* of power. Consequently, the value of the RSET resistor *
* must be adjusted according to the number of digits displayed, *
* to limit individual digit driver power dissipation. *
* *
* This function has been added only for debug purpose or *
* - when the Max7219 is used a LED driver (i.e Decode mode disabled) *
* - when the Max7219 is cascaded with another Max7219 that is used to *
* less than 8 digits *
* Purpose : Sets the number of digits availble in the display
* param
*
*
*
*
*
*
*
*
* This function has been added only for debug purpose or
* - when the Max7219 is used a LED driver (i
* - when the Max7219 is cascaded with another Max7219 that is used to *
* less than 8 digits
to:
* Name : SetDecodeMode *
* Purpose : Sets de Max7219 decode mode for each digit *
* param : pDecodeMask = a 8 bit value. Setting bit to 0/1 *
* disables/enables the B-Decoding for concerned digit *
*
When the code B decode mode is used, the decoder *
looks only at the lower nibble of the data in the digit *
registers (D3–D0), disregarding bits D4–D6. D7, which *
sets the decimal point (SEG DP), is independent of the *
decoder and is positive logic (D7 = 1 turns the decimal *
point on). *
When no-decode is selected, data bits D7–D0 correspond *
to the segment lines of the MAX7219/MAX7221. *
Table 6 shows the one-to-one pairing of each data bit *
to the appropriate segment line. *
* Purpose : Sets de Max7219 decode mode for each digit *
* param : pDecodeMask = a 8 bit value. Setting bit to 0/1 *
* disables/enables the B-Decoding for concerned digit *
*
When the code B decode mode is used, the decoder *
looks only at the lower nibble of the data in the digit *
registers (D3–D0), disregarding bits D4–D6. D7, which *
sets the decimal point (SEG DP), is independent of the *
decoder and is positive logic (D7 = 1 turns the decimal *
point on). *
When no-decode is selected, data bits D7–D0 correspond *
to the segment lines of the MAX7219/MAX7221. *
Table 6 shows the one-to-one pairing of each data bit *
to the appropriate segment line. *
Changed lines 355-361 from:
Public Sub SetNumberOfDigits(pNumberOfDigits As Byte)
If pNumberOfDigits > 8 Then
pNumberOfDigits = 8
ElseIf pNumberOfDigits < 1 Then
pNumberOfDigits = 1
EndIf
WriteReg(REG_SCAN_LIMIT, pNumberOfDigits-1)
pNumberOfDigits = 8
ElseIf pNumberOfDigits < 1 Then
pNumberOfDigits = 1
EndIf
WriteReg(REG_SCAN_LIMIT, pNumberOfDigits-1
to:
Public Inline Sub SetDecodeMode(pDecodeMask As Byte)
WriteReg(REG_DECODE_MODE, pDecodeMask)
WriteReg(REG_DECODE_MODE, pDecodeMask)
Changed lines 361-363 from:
* Name : SetBrightness *
* Purpose : Sets de Max7219 brightness *
* param : pIntensity = a 8 bit value between 0 to 15 (16 steps) *
* Purpose : Sets de Max7219 brightness
* param : pIntensity = a 8 bit value between 0 to 15 (16 steps)
to:
* Name : DisplayOn *
* Purpose : Enables the display *
* Purpose : Enables the display *
Changed lines 365-366 from:
Public Inline Sub SetBrightness(pIntensity As Byte)
WriteReg(REG_INTENSITY, (pIntensity And $F))
to:
Public Inline Sub DisplayOn()
WriteReg(REG_SHUTDOWN, $1)
WriteReg(REG_SHUTDOWN, $1)
Changed lines 371-373 from:
* Name : SetDisplayTestMode *
* Purpose : Enables/Disables de Max7219 test mode *
* param : pDispTestEnabled = True/False to Enable/Disable test mode *
* Purpose : Enables/Disables de Max7219 test mode
* param
to:
* Name : DisplayOff *
* Purpose : Shuts down the display *
* Purpose : Shuts down the display *
Changed lines 375-380 from:
Public Sub SetDisplayTestMode(pDispTestEnabled As Boolean)
If pDispTestEnabled Then
WriteReg(REG_DISP_TEST, 1)
Else
WriteReg(REG_DISP_TEST, 0)
EndIf
WriteReg(REG_DISP_TEST, 1
Else
WriteReg(REG_DISP_TEST, 0)
EndIf
to:
Public Inline Sub DisplayOff()
WriteReg(REG_SHUTDOWN, $0)
WriteReg(REG_SHUTDOWN, $0)
Changed lines 381-400 from:
* Name : WriteDigit *
* Purpose : writes a value to position pDigitPos *
* param : pDigitPos = digit position from 0 to 7 *
* pValue = value to write to at pDigitPos digit position *
* values from 0 to 9 displays corresponding digit *
* $A = displays "-" symbol *
* $B = displays "E" symbol *
* $C = displays "H" symbol *
* $D = displays "L" symbol *
* $E = displays "P" symbol *
* $F = blanks the digit *
Use the constants defined at top of this module *
SYMB_DASH As Byte = $A, ' displays "-" symbol *
SYMB_E As Byte = $B, ' displays "E" symbol *
SYMB_H As Byte = $C, ' displays "H" symbol *
SYMB_L As Byte = $D, ' displays "L" symbol *
SYMB_P As Byte = $E, ' displays "P" symbol *
SYMB_BLANK As Byte = $F ' blanks the digit *
*
* pDecimalPointOn = True/False Switch On/Off decimal point led *
* Purpose : writes a value to position pDigitPos
* param
*
SYMB_L As Byte = $D, ' displays "L" symbol *
SYMB_P As Byte = $E, ' displays "P" symbol *
SYMB_BLANK As Byte = $F ' blanks the digit *
*
* pDecimalPointOn = True/False Switch On/Off decimal point led
to:
* Name : SetNumberOfDigits *
* Purpose : Sets the number of digits availble in the display *
* param : pNumberOfDigits = value from 1 to 8 *
* *
* WARNING:::: DANGEOUROUS !!!!! *
* *
* If the scan-limit register is set for three digits or less, *
* individual digit drivers will dissipate excessive amounts *
* of power. Consequently, the value of the RSET resistor *
* must be adjusted according to the number of digits displayed, *
* to limit individual digit driver power dissipation. *
* *
* This function has been added only for debug purpose or *
* - when the Max7219 is used a LED driver (i.e Decode mode disabled) *
* - when the Max7219 is cascaded with another Max7219 that is used to *
* less than 8 digits *
* Purpose : Sets the number of digits availble in the display *
* param : pNumberOfDigits = value from 1 to 8 *
* *
* WARNING:::: DANGEOUROUS !!!!! *
* *
* If the scan-limit register is set for three digits or less, *
* individual digit drivers will dissipate excessive amounts *
* of power. Consequently, the value of the RSET resistor *
* must be adjusted according to the number of digits displayed, *
* to limit individual digit driver power dissipation. *
* *
* This function has been added only for debug purpose or *
* - when the Max7219 is used a LED driver (i.e Decode mode disabled) *
* - when the Max7219 is cascaded with another Max7219 that is used to *
* less than 8 digits *
Changed lines 399-401 from:
Public Sub WriteDigit(pDigitPos As Byte, pValue As Byte, pDecimalPointOn As Boolean = false)
pValue.Booleans(7) = pDecimalPointOn
WriteReg(REG_DIGIT(pDigitPos), pValue)
to:
Public Sub SetNumberOfDigits(pNumberOfDigits As Byte)
If pNumberOfDigits > 8 Then
pNumberOfDigits = 8
ElseIf pNumberOfDigits < 1 Then
pNumberOfDigits = 1
EndIf
WriteReg(REG_SCAN_LIMIT, pNumberOfDigits-1)
If pNumberOfDigits > 8 Then
pNumberOfDigits = 8
ElseIf pNumberOfDigits < 1 Then
pNumberOfDigits = 1
EndIf
WriteReg(REG_SCAN_LIMIT, pNumberOfDigits-1)
Changed lines 410-413 from:
* Name : BlankDisplay *
* Purpose :Writes blank to each digit of the display *
* Note : this is **NOT** the same as DisplayOff() which puts the disp *
* in shutdown mode *
* Purpose :
* Note
*
to:
* Name : SetBrightness *
* Purpose : Sets de Max7219 brightness *
* param : pIntensity = a 8 bit value between 0 to 15 (16 steps) *
* Purpose : Sets de Max7219 brightness *
* param : pIntensity = a 8 bit value between 0 to 15 (16 steps) *
Changed lines 415-419 from:
Public Sub BlankDisplay()
Dim i As Byte
For i = 0 To 7
WriteDigit(i,$F, false)
Next
For i = 0 To 7
WriteDigit(i,
to:
Public Inline Sub SetBrightness(pIntensity As Byte)
WriteReg(REG_INTENSITY, (pIntensity And $F))
WriteReg(REG_INTENSITY, (pIntensity And $F))
Changed lines 421-425 from:
* Name : WriteValue *
* Purpose : Writes a value to the display. *
* Param : pStr = string containing a formate value to display *
* Blanks and special symbols ("-", "H", "L", "E", "P", " ", "." *
* are handled automatically by this routine *
* Purpose : Writes a value to the display.
* Param : pStr = string containing a formate value to display *
* Blanks and special symbols ("-", "H", "L", "E", "P", " ", "." *
* are handled automatically by this routine
to:
* Name : SetDisplayTestMode *
* Purpose : Enables/Disables de Max7219 test mode *
* param : pDispTestEnabled = True/False to Enable/Disable test mode *
* Purpose : Enables/Disables de Max7219 test mode *
* param : pDispTestEnabled = True/False to Enable/Disable test mode *
Changed lines 426-452 from:
Dim i, value, curDigit As Byte
Dim NextDigitHasDecPoint As Boolean
NextDigitHasDecPoint = false
curDigit = 0 'Length(pStr)-1
For i = Length(pStr)-1 To 0 Step -1
value = pStr(i)
If value = 45 Then ' "-"
value = SYMB_DASH
ElseIf value = 32 Then ' " "
value = SYMB_BLANK
ElseIf value = 72 Then ' "H"
value = SYMB_H
ElseIf value = 76 Then ' "L"
value = SYMB_L
ElseIf value = 69 Then ' "E"
value = SYMB_E
ElseIf value = 80 Then ' "P"
value = SYMB_P
ElseIf value = 46 Then ' "."
NextDigitHasDecPoint = true
Continue
EndIf
WriteDigit(curDigit, value, NextDigitHasDecPoint)
NextDigitHasDecPoint = false
Inc(curDigit)
Next
to:
Public Sub SetDisplayTestMode(pDispTestEnabled As Boolean)
If pDispTestEnabled Then
WriteReg(REG_DISP_TEST, 1)
Else
WriteReg(REG_DISP_TEST, 0)
EndIf
If pDispTestEnabled Then
WriteReg(REG_DISP_TEST, 1)
Else
WriteReg(REG_DISP_TEST, 0)
EndIf
Added line 433:
Changed lines 436-437 from:
* Name : InitChip *
* Purpose :Initialize the MAX7219 CHIP *
* Purpose :
to:
* Name : WriteDigit *
* Purpose : writes a value to position pDigitPos *
* param : pDigitPos = digit position from 0 to 7 *
* pValue = value to write to at pDigitPos digit position *
* values from 0 to 9 displays corresponding digit *
* $A = displays "-" symbol *
* $B = displays "E" symbol *
* $C = displays "H" symbol *
* $D = displays "L" symbol *
* $E = displays "P" symbol *
* $F = blanks the digit *
Use the constants defined at top of this module *
SYMB_DASH As Byte = $A, ' displays "-" symbol *
SYMB_E As Byte = $B, ' displays "E" symbol *
SYMB_H As Byte = $C, ' displays "H" symbol *
SYMB_L As Byte = $D, ' displays "L" symbol *
SYMB_P As Byte = $E, ' displays "P" symbol *
SYMB_BLANK As Byte = $F ' blanks the digit *
*
* pDecimalPointOn = True/False Switch On/Off decimal point led *
* Purpose : writes a value to position pDigitPos *
* param : pDigitPos = digit position from 0 to 7 *
* pValue = value to write to at pDigitPos digit position *
* values from 0 to 9 displays corresponding digit *
* $A = displays "-" symbol *
* $B = displays "E" symbol *
* $C = displays "H" symbol *
* $D = displays "L" symbol *
* $E = displays "P" symbol *
* $F = blanks the digit *
Use the constants defined at top of this module *
SYMB_DASH As Byte = $A, ' displays "-" symbol *
SYMB_E As Byte = $B, ' displays "E" symbol *
SYMB_H As Byte = $C, ' displays "H" symbol *
SYMB_L As Byte = $D, ' displays "L" symbol *
SYMB_P As Byte = $E, ' displays "P" symbol *
SYMB_BLANK As Byte = $F ' blanks the digit *
*
* pDecimalPointOn = True/False Switch On/Off decimal point led *
Changed lines 458-471 from:
Public Sub InitChip()
to:
Public Sub WriteDigit(pDigitPos As Byte, pValue As Byte, pDecimalPointOn As Boolean = false)
pValue.Booleans(7) = pDecimalPointOn
WriteReg(REG_DIGIT(pDigitPos), pValue)
End Sub
{
****************************************************************************
* Name : BlankDisplay *
* Purpose : Writes blank to each digit of the display *
* Note : this is **NOT** the same as DisplayOff() which puts the disp *
* in shutdown mode *
****************************************************************************
}
Public Sub BlankDisplay()
pValue.Booleans(7) = pDecimalPointOn
WriteReg(REG_DIGIT(pDigitPos), pValue)
End Sub
{
****************************************************************************
* Name : BlankDisplay *
* Purpose : Writes blank to each digit of the display *
* Note : this is **NOT** the same as DisplayOff() which puts the disp *
* in shutdown mode *
****************************************************************************
}
Public Sub BlankDisplay()
Changed lines 473-480 from:
For i = 0 To MAX7219_DISPLAY_COUNT-1
SelectDisplay(i)
SetNumberOfDigits(8)
DisplayOn()
SetDecodeMode(%11111111) // enables B-Decoding for all digits
SetBrightness($A) // can be up to 15. intensity 0 means display off
WriteReg(REG_NO_OP, $FF)
BlankDisplay()
DisplayOn()
SetDecodeMode(%11111111) // enables B-Decoding for all digits
SetBrightness($A) // can be up to 15. intensity 0 means display off
WriteReg(REG_NO_OP, $FF)
BlankDisplay(
to:
For i = 0 To 7
WriteDigit(i, $F, false)
WriteDigit(i, $F, false)
Deleted line 475:
Changed lines 480-481 from:
* Name : Initialize *
* Purpose :Initializes module and included modules *
* Purpose :
to:
* Name : WriteValue *
* Purpose : Writes a value to the display. *
* Param : pStr = string containing a formate value to display *
* Blanks and special symbols ("-", "H", "L", "E", "P", " ", "." *
* are handled automatically by this routine *
* Purpose : Writes a value to the display. *
* Param : pStr = string containing a formate value to display *
* Blanks and special symbols ("-", "H", "L", "E", "P", " ", "." *
* are handled automatically by this routine *
Changed lines 487-500 from:
Public Sub Initialize()
#If MAX7219_SPI_SOFTWARE
SSPI.Initialize
SSPI.SetClock(spiIdleHigh)
#Else
SPI.SetAsMaster(spiOscDiv16)
SPI.SetClock(spiIdleHigh, spiRisingEdge)
SPI.SetSample(spiSampleMiddle)
EnableSPI()
#EndIf
Output(CS)
High(CS)
InitChip()
#If MAX7219_SPI_SOFTWARE
SSPI.SetClock(spiIdleHigh)
#Else
to:
Public Sub WriteValue(pStr As String)
Dim i, value, curDigit As Byte
Dim NextDigitHasDecPoint As Boolean
NextDigitHasDecPoint = false
curDigit = 0 'Length(pStr)-1
For i = Length(pStr)-1 To 0 Step -1
value = pStr(i)
If value = 45 Then ' "-"
value = SYMB_DASH
ElseIf value = 32 Then ' " "
value = SYMB_BLANK
ElseIf value = 72 Then ' "H"
value = SYMB_H
ElseIf value = 76 Then ' "L"
value = SYMB_L
ElseIf value = 69 Then ' "E"
value = SYMB_E
ElseIf value = 80 Then ' "P"
value = SYMB_P
ElseIf value = 46 Then ' "."
NextDigitHasDecPoint = true
Continue
EndIf
WriteDigit(curDigit, value, NextDigitHasDecPoint)
NextDigitHasDecPoint = false
Inc(curDigit)
Next
Dim i, value, curDigit As Byte
Dim NextDigitHasDecPoint As Boolean
NextDigitHasDecPoint = false
curDigit = 0 'Length(pStr)-1
For i = Length(pStr)-1 To 0 Step -1
value = pStr(i)
If value = 45 Then ' "-"
value = SYMB_DASH
ElseIf value = 32 Then ' " "
value = SYMB_BLANK
ElseIf value = 72 Then ' "H"
value = SYMB_H
ElseIf value = 76 Then ' "L"
value = SYMB_L
ElseIf value = 69 Then ' "E"
value = SYMB_E
ElseIf value = 80 Then ' "P"
value = SYMB_P
ElseIf value = 46 Then ' "."
NextDigitHasDecPoint = true
Continue
EndIf
WriteDigit(curDigit, value, NextDigitHasDecPoint)
NextDigitHasDecPoint = false
Inc(curDigit)
Next
Deleted lines 514-521:
Initialize()
=]
!!!Example Code
This program uses 2 MAX7219 modules, each handling 8 7Seg display module.
=code [=
Changed lines 516-551 from:
*************************************************************************
* Name : MAX7219.BAS *
* Author : Ahmed Lazreg ([email protected]) *
* http://www.pocketmt.com *
* http://www.microcodeproject.com *
* Notice : Copyright (c) 20015 Pocket MicroTechnics *
* : All Rights Reserved *
* Date : 01/01/2015 *
* Version : 1.0 *
* Desc. : Test program for MAX7219 module *
* *
*************************************************************************
}
Program Max7219_test
Device = 18F452
Clock = 20
Include "utils.bas"
Include "convert.bas"
//#option MAX7219_SPI_SOFTWARE = true
#option MAX7219_DISP_COUNT = 2
Include "Max7219.bas"
Dim RED_LED As PORTB.1
Dim i, j As Word
Dim k As Float
Sub Init_MCU()
PORTA = %00000000
TRISA = %11111100
PORTB = %00000000
TRISB = $00
SetAllDigital()
*
*
*
*************************************************************************
}
Program Max7219_test
Device = 18F452
Clock = 20
Include "utils.bas"
Include "convert
//#option MAX7219_SPI_SOFTWARE = true
#option MAX7219_DISP_COUNT = 2
Include "Max7219.bas"
Dim RED_LED
Dim i, j As Word
Sub Init_MCU
PORTB = %00000000
TRISB = $00
SetAllDigital
to:
****************************************************************************
* Name : InitChip *
* Purpose : Initialize the MAX7219 CHIP *
****************************************************************************
}
Public Sub InitChip()
Dim i As Byte
For i = 0 To MAX7219_DISPLAY_COUNT-1
SelectDisplay(i)
SetNumberOfDigits(8)
DisplayOn()
SetDecodeMode(%11111111) // enables B-Decoding for all digits
SetBrightness($A) // can be up to 15. intensity 0 means display off
WriteReg(REG_NO_OP, $FF)
BlankDisplay()
Next
SelectDisplay(0)
* Name : InitChip *
* Purpose : Initialize the MAX7219 CHIP *
****************************************************************************
}
Public Sub InitChip()
Dim i As Byte
For i = 0 To MAX7219_DISPLAY_COUNT-1
SelectDisplay(i)
SetNumberOfDigits(8)
DisplayOn()
SetDecodeMode(%11111111) // enables B-Decoding for all digits
SetBrightness($A) // can be up to 15. intensity 0 means display off
WriteReg(REG_NO_OP, $FF)
BlankDisplay()
Next
SelectDisplay(0)
Changed lines 535-580 from:
Init_MCU()
High(RED_LED)
// main program loop
SelectDisplay(0)
SetDisplayTestMode(true)
DelayMS(300)
SetDisplayTestMode(false)
SelectDisplay(0)
WriteDigit(6, SYMB_E)
WriteDigit(7, SYMB_P)
DelayMS(1000)
SelectDisplay(0)
BlankDisplay()
WriteValue("HELP-. ")
SelectDisplay(1)
WriteValue("-41.73")
DelayMS(1000)
SelectDisplay(0)
BlankDisplay()
WriteValue("HELP ")
SelectDisplay(1)
BlankDisplay()
WriteDigit(7, SYMB_L)
i = 0
j = 0
k = 0.0
While (true)
Toggle(RED_LED)
DelayMS(800)
SelectDisplay(0)
WriteValue(DecToStr(i))
SelectDisplay(1)
WriteValue(FloatToStr(k))
i = i +1
k = k + 0.2
End While
End Program
to:
{
****************************************************************************
* Name : Initialize *
* Purpose : Initializes module and included modules *
****************************************************************************
}
Public Sub Initialize()
#If MAX7219_SPI_SOFTWARE
SSPI.Initialize
SSPI.SetClock(spiIdleHigh)
#Else
SPI.SetAsMaster(spiOscDiv16)
SPI.SetClock(spiIdleHigh, spiRisingEdge)
SPI.SetSample(spiSampleMiddle)
EnableSPI()
#EndIf
Output(CS)
High(CS)
InitChip()
End Sub
Initialize()
****************************************************************************
* Name : Initialize *
* Purpose : Initializes module and included modules *
****************************************************************************
}
Public Sub Initialize()
#If MAX7219_SPI_SOFTWARE
SSPI.Initialize
SSPI.SetClock(spiIdleHigh)
#Else
SPI.SetAsMaster(spiOscDiv16)
SPI.SetClock(spiIdleHigh, spiRisingEdge)
SPI.SetSample(spiSampleMiddle)
EnableSPI()
#EndIf
Output(CS)
High(CS)
InitChip()
End Sub
Initialize()
Added line 559:
Changed lines 33-34 from:
!!Single MCP23S17 chip module
to:
!!Single MAX7219 chip module connection
Changed lines 37-38 from:
http://www.pocketmt.com/images/mcp23s17.jpg
to:
http://www.pocketmt.com/images/max7219.png
Changed line 726 from:
=]
to:
=]
Added lines 1-726:
The MAX7219/MAX7221 are compact, serial input/output common-cathode display drivers that interface microprocessors (µPs) to 7-segment numeric LED displays of up to 8 digits, bar-graph displays, or 64 individual LEDs. Included on-chip are a BCD code-B decoder, multiplex scan circuitry, segment and digit drivers, and an 8x8 static RAM that stores each digit. Only one external resistor is required to set the segment current for all LEDs. The MAX7221 is compatible with SPI™, QSPI™, and MICROWIRE™, and has slew-rate-limited segment drivers to reduce EMI.
A convenient 4-wire serial interface connects to all common µPs. Individual digits may be addressed and updated without rewriting the entire display. The MAX7219/MAX7221 also allow the user to select code-B decoding or no-decode for each digit.
The devices include a 150µA low-power shutdown mode, analog and digital brightness control, a scan-limit register that allows the user to display from 1 to 8 digits, and a test mode that forces all LEDs on.
'''Main Features:'''
1- Handle one or multiple cascaded MAX72xx modules
2- Use Hardware or Software SPI to manage the MAX72xx module(s). Software SPI is usefull for little PICs that does not have SPI hardware module (like the little 18 pins 18F1320 mcu).
'''For any comment, or feedback (or bug report), please post to Swordfish Forum'''.
!!!VERY IMPORTANT NOTICE concerning Swordfish SPI module:
PS. I never got this module to work with official Swordfish hatdware SPI driver. I used instead a modified version of (hardware) SPI driver using some comments published by Steven on the forum (and sent to me by mail - Great thank Steven).
'''The modified version of the SPI module is also published at the END of this article.'''
!!!IMPORTANT Options
#option MAX7219_DISP_COUNT = nnValue // where nnValue is the number of your cascaded modules. if not specified, defaults to 1 module
#option MAX7219_SPI_SOFTWARE = true // use Software SPI
#option MCPSPI_SOFTWARE = false // Use Hardware SPI (default to false)
#Option MCP_CS = PORTC.1 // Chip Select Pin
!!Single MCP23S17 chip module
connection to hardware SPI is shown in following diagram (for software SPI you can use Swordfish Options to modify pins affectation).
http://www.pocketmt.com/images/mcp23s17.jpg
!!!Module Code
=code [=
{
*************************************************************************
* Name : MAX7219.BAS *
* Author : Ahmed Lazreg ([email protected]) *
* http://www.pocketmt.com *
* http://www.microcodeproject.com *
* Notice : Copyright (c) 20015 Pocket MicroTechnics *
* : All Rights Reserved *
* Date : 01/01/2015 *
* Version : 1.0 *
* Modified: *
* Notes : This module handles Maxime Integrated(TM) MAX7219/MAX7221 *
* Serially Interfaced, 8-Digit LED Display Drivers *
* It can be used via Hardware or Software SPI modules *
*************************************************************************
}
Module MAX7219
Include "convert.bas"
Include "string.bas"
// Number of cascaded display modules
#if IsOption(MAX7219_DISP_COUNT) And Not (MAX7219_DISP_COUNT > 0)
#error MAX7219_DISP_COUNT, "Invalid option, must be > 0"
#endif
#option MAX7219_DISP_COUNT = 1
Const MAX7219_DISPLAY_COUNT = MAX7219_DISP_COUNT
// hardware or software SPI...
#if IsOption(MAX7219_SPI_SOFTWARE) And Not (MAX7219_SPI_SOFTWARE in (true, false))
#error MAX7219_SPI_SOFTWARE, "Invalid option, must be TRUE or FALSE."
#endif
#option MAX7219_SPI_SOFTWARE = false
#if MAX7219_SPI_SOFTWARE = true // use software SPI...
Include "sspi.bas"
#else // use hardware SPI...
Include "SPI.BAS"
#EndIf
#Option MAX7219_CS = PORTC.1
// validate SCK pin...
#If IsOption(MAX7219_CS) And Not IsValidPortPin(MAX7219_CS)
#Error MAX7219_CS, "Invalid option. MCP_CS must be a valid port pin."
#EndIf
Public Dim
CS As MAX7219_CS.MAX7219_CS@ // Chip select
' To be used with WriteDigit(...) subroutine
' for digits (0..9) just send the digit itself
' for non-digits, use codes below as pValue param in WriteDigit(...)
Public Const
SYMB_DASH As Byte = $A, ' displays "-" symbol
SYMB_E As Byte = $B, ' displays "E" symbol
SYMB_H As Byte = $C, ' displays "H" symbol
SYMB_L As Byte = $D, ' displays "L" symbol
SYMB_P As Byte = $E, ' displays "P" symbol
SYMB_BLANK As Byte = $F ' blanks the digit
' Internal registers of the MAX7219
Private Const
REG_NO_OP As Byte = $00,
REG_DIGIT(8) As Byte = ($01, $02, $03, $04, $05, $06, $07, $08),
REG_DECODE_MODE As Byte = $09,
REG_INTENSITY As Byte = $0A,
REG_SCAN_LIMIT As Byte = $0B,
REG_SHUTDOWN As Byte = $0C,
REG_DISP_TEST As Byte = $0F
Private Dim fSelectedDisp As Byte
{
****************************************************************************
* Name : SelectDisplay *
* Purpose : Selects active display *
* param : pDisplayIndex = display index. *
* - First display module = 0 *
* - pDisplayIndex must be < MAX7219_DISP_COUNT *
****************************************************************************
}
Public Sub SelectDisplay(pDisplayIndex As Byte)
If pDisplayIndex >= MAX7219_DISPLAY_COUNT Then
pDisplayIndex = MAX7219_DISPLAY_COUNT
EndIf
fSelectedDisp = pDisplayIndex
End Sub
{
****************************************************************************
* Name : GetSelectedDisplay() *
* Purpose : returns actually selected Max7219 module *
****************************************************************************
}
Public Function GetSelectedDisplay() As Byte
result = fSelectedDisp
End Function
' MAX7219 command format is
' [D15][D14][D13][D12] [D11 - D8] [D7 - D0]
' [ x ][ x ][ x ][ x ] [ REG_ADDR] [msb DATA lsb]
{
****************************************************************************
* Name : WriteReg *
* Purpose : Writes pData byte to register address given by pRegAddress *
****************************************************************************
}
Public Sub WriteReg(pRegAddress As Byte, pData As Byte)
Dim i, count As Byte
CS = 0 ' must be set here mainly because of Max7221
count = MAX7219_DISPLAY_COUNT-fSelectedDisp-1
For i = 1 To count
WriteByte(REG_NO_OP)
WriteByte($00)
Next
WriteByte(pRegAddress)
WriteByte(pData)
count = fSelectedDisp
For i = 1 To count
WriteByte(REG_NO_OP)
WriteByte($00)
Next
CS = 1
End Sub
{
****************************************************************************
* Name : SetDecodeMode *
* Purpose : Sets de Max7219 decode mode for each digit *
* param : pDecodeMask = a 8 bit value. Setting bit to 0/1 *
* disables/enables the B-Decoding for concerned digit *
*
When the code B decode mode is used, the decoder *
looks only at the lower nibble of the data in the digit *
registers (D3–D0), disregarding bits D4–D6. D7, which *
sets the decimal point (SEG DP), is independent of the *
decoder and is positive logic (D7 = 1 turns the decimal *
point on). *
When no-decode is selected, data bits D7–D0 correspond *
to the segment lines of the MAX7219/MAX7221. *
Table 6 shows the one-to-one pairing of each data bit *
to the appropriate segment line. *
****************************************************************************
}
Public Inline Sub SetDecodeMode(pDecodeMask As Byte)
WriteReg(REG_DECODE_MODE, pDecodeMask)
End Sub
{
****************************************************************************
* Name : DisplayOn *
* Purpose : Enables the display *
****************************************************************************
}
Public Inline Sub DisplayOn()
WriteReg(REG_SHUTDOWN, $1)
End Sub
{
****************************************************************************
* Name : DisplayOff *
* Purpose : Shuts down the display *
****************************************************************************
}
Public Inline Sub DisplayOff()
WriteReg(REG_SHUTDOWN, $0)
End Sub
{
****************************************************************************
* Name : SetNumberOfDigits *
* Purpose : Sets the number of digits availble in the display *
* param : pNumberOfDigits = value from 1 to 8 *
* *
* WARNING:::: DANGEOUROUS !!!!! *
* *
* If the scan-limit register is set for three digits or less, *
* individual digit drivers will dissipate excessive amounts *
* of power. Consequently, the value of the RSET resistor *
* must be adjusted according to the number of digits displayed, *
* to limit individual digit driver power dissipation. *
* *
* This function has been added only for debug purpose or *
* - when the Max7219 is used a LED driver (i.e Decode mode disabled) *
* - when the Max7219 is cascaded with another Max7219 that is used to *
* less than 8 digits *
****************************************************************************
}
Public Sub SetNumberOfDigits(pNumberOfDigits As Byte)
If pNumberOfDigits > 8 Then
pNumberOfDigits = 8
ElseIf pNumberOfDigits < 1 Then
pNumberOfDigits = 1
EndIf
WriteReg(REG_SCAN_LIMIT, pNumberOfDigits-1)
End Sub
{
****************************************************************************
* Name : SetBrightness *
* Purpose : Sets de Max7219 brightness *
* param : pIntensity = a 8 bit value between 0 to 15 (16 steps) *
****************************************************************************
}
Public Inline Sub SetBrightness(pIntensity As Byte)
WriteReg(REG_INTENSITY, (pIntensity And $F))
End Sub
{
****************************************************************************
* Name : SetDisplayTestMode *
* Purpose : Enables/Disables de Max7219 test mode *
* param : pDispTestEnabled = True/False to Enable/Disable test mode *
****************************************************************************
}
Public Sub SetDisplayTestMode(pDispTestEnabled As Boolean)
If pDispTestEnabled Then
WriteReg(REG_DISP_TEST, 1)
Else
WriteReg(REG_DISP_TEST, 0)
EndIf
End Sub
{
****************************************************************************
* Name : WriteDigit *
* Purpose : writes a value to position pDigitPos *
* param : pDigitPos = digit position from 0 to 7 *
* pValue = value to write to at pDigitPos digit position *
* values from 0 to 9 displays corresponding digit *
* $A = displays "-" symbol *
* $B = displays "E" symbol *
* $C = displays "H" symbol *
* $D = displays "L" symbol *
* $E = displays "P" symbol *
* $F = blanks the digit *
Use the constants defined at top of this module *
SYMB_DASH As Byte = $A, ' displays "-" symbol *
SYMB_E As Byte = $B, ' displays "E" symbol *
SYMB_H As Byte = $C, ' displays "H" symbol *
SYMB_L As Byte = $D, ' displays "L" symbol *
SYMB_P As Byte = $E, ' displays "P" symbol *
SYMB_BLANK As Byte = $F ' blanks the digit *
*
* pDecimalPointOn = True/False Switch On/Off decimal point led *
****************************************************************************
}
Public Sub WriteDigit(pDigitPos As Byte, pValue As Byte, pDecimalPointOn As Boolean = false)
pValue.Booleans(7) = pDecimalPointOn
WriteReg(REG_DIGIT(pDigitPos), pValue)
End Sub
{
****************************************************************************
* Name : BlankDisplay *
* Purpose : Writes blank to each digit of the display *
* Note : this is **NOT** the same as DisplayOff() which puts the disp *
* in shutdown mode *
****************************************************************************
}
Public Sub BlankDisplay()
Dim i As Byte
For i = 0 To 7
WriteDigit(i, $F, false)
Next
End Sub
{
****************************************************************************
* Name : WriteValue *
* Purpose : Writes a value to the display. *
* Param : pStr = string containing a formate value to display *
* Blanks and special symbols ("-", "H", "L", "E", "P", " ", "." *
* are handled automatically by this routine *
****************************************************************************
}
Public Sub WriteValue(pStr As String)
Dim i, value, curDigit As Byte
Dim NextDigitHasDecPoint As Boolean
NextDigitHasDecPoint = false
curDigit = 0 'Length(pStr)-1
For i = Length(pStr)-1 To 0 Step -1
value = pStr(i)
If value = 45 Then ' "-"
value = SYMB_DASH
ElseIf value = 32 Then ' " "
value = SYMB_BLANK
ElseIf value = 72 Then ' "H"
value = SYMB_H
ElseIf value = 76 Then ' "L"
value = SYMB_L
ElseIf value = 69 Then ' "E"
value = SYMB_E
ElseIf value = 80 Then ' "P"
value = SYMB_P
ElseIf value = 46 Then ' "."
NextDigitHasDecPoint = true
Continue
EndIf
WriteDigit(curDigit, value, NextDigitHasDecPoint)
NextDigitHasDecPoint = false
Inc(curDigit)
Next
End Sub
{
****************************************************************************
* Name : InitChip *
* Purpose : Initialize the MAX7219 CHIP *
****************************************************************************
}
Public Sub InitChip()
Dim i As Byte
For i = 0 To MAX7219_DISPLAY_COUNT-1
SelectDisplay(i)
SetNumberOfDigits(8)
DisplayOn()
SetDecodeMode(%11111111) // enables B-Decoding for all digits
SetBrightness($A) // can be up to 15. intensity 0 means display off
WriteReg(REG_NO_OP, $FF)
BlankDisplay()
Next
SelectDisplay(0)
End Sub
{
****************************************************************************
* Name : Initialize *
* Purpose : Initializes module and included modules *
****************************************************************************
}
Public Sub Initialize()
#If MAX7219_SPI_SOFTWARE
SSPI.Initialize
SSPI.SetClock(spiIdleHigh)
#Else
SPI.SetAsMaster(spiOscDiv16)
SPI.SetClock(spiIdleHigh, spiRisingEdge)
SPI.SetSample(spiSampleMiddle)
EnableSPI()
#EndIf
Output(CS)
High(CS)
InitChip()
End Sub
Initialize()
=]
!!!Example Code
This program uses 2 MAX7219 modules, each handling 8 7Seg display module.
=code [=
{
*************************************************************************
* Name : MAX7219.BAS *
* Author : Ahmed Lazreg ([email protected]) *
* http://www.pocketmt.com *
* http://www.microcodeproject.com *
* Notice : Copyright (c) 20015 Pocket MicroTechnics *
* : All Rights Reserved *
* Date : 01/01/2015 *
* Version : 1.0 *
* Desc. : Test program for MAX7219 module *
* *
*************************************************************************
}
Program Max7219_test
Device = 18F452
Clock = 20
Include "utils.bas"
Include "convert.bas"
//#option MAX7219_SPI_SOFTWARE = true
#option MAX7219_DISP_COUNT = 2
Include "Max7219.bas"
Dim RED_LED As PORTB.1
Dim i, j As Word
Dim k As Float
Sub Init_MCU()
PORTA = %00000000
TRISA = %11111100
PORTB = %00000000
TRISB = $00
SetAllDigital()
End Sub
Init_MCU()
High(RED_LED)
// main program loop
SelectDisplay(0)
SetDisplayTestMode(true)
DelayMS(300)
SetDisplayTestMode(false)
SelectDisplay(0)
WriteDigit(6, SYMB_E)
WriteDigit(7, SYMB_P)
DelayMS(1000)
SelectDisplay(0)
BlankDisplay()
WriteValue("HELP-. ")
SelectDisplay(1)
WriteValue("-41.73")
DelayMS(1000)
SelectDisplay(0)
BlankDisplay()
WriteValue("HELP ")
SelectDisplay(1)
BlankDisplay()
WriteDigit(7, SYMB_L)
i = 0
j = 0
k = 0.0
While (true)
Toggle(RED_LED)
DelayMS(800)
SelectDisplay(0)
WriteValue(DecToStr(i))
SelectDisplay(1)
WriteValue(FloatToStr(k))
i = i +1
k = k + 0.2
End While
End Program
=]
!!Modified Hardware SPI module
=code [=
{
****************************************************************************
* Name : SPI.BAS *
* Author : John Barrat *
* : David John Barker *
* Notice : Copyright (c) 2006 Mecanique *
* : All Rights Reserved *
* Date : 26/05/2006 *
* Version : 1.1 Changed WriteByte() param to WREG for silicon workaround *
* : 1.0 Release *
* : ============================================================= *
* Notes : This post was made on the Swordfish forum by Steve B on *
* : April 8th 2007... *
* : I was having some trouble with the SPI module as well. I am *
* : using an 18F2620, Silicon A4, and was getting some *
* : inconsistent reads/writes, especially when doing a lot of *
* : TX/RX one after another. After looking at the errata, I *
* : changed the ReadByte and WriteByte routines as follows... *
* : *
* : Public Function ReadByte() As SSPBuffer *
* : SSPIF = 0 *
* : SSPBuffer = 0 *
* : Repeat *
* : ClrWDT *
* : Until SSPIF = 1 *
* : End Function *
* : *
* : Public Sub WriteByte(pData As WREG) *
* : SSPIF = 0 *
* : SSPBuffer = pData *
* : Repeat *
* : ClrWDT *
* : Until SSPIF = 1 *
* : End Sub *
* : *
* : Now they use the SSP Interrupt flag instead of the Buffer *
* : Full flag (SSPSTAT.0). I also added a subroutine to enable *
* : the SPI module *
* : *
* : Public Sub EnableSPI() *
* : Dim pDummy As Byte *
* : Enabled = true *
* : pDummy = SSPBuffer *
* : SSPIF = 0 *
* : End Sub *
****************************************************************************
}
Module SPI
Include "system.bas"
// map registers to SSP(x)
#if _mssp = 0
#error _device + " does not support MSSP"
// single SSP...
#elseif _mssp = 1
Dim
SSPControl1 As SSPCON1,
SSPStatus As SSPSTAT,
SSPBuffer As SSPBUF,
SCK As PORTC.3,
SDI As PORTC.4,
SDO As PORTC.5,
_SS As PORTA.5
// has more than one SSP module...
#else
Dim // -> MSSP2
SSPControl1 As SSP1CON1, // as SSP2CON1
SSPStatus As SSP1STAT, // as SSP2STAT
SSPBuffer As SSP1BUF, // as SSP2BUF
SCK As PORTC.3,
SDI As PORTC.4,
SDO As PORTC.5,
_SS As PORTA.5
#endif
// SSPSTAT bitnames
Public Dim
BF As SSPStatus.0, // buffer full (receive and transmit)
SMP As SSPStatus.7, // read sample mode
CKE As SSPStatus.6 // clock edge control
// SSPCON1 bitnames, master mode only...
Public Dim
WCOL As SSPControl1.7, // write collision Detect
SSPOV As SSPControl1.6, // receive overflow
SSPEN As SSPControl1.5, // synchronous receive enable
CKP As SSPControl1.4, // clock polarity
// synchronous mode select bits, %00XX for master mode
SSPM3 As SSPControl1.3, // always zero
SSPM2 As SSPControl1.2, // slave Mode
SSPM1 As SSPControl1.1, // clock Mode (MSB)
SSPM0 As SSPControl1.0 // clock Mode (LSB)
// interrupt flag
Public Dim
SSPIF As PIR1.3
Public Const
spiOscDiv4 = 0, // master mode FOSC/4
spiOscDiv16 = 1, // master mode FOSC/16
spiOscDiv64 = 2, // master mode FOSC/64
spiOscTimer2 = 3, // master mode TMR2 provides clock
spiSlaveSSEnabled = 4, // slave mode slave synch enabled
spiSlaveSSDisabled = 5, // slave mode slave synch disabled
// clock idle and edge settings (SPI Mode compatible)
spiRisingEdge = $40, // data transmitted on rising edge of clock
spiFallingEdge = $00, // data transmitted on falling edge of clock
spiIdleHigh = $10, // idle state for clock is high
spiIdleLow = $00, // idle state for clock is low
// RX data sampling settings (SSPStatus.6 - SMP)
spiSampleEnd = $80, // input data sampled at end of data output time
spiSampleMiddle = $00 // input data sampled at middle of data output time
// local helper aliases...
Dim
FBufferIsFull As SSPStatus.Booleans(0) // BF as boolean
// public aliases...
Public Dim
Enabled As SSPControl1.Booleans(5), // SSPEN as boolean
Overflow As SSPControl1.Booleans(6), // SSPOV as boolean
WriteCollision As SSPControl1.Booleans(7) // WCOL as boolean
{
****************************************************************************
* Name : SetAsMaster *
* Purpose : Set SPI to master mode *
* : spiOscDiv4 (DEFAULT), spiOscDiv16, spiOscDiv64, spiOscTmr2 *
****************************************************************************
}
Public Sub SetAsMaster(pMode As Byte = spiOscDiv4)
SSPControl1 = SSPControl1 And $F0
SSPControl1 = SSPControl1 Or pMode
Output(SDO)
Output(SCK)
End Sub
{
****************************************************************************
* Name : SetAsSlave *
* Purpose : Set SPI to slave mode *
* : spiSlaveSSEnabled, spiSlaveSSDisabled (DEFAULT) *
****************************************************************************
}
Public Sub SetAsSlave(pMode As Byte = spiSlaveSSDisabled)
SSPControl1 = SSPControl1 And $F0
SSPControl1 = SSPControl1 Or pMode
Output(SDO)
Input(SCK)
Input(_SS)
End Sub
{
****************************************************************************
* Name : SetSample *
* Purpose : Sets when the SPI input data in sampled *
* : spiSampleEnd, spiSampleMiddle. For slave mode, sample should *
* : always be spiSampleMiddle *
****************************************************************************
}
Public Sub SetSample(pSample As Byte)
SSPStatus = SSPStatus And $7F
SSPStatus = SSPStatus Or pSample
End Sub
{
****************************************************************************
* Name : SetClock *
* Purpose : Set SPI idle state and data transmission clock edge *
* : pIdle -> spiIdleHigh, spiIdleLow *
* : pEdge -> spiRisingEdge, spiFallingEdge *
****************************************************************************
}
Public Sub SetClock(pIdle As Byte, pEdge As Byte)
SSPControl1 = SSPControl1 And $EF
SSPControl1 = SSPControl1 Or pIdle
If pIdle = spiIdleHigh Then
pEdge = Not pEdge And $BF
EndIf
SSPStatus = SSPStatus And $BF
SSPStatus = SSPStatus Or pEdge
End Sub
{
****************************************************************************
* Name : ReadByte *
* Purpose : Read a single byte from the SPI bus *
****************************************************************************
}
'Public Function ReadByte() As SSPBuffer
' SSPBuffer = 0
' Repeat
' ClrWDT
' Until FBufferIsFull
'End Function
Public Function ReadByte() As SSPBuffer
SSPIF = 0
SSPBuffer = $FF
Repeat
ClrWDT
Until SSPIF = 1
ReadByte = SSPBuffer
End Function
Public Sub WriteByte(pData As Byte)
SSPIF = 0
SSPBuffer = pData
Repeat
ClrWDT
Until SSPIF = 1
End Sub
{
****************************************************************************
* Name : WriteByte *
* Purpose : Write a single byte to the SPI bus *
****************************************************************************
}
'Public Sub WriteByte(pData As WREG)
' SSPBuffer = pData
' Repeat
' ClrWDT
' Until FBufferIsFull
'End Sub
Public Sub EnableSPI()
Dim pDummy As Byte
Enabled = true
pDummy = SSPBuffer
SSPIF = 0
End Sub
=]
A convenient 4-wire serial interface connects to all common µPs. Individual digits may be addressed and updated without rewriting the entire display. The MAX7219/MAX7221 also allow the user to select code-B decoding or no-decode for each digit.
The devices include a 150µA low-power shutdown mode, analog and digital brightness control, a scan-limit register that allows the user to display from 1 to 8 digits, and a test mode that forces all LEDs on.
'''Main Features:'''
1- Handle one or multiple cascaded MAX72xx modules
2- Use Hardware or Software SPI to manage the MAX72xx module(s). Software SPI is usefull for little PICs that does not have SPI hardware module (like the little 18 pins 18F1320 mcu).
'''For any comment, or feedback (or bug report), please post to Swordfish Forum'''.
!!!VERY IMPORTANT NOTICE concerning Swordfish SPI module:
PS. I never got this module to work with official Swordfish hatdware SPI driver. I used instead a modified version of (hardware) SPI driver using some comments published by Steven on the forum (and sent to me by mail - Great thank Steven).
'''The modified version of the SPI module is also published at the END of this article.'''
!!!IMPORTANT Options
#option MAX7219_DISP_COUNT = nnValue // where nnValue is the number of your cascaded modules. if not specified, defaults to 1 module
#option MAX7219_SPI_SOFTWARE = true // use Software SPI
#option MCPSPI_SOFTWARE = false // Use Hardware SPI (default to false)
#Option MCP_CS = PORTC.1 // Chip Select Pin
!!Single MCP23S17 chip module
connection to hardware SPI is shown in following diagram (for software SPI you can use Swordfish Options to modify pins affectation).
http://www.pocketmt.com/images/mcp23s17.jpg
!!!Module Code
=code [=
{
*************************************************************************
* Name : MAX7219.BAS *
* Author : Ahmed Lazreg ([email protected]) *
* http://www.pocketmt.com *
* http://www.microcodeproject.com *
* Notice : Copyright (c) 20015 Pocket MicroTechnics *
* : All Rights Reserved *
* Date : 01/01/2015 *
* Version : 1.0 *
* Modified: *
* Notes : This module handles Maxime Integrated(TM) MAX7219/MAX7221 *
* Serially Interfaced, 8-Digit LED Display Drivers *
* It can be used via Hardware or Software SPI modules *
*************************************************************************
}
Module MAX7219
Include "convert.bas"
Include "string.bas"
// Number of cascaded display modules
#if IsOption(MAX7219_DISP_COUNT) And Not (MAX7219_DISP_COUNT > 0)
#error MAX7219_DISP_COUNT, "Invalid option, must be > 0"
#endif
#option MAX7219_DISP_COUNT = 1
Const MAX7219_DISPLAY_COUNT = MAX7219_DISP_COUNT
// hardware or software SPI...
#if IsOption(MAX7219_SPI_SOFTWARE) And Not (MAX7219_SPI_SOFTWARE in (true, false))
#error MAX7219_SPI_SOFTWARE, "Invalid option, must be TRUE or FALSE."
#endif
#option MAX7219_SPI_SOFTWARE = false
#if MAX7219_SPI_SOFTWARE = true // use software SPI...
Include "sspi.bas"
#else // use hardware SPI...
Include "SPI.BAS"
#EndIf
#Option MAX7219_CS = PORTC.1
// validate SCK pin...
#If IsOption(MAX7219_CS) And Not IsValidPortPin(MAX7219_CS)
#Error MAX7219_CS, "Invalid option. MCP_CS must be a valid port pin."
#EndIf
Public Dim
CS As MAX7219_CS.MAX7219_CS@ // Chip select
' To be used with WriteDigit(...) subroutine
' for digits (0..9) just send the digit itself
' for non-digits, use codes below as pValue param in WriteDigit(...)
Public Const
SYMB_DASH As Byte = $A, ' displays "-" symbol
SYMB_E As Byte = $B, ' displays "E" symbol
SYMB_H As Byte = $C, ' displays "H" symbol
SYMB_L As Byte = $D, ' displays "L" symbol
SYMB_P As Byte = $E, ' displays "P" symbol
SYMB_BLANK As Byte = $F ' blanks the digit
' Internal registers of the MAX7219
Private Const
REG_NO_OP As Byte = $00,
REG_DIGIT(8) As Byte = ($01, $02, $03, $04, $05, $06, $07, $08),
REG_DECODE_MODE As Byte = $09,
REG_INTENSITY As Byte = $0A,
REG_SCAN_LIMIT As Byte = $0B,
REG_SHUTDOWN As Byte = $0C,
REG_DISP_TEST As Byte = $0F
Private Dim fSelectedDisp As Byte
{
****************************************************************************
* Name : SelectDisplay *
* Purpose : Selects active display *
* param : pDisplayIndex = display index. *
* - First display module = 0 *
* - pDisplayIndex must be < MAX7219_DISP_COUNT *
****************************************************************************
}
Public Sub SelectDisplay(pDisplayIndex As Byte)
If pDisplayIndex >= MAX7219_DISPLAY_COUNT Then
pDisplayIndex = MAX7219_DISPLAY_COUNT
EndIf
fSelectedDisp = pDisplayIndex
End Sub
{
****************************************************************************
* Name : GetSelectedDisplay() *
* Purpose : returns actually selected Max7219 module *
****************************************************************************
}
Public Function GetSelectedDisplay() As Byte
result = fSelectedDisp
End Function
' MAX7219 command format is
' [D15][D14][D13][D12] [D11 - D8] [D7 - D0]
' [ x ][ x ][ x ][ x ] [ REG_ADDR] [msb DATA lsb]
{
****************************************************************************
* Name : WriteReg *
* Purpose : Writes pData byte to register address given by pRegAddress *
****************************************************************************
}
Public Sub WriteReg(pRegAddress As Byte, pData As Byte)
Dim i, count As Byte
CS = 0 ' must be set here mainly because of Max7221
count = MAX7219_DISPLAY_COUNT-fSelectedDisp-1
For i = 1 To count
WriteByte(REG_NO_OP)
WriteByte($00)
Next
WriteByte(pRegAddress)
WriteByte(pData)
count = fSelectedDisp
For i = 1 To count
WriteByte(REG_NO_OP)
WriteByte($00)
Next
CS = 1
End Sub
{
****************************************************************************
* Name : SetDecodeMode *
* Purpose : Sets de Max7219 decode mode for each digit *
* param : pDecodeMask = a 8 bit value. Setting bit to 0/1 *
* disables/enables the B-Decoding for concerned digit *
*
When the code B decode mode is used, the decoder *
looks only at the lower nibble of the data in the digit *
registers (D3–D0), disregarding bits D4–D6. D7, which *
sets the decimal point (SEG DP), is independent of the *
decoder and is positive logic (D7 = 1 turns the decimal *
point on). *
When no-decode is selected, data bits D7–D0 correspond *
to the segment lines of the MAX7219/MAX7221. *
Table 6 shows the one-to-one pairing of each data bit *
to the appropriate segment line. *
****************************************************************************
}
Public Inline Sub SetDecodeMode(pDecodeMask As Byte)
WriteReg(REG_DECODE_MODE, pDecodeMask)
End Sub
{
****************************************************************************
* Name : DisplayOn *
* Purpose : Enables the display *
****************************************************************************
}
Public Inline Sub DisplayOn()
WriteReg(REG_SHUTDOWN, $1)
End Sub
{
****************************************************************************
* Name : DisplayOff *
* Purpose : Shuts down the display *
****************************************************************************
}
Public Inline Sub DisplayOff()
WriteReg(REG_SHUTDOWN, $0)
End Sub
{
****************************************************************************
* Name : SetNumberOfDigits *
* Purpose : Sets the number of digits availble in the display *
* param : pNumberOfDigits = value from 1 to 8 *
* *
* WARNING:::: DANGEOUROUS !!!!! *
* *
* If the scan-limit register is set for three digits or less, *
* individual digit drivers will dissipate excessive amounts *
* of power. Consequently, the value of the RSET resistor *
* must be adjusted according to the number of digits displayed, *
* to limit individual digit driver power dissipation. *
* *
* This function has been added only for debug purpose or *
* - when the Max7219 is used a LED driver (i.e Decode mode disabled) *
* - when the Max7219 is cascaded with another Max7219 that is used to *
* less than 8 digits *
****************************************************************************
}
Public Sub SetNumberOfDigits(pNumberOfDigits As Byte)
If pNumberOfDigits > 8 Then
pNumberOfDigits = 8
ElseIf pNumberOfDigits < 1 Then
pNumberOfDigits = 1
EndIf
WriteReg(REG_SCAN_LIMIT, pNumberOfDigits-1)
End Sub
{
****************************************************************************
* Name : SetBrightness *
* Purpose : Sets de Max7219 brightness *
* param : pIntensity = a 8 bit value between 0 to 15 (16 steps) *
****************************************************************************
}
Public Inline Sub SetBrightness(pIntensity As Byte)
WriteReg(REG_INTENSITY, (pIntensity And $F))
End Sub
{
****************************************************************************
* Name : SetDisplayTestMode *
* Purpose : Enables/Disables de Max7219 test mode *
* param : pDispTestEnabled = True/False to Enable/Disable test mode *
****************************************************************************
}
Public Sub SetDisplayTestMode(pDispTestEnabled As Boolean)
If pDispTestEnabled Then
WriteReg(REG_DISP_TEST, 1)
Else
WriteReg(REG_DISP_TEST, 0)
EndIf
End Sub
{
****************************************************************************
* Name : WriteDigit *
* Purpose : writes a value to position pDigitPos *
* param : pDigitPos = digit position from 0 to 7 *
* pValue = value to write to at pDigitPos digit position *
* values from 0 to 9 displays corresponding digit *
* $A = displays "-" symbol *
* $B = displays "E" symbol *
* $C = displays "H" symbol *
* $D = displays "L" symbol *
* $E = displays "P" symbol *
* $F = blanks the digit *
Use the constants defined at top of this module *
SYMB_DASH As Byte = $A, ' displays "-" symbol *
SYMB_E As Byte = $B, ' displays "E" symbol *
SYMB_H As Byte = $C, ' displays "H" symbol *
SYMB_L As Byte = $D, ' displays "L" symbol *
SYMB_P As Byte = $E, ' displays "P" symbol *
SYMB_BLANK As Byte = $F ' blanks the digit *
*
* pDecimalPointOn = True/False Switch On/Off decimal point led *
****************************************************************************
}
Public Sub WriteDigit(pDigitPos As Byte, pValue As Byte, pDecimalPointOn As Boolean = false)
pValue.Booleans(7) = pDecimalPointOn
WriteReg(REG_DIGIT(pDigitPos), pValue)
End Sub
{
****************************************************************************
* Name : BlankDisplay *
* Purpose : Writes blank to each digit of the display *
* Note : this is **NOT** the same as DisplayOff() which puts the disp *
* in shutdown mode *
****************************************************************************
}
Public Sub BlankDisplay()
Dim i As Byte
For i = 0 To 7
WriteDigit(i, $F, false)
Next
End Sub
{
****************************************************************************
* Name : WriteValue *
* Purpose : Writes a value to the display. *
* Param : pStr = string containing a formate value to display *
* Blanks and special symbols ("-", "H", "L", "E", "P", " ", "." *
* are handled automatically by this routine *
****************************************************************************
}
Public Sub WriteValue(pStr As String)
Dim i, value, curDigit As Byte
Dim NextDigitHasDecPoint As Boolean
NextDigitHasDecPoint = false
curDigit = 0 'Length(pStr)-1
For i = Length(pStr)-1 To 0 Step -1
value = pStr(i)
If value = 45 Then ' "-"
value = SYMB_DASH
ElseIf value = 32 Then ' " "
value = SYMB_BLANK
ElseIf value = 72 Then ' "H"
value = SYMB_H
ElseIf value = 76 Then ' "L"
value = SYMB_L
ElseIf value = 69 Then ' "E"
value = SYMB_E
ElseIf value = 80 Then ' "P"
value = SYMB_P
ElseIf value = 46 Then ' "."
NextDigitHasDecPoint = true
Continue
EndIf
WriteDigit(curDigit, value, NextDigitHasDecPoint)
NextDigitHasDecPoint = false
Inc(curDigit)
Next
End Sub
{
****************************************************************************
* Name : InitChip *
* Purpose : Initialize the MAX7219 CHIP *
****************************************************************************
}
Public Sub InitChip()
Dim i As Byte
For i = 0 To MAX7219_DISPLAY_COUNT-1
SelectDisplay(i)
SetNumberOfDigits(8)
DisplayOn()
SetDecodeMode(%11111111) // enables B-Decoding for all digits
SetBrightness($A) // can be up to 15. intensity 0 means display off
WriteReg(REG_NO_OP, $FF)
BlankDisplay()
Next
SelectDisplay(0)
End Sub
{
****************************************************************************
* Name : Initialize *
* Purpose : Initializes module and included modules *
****************************************************************************
}
Public Sub Initialize()
#If MAX7219_SPI_SOFTWARE
SSPI.Initialize
SSPI.SetClock(spiIdleHigh)
#Else
SPI.SetAsMaster(spiOscDiv16)
SPI.SetClock(spiIdleHigh, spiRisingEdge)
SPI.SetSample(spiSampleMiddle)
EnableSPI()
#EndIf
Output(CS)
High(CS)
InitChip()
End Sub
Initialize()
=]
!!!Example Code
This program uses 2 MAX7219 modules, each handling 8 7Seg display module.
=code [=
{
*************************************************************************
* Name : MAX7219.BAS *
* Author : Ahmed Lazreg ([email protected]) *
* http://www.pocketmt.com *
* http://www.microcodeproject.com *
* Notice : Copyright (c) 20015 Pocket MicroTechnics *
* : All Rights Reserved *
* Date : 01/01/2015 *
* Version : 1.0 *
* Desc. : Test program for MAX7219 module *
* *
*************************************************************************
}
Program Max7219_test
Device = 18F452
Clock = 20
Include "utils.bas"
Include "convert.bas"
//#option MAX7219_SPI_SOFTWARE = true
#option MAX7219_DISP_COUNT = 2
Include "Max7219.bas"
Dim RED_LED As PORTB.1
Dim i, j As Word
Dim k As Float
Sub Init_MCU()
PORTA = %00000000
TRISA = %11111100
PORTB = %00000000
TRISB = $00
SetAllDigital()
End Sub
Init_MCU()
High(RED_LED)
// main program loop
SelectDisplay(0)
SetDisplayTestMode(true)
DelayMS(300)
SetDisplayTestMode(false)
SelectDisplay(0)
WriteDigit(6, SYMB_E)
WriteDigit(7, SYMB_P)
DelayMS(1000)
SelectDisplay(0)
BlankDisplay()
WriteValue("HELP-. ")
SelectDisplay(1)
WriteValue("-41.73")
DelayMS(1000)
SelectDisplay(0)
BlankDisplay()
WriteValue("HELP ")
SelectDisplay(1)
BlankDisplay()
WriteDigit(7, SYMB_L)
i = 0
j = 0
k = 0.0
While (true)
Toggle(RED_LED)
DelayMS(800)
SelectDisplay(0)
WriteValue(DecToStr(i))
SelectDisplay(1)
WriteValue(FloatToStr(k))
i = i +1
k = k + 0.2
End While
End Program
=]
!!Modified Hardware SPI module
=code [=
{
****************************************************************************
* Name : SPI.BAS *
* Author : John Barrat *
* : David John Barker *
* Notice : Copyright (c) 2006 Mecanique *
* : All Rights Reserved *
* Date : 26/05/2006 *
* Version : 1.1 Changed WriteByte() param to WREG for silicon workaround *
* : 1.0 Release *
* : ============================================================= *
* Notes : This post was made on the Swordfish forum by Steve B on *
* : April 8th 2007... *
* : I was having some trouble with the SPI module as well. I am *
* : using an 18F2620, Silicon A4, and was getting some *
* : inconsistent reads/writes, especially when doing a lot of *
* : TX/RX one after another. After looking at the errata, I *
* : changed the ReadByte and WriteByte routines as follows... *
* : *
* : Public Function ReadByte() As SSPBuffer *
* : SSPIF = 0 *
* : SSPBuffer = 0 *
* : Repeat *
* : ClrWDT *
* : Until SSPIF = 1 *
* : End Function *
* : *
* : Public Sub WriteByte(pData As WREG) *
* : SSPIF = 0 *
* : SSPBuffer = pData *
* : Repeat *
* : ClrWDT *
* : Until SSPIF = 1 *
* : End Sub *
* : *
* : Now they use the SSP Interrupt flag instead of the Buffer *
* : Full flag (SSPSTAT.0). I also added a subroutine to enable *
* : the SPI module *
* : *
* : Public Sub EnableSPI() *
* : Dim pDummy As Byte *
* : Enabled = true *
* : pDummy = SSPBuffer *
* : SSPIF = 0 *
* : End Sub *
****************************************************************************
}
Module SPI
Include "system.bas"
// map registers to SSP(x)
#if _mssp = 0
#error _device + " does not support MSSP"
// single SSP...
#elseif _mssp = 1
Dim
SSPControl1 As SSPCON1,
SSPStatus As SSPSTAT,
SSPBuffer As SSPBUF,
SCK As PORTC.3,
SDI As PORTC.4,
SDO As PORTC.5,
_SS As PORTA.5
// has more than one SSP module...
#else
Dim // -> MSSP2
SSPControl1 As SSP1CON1, // as SSP2CON1
SSPStatus As SSP1STAT, // as SSP2STAT
SSPBuffer As SSP1BUF, // as SSP2BUF
SCK As PORTC.3,
SDI As PORTC.4,
SDO As PORTC.5,
_SS As PORTA.5
#endif
// SSPSTAT bitnames
Public Dim
BF As SSPStatus.0, // buffer full (receive and transmit)
SMP As SSPStatus.7, // read sample mode
CKE As SSPStatus.6 // clock edge control
// SSPCON1 bitnames, master mode only...
Public Dim
WCOL As SSPControl1.7, // write collision Detect
SSPOV As SSPControl1.6, // receive overflow
SSPEN As SSPControl1.5, // synchronous receive enable
CKP As SSPControl1.4, // clock polarity
// synchronous mode select bits, %00XX for master mode
SSPM3 As SSPControl1.3, // always zero
SSPM2 As SSPControl1.2, // slave Mode
SSPM1 As SSPControl1.1, // clock Mode (MSB)
SSPM0 As SSPControl1.0 // clock Mode (LSB)
// interrupt flag
Public Dim
SSPIF As PIR1.3
Public Const
spiOscDiv4 = 0, // master mode FOSC/4
spiOscDiv16 = 1, // master mode FOSC/16
spiOscDiv64 = 2, // master mode FOSC/64
spiOscTimer2 = 3, // master mode TMR2 provides clock
spiSlaveSSEnabled = 4, // slave mode slave synch enabled
spiSlaveSSDisabled = 5, // slave mode slave synch disabled
// clock idle and edge settings (SPI Mode compatible)
spiRisingEdge = $40, // data transmitted on rising edge of clock
spiFallingEdge = $00, // data transmitted on falling edge of clock
spiIdleHigh = $10, // idle state for clock is high
spiIdleLow = $00, // idle state for clock is low
// RX data sampling settings (SSPStatus.6 - SMP)
spiSampleEnd = $80, // input data sampled at end of data output time
spiSampleMiddle = $00 // input data sampled at middle of data output time
// local helper aliases...
Dim
FBufferIsFull As SSPStatus.Booleans(0) // BF as boolean
// public aliases...
Public Dim
Enabled As SSPControl1.Booleans(5), // SSPEN as boolean
Overflow As SSPControl1.Booleans(6), // SSPOV as boolean
WriteCollision As SSPControl1.Booleans(7) // WCOL as boolean
{
****************************************************************************
* Name : SetAsMaster *
* Purpose : Set SPI to master mode *
* : spiOscDiv4 (DEFAULT), spiOscDiv16, spiOscDiv64, spiOscTmr2 *
****************************************************************************
}
Public Sub SetAsMaster(pMode As Byte = spiOscDiv4)
SSPControl1 = SSPControl1 And $F0
SSPControl1 = SSPControl1 Or pMode
Output(SDO)
Output(SCK)
End Sub
{
****************************************************************************
* Name : SetAsSlave *
* Purpose : Set SPI to slave mode *
* : spiSlaveSSEnabled, spiSlaveSSDisabled (DEFAULT) *
****************************************************************************
}
Public Sub SetAsSlave(pMode As Byte = spiSlaveSSDisabled)
SSPControl1 = SSPControl1 And $F0
SSPControl1 = SSPControl1 Or pMode
Output(SDO)
Input(SCK)
Input(_SS)
End Sub
{
****************************************************************************
* Name : SetSample *
* Purpose : Sets when the SPI input data in sampled *
* : spiSampleEnd, spiSampleMiddle. For slave mode, sample should *
* : always be spiSampleMiddle *
****************************************************************************
}
Public Sub SetSample(pSample As Byte)
SSPStatus = SSPStatus And $7F
SSPStatus = SSPStatus Or pSample
End Sub
{
****************************************************************************
* Name : SetClock *
* Purpose : Set SPI idle state and data transmission clock edge *
* : pIdle -> spiIdleHigh, spiIdleLow *
* : pEdge -> spiRisingEdge, spiFallingEdge *
****************************************************************************
}
Public Sub SetClock(pIdle As Byte, pEdge As Byte)
SSPControl1 = SSPControl1 And $EF
SSPControl1 = SSPControl1 Or pIdle
If pIdle = spiIdleHigh Then
pEdge = Not pEdge And $BF
EndIf
SSPStatus = SSPStatus And $BF
SSPStatus = SSPStatus Or pEdge
End Sub
{
****************************************************************************
* Name : ReadByte *
* Purpose : Read a single byte from the SPI bus *
****************************************************************************
}
'Public Function ReadByte() As SSPBuffer
' SSPBuffer = 0
' Repeat
' ClrWDT
' Until FBufferIsFull
'End Function
Public Function ReadByte() As SSPBuffer
SSPIF = 0
SSPBuffer = $FF
Repeat
ClrWDT
Until SSPIF = 1
ReadByte = SSPBuffer
End Function
Public Sub WriteByte(pData As Byte)
SSPIF = 0
SSPBuffer = pData
Repeat
ClrWDT
Until SSPIF = 1
End Sub
{
****************************************************************************
* Name : WriteByte *
* Purpose : Write a single byte to the SPI bus *
****************************************************************************
}
'Public Sub WriteByte(pData As WREG)
' SSPBuffer = pData
' Repeat
' ClrWDT
' Until FBufferIsFull
'End Sub
Public Sub EnableSPI()
Dim pDummy As Byte
Enabled = true
pDummy = SSPBuffer
SSPIF = 0
End Sub
=]