Sixteen bits, one register
Every message to a MAX7219 is the same shape: sixteen bits, of which four are ignored, four are an address and eight are data. Then CS goes high and the chip acts on it. Nothing at all happens before that edge, which explains one of the stranger faults on this board.
One frame
Press Clock it in and watch what the display does, which is nothing, until the very last step.
Sixteen rising clock edges push sixteen bits into an ordinary shift register inside the chip. Most significant bit first. The chip is not interpreting any of them as they arrive — it does not know whether it is receiving an address or data, and it does not care.
| Bits | What they are |
|---|---|
| D15–D12 | Ignored. Send zeros. |
| D11–D8 | The register address, 0x0 to 0xF |
| D7–D0 | The data byte |
Then CS rises, and on that edge the sixteen bits move into whichever register the address named. That is the entire protocol.
Why the edge matters
Because everything before it is reversible and nothing after it is.
Two consequences follow, and both of them show up as real faults:
CS has to rise after the sixteenth clock edge and before the next one. Leave it and the frame is lost — the seventeenth clock pushes the first bit out the other end of the shift register and the word is scrambled. Every library gets this right; hand-written bit-banging sometimes does not.
CS held low gives you a display that lags. Each frame you send sits in the shift register, uncommitted, until the following frame's clocks push it into place. So the display shows the previous message, always, and looks like a timing bug in your sketch. It is a wiring problem: something else is holding that pin, or it was never connected.
The fourteen registers
Eight of them are the digits. The other six are the whole of the chip's behaviour.
| Address | Register | What it does |
|---|---|---|
0x00 | No-op | Nothing. What you send to a chip in a chain you are not addressing. |
0x01–0x08 | Digit 0–7 | One byte each. This is the display. |
0x09 | Decode mode | One bit per digit: use the built-in font, or take the bits raw. |
0x0A | Intensity | Brightness, 0 to 15. |
0x0B | Scan limit | How many digits get a turn, 0 to 7 meaning 1 to 8. |
0x0C | Shutdown | 0 blanks and stops the scan. The power-up value. |
0x0F | Display test | 1 lights everything, overriding all of the above. |
Two things worth noticing in that table. The digit registers are one-based while
the digits are zero-based — digit 0 lives at address 0x01 — which is a
transposition waiting to happen. And 0x0F, display test, ignores shutdown,
ignores intensity and ignores every digit byte, which makes it the single most
useful diagnostic on the board: one write, and either all sixty-four LEDs light
or your wiring is wrong.
Speed is not the problem
The minimum clock period is 100 ns, so the interface will take 10 MHz. Nothing
in the Arduino world sends it that fast — LedControl bit-bangs with
shiftOut and manages a few hundred kilohertz on an Uno — and it does not
matter, because eight digits is sixteen bytes and a clock update is two or three
of them.
Which is why none of the three signal pins has to be a special pin. There is no peripheral to match, no baud rate to agree on, and no minimum speed below which the chip times out. Any three GPIOs.
When it does not work
CS is not being taken high between frames. The shift register keeps accepting bits whatever CS is doing, and only the rising edge moves them into a real register — so with CS held low each frame appears when the next one pushes it through. Check nothing else on your board is driving that pin, and that you have not wired CS to a pin your board uses for something at boot.
10 MHz, from the 100 ns minimum clock period. No Arduino library gets close: LedControl bit-bangs with shiftOut and manages a few hundred kilohertz on an Uno. Speed is never the constraint on this board, which is why any three GPIO pins will do.
Yes. The frame is MSB first, data sampled on the rising clock edge, which is SPI mode 0, and CS is an ordinary chip select you assert low around the sixteen bits. The MAX7221 is the variant Maxim made properly SPI-compatible, but the MAX7219 works this way in practice on every board people have tried it on.
Nothing. D15 to D12 are genuinely don't-care and the chip discards them, so send zeros and stop worrying about them. They exist because the address field only needs four bits and the frame is a round sixteen.
The digit registers are addresses 0x01 to 0x08 for digits 0 to 7, so they are one-based while the digit numbering is zero-based. Digit 0 is register 0x01. Address 0x00 is the no-op register and writing a digit's worth of data there does nothing at all.
The chip has a font built in and will also let you drive the segments yourself — and the raw bit order is backwards from every other display in the shop.
Decode, or no decode →Edit this page — content/books/max7219-tube-clock/sixteen-bits-one-register.mdx
Questions about this product
See what other owners have asked, and read their solutions.
MAX7219 Vintage Tube LED Clock Kit
Loading discussions…
Discuss this article
Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.