MAX7219 Example (8 digit segment driver)

Published: (December 31, 2025 at 03:35 PM EST)
4 min read
Source: Dev.to

Source: Dev.to

Hardware

The board I used contains an 8‑digit 7‑segment display and a MAX7219 driver.

MAX7219 8‑digit 7‑segment

Pinout

PinFunction
GNDPower ground
VCCPower supply (5 V)
DINSerial data input
CLKSerial clock
LOAD / CSLatch (chip‑select)

Although the pins look like a SPI interface, the MAX7219 only uses a simple 16‑bit serial protocol (the MAX7221 is the SPI‑compatible variant).

Serial Data Format

Each transaction consists of 16 bits:

  • Upper 8 bits – Register address
  • Lower 8 bits – Data for that register

The datasheet shows the bits being shifted MSB first (the functional diagram mistakenly mentions LSB first).

Serial Data Format

Register Address Map

Address (hex)Register nameDescription
0x01‑0x08Digit 0‑7Segment data for each digit
0x09Decode ModeEnable/disable BCD decoding per digit
0x0AIntensityBrightness (0x0 … 0xF)
0x0BScan‑LimitNumber of digits displayed (0‑7)
0x0CShutdownNormal operation (0x01) / shutdown (0x00)
0x0FDisplay TestForce all segments on at full intensity

Register Address Map

The Display Test register lights every segment of every digit at maximum intensity.
The Shutdown register uses 0x01 to enable normal operation (the name is a bit confusing).

Register: Scan‑Limit

The Scan‑Limit register selects how many digits are active:

  • 0x00 – Only digit 0 is displayed (default after reset)
  • 0x07 – All eight digits are displayed

If you want no output at all, either:

  • Put the device into Shutdown (0x0C 0x00), or
  • Set the first digit to 0x00 (no segments on) in No‑Decode mode, or 0x0F in BCD mode.

Register: Digit

Each digit register holds 8 bits that control the individual segments (or a BCD value when decoding is enabled).

1. No‑Decode (raw segment) mode

Bits correspond to segments A‑G and the decimal point DP:

BitSegment
D7DP
D6A
D5B
D4C
D3D
D2E
D1F
D0G

Example – to display the numeral 1 you would write 0x30 (D5=1, D4=1, i.e. segments B and C).

No Decode Mode

2. BCD (decode) mode

When the corresponding bit in the Decode Mode register is set, the driver interprets the lower‑nibble (0x00x9) as a decimal digit and automatically lights the proper segments.

Special BCD codes (0xA0xF):

CodeCharacter
0xAdash (-)
0xBE
0xCH
0xDL
0xEP
0xFblank (all segments off) – same effect as 0x00 in No‑Decode mode

You can even spell “HELP” by sending the sequence 0x040C 0x030B 0x020D 0x010E (digit 3 → H, digit 2 → E, digit 1 → L, digit 0 → P).

Register: Decode Mode

The Decode Mode register is a mask; each bit enables BCD decoding for the corresponding digit:

BitDigit
D0Digit 0
D1Digit 1
D7Digit 7
  • 0x00 – No decoding for any digit (raw segment mode).
  • 0x01 – Enable BCD decoding for Digit 0 only.
  • 0x03 – Enable BCD decoding for Digits 0 & 1, etc.

Loading Data (Serial Write)

Data is clocked in on the rising edge of CLK. The driver samples DIN and shifts the bit into an internal 16‑bit shift register (MSB first).

Sending a single bit (Arduino‑style pseudocode)

digitalWrite(PIN_CLK, LOW);          // prepare for rising edge
if (cmd & 0x8000) {                  // MSB of the 16‑bit word?
    digitalWrite(PIN_DIN, HIGH);
} else {
    digitalWrite(PIN_DIN, LOW);
}
digitalWrite(PIN_CLK, HIGH);         // latch the bit

Sending a full 16‑bit command

// Example: enable Display‑Test (register 0x0F, data 0x01)
uint16_t cmd = 0x0F01;               // high byte = address, low byte = data

for (int i = 0; i (reg)

Note: This can be converted into a macro if you need better performance.

Building Commands

The commands are very easy to build. For example, to send the number 6 to digit 0 (using BCD):

// 0x1 is the register for digit 0
uint16_t cmd = buildCmd(0x1, 6);
// send the command to the module
sendCmd(cmd);

If you are not using BCD:

// 0x1 is the register for digit 0
// 6 uses segments A, C, D, E, F, G → 0b0101 1111 = 0x5F
uint16_t cmd = buildCmd(0x1, 0x5F);
sendCmd(cmd);

Example

The example below uses test mode, then resets most registers. Resetting the module alone would be sufficient, but resetting everything gives you a clean slate before configuring it.

// Enable all 8 digits
cmdSetScanLimit(7);

// Set lowest intensity
cmdSetIntensity(0);

// Use BCD decoding for all digits
cmdSetDecodeMode(0xFF);

// Blank all segments
for (uint8_t i = 0; i < 8; i++) {
    uint16_t cmd = buildCmd(REGISTER_DIGIT0 + i, 0xF);
    sendCmd(cmd);
}

// Show all possible BCD values, finishing with a blank
for (uint8_t i = 0; i < 8; i++) {
    for (uint8_t j = 0; j < 16; j++) {
        uint16_t cmd = buildCmd(REGISTER_DIGIT0 + i, j);
        sendCmd(cmd);
        delay(200);
    }
}

Example Repository

https://github.com/danguer/arduino-examples/tree/main/max7219

Datasheet

https://www.analog.com/media/en/technical-documentation/data-sheets/max7219-max7221.pdf

Back to Blog

Related posts

Read more »

AI SEO agencies Nordic

!Cover image for AI SEO agencies Nordichttps://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads...