Dotmatrix на MAX7219
Для начального уровная достаточно смотреть:
- Минимальное и максимальное напряжение питания и дата линий - для каких-то микросхем нам может не хватить 3.3v, а какие-то можно спалить пятью вольтами. В обоих случаях придется либо искать замену, либо использовать level-converter. Хотя, иногда, если очень хочется, можно и забить на рекомендацию и попробовать - для esp8266
max7219
seems to work fine - Timing Diagram - например для 74hc595 она простая и можно понять логику по ней. Здесь думаю не тот случай.
- Detailed description - читаем какие есть режимы работы, регистры итд. Потихоньку вкуриваем ей управлять.
Инициализация
Даташит достаточно скромно описывает процесс инициализации.

Здесь следовало бы упомянуть, что при запуске в SRAM лежит мусор. Поэтому перед тем, как выходить из shutdown mode, следует:
- Scan Limit установить в максимум (на матрице 7 строк, по умолчанию включена одна)
- Настроить intensity как нам хочется
- Занулить дисплей. Отдельной команды на это нет, поэтому отправляем 7 пакетов - на каждую строку.
После чего спокойно выходим из shutdown и рисуем что хотим.
Относительно отображения, микросхема оперирует в двух режимах (управляются регистром Decode Mode):
- no-decode - биты в D0-D7 напрямую управляют каждый своим анодом (в случае 7-сегментных дисплеев, это сегмент, в случае матрицы - строчка) (Table 6. No-Decode Mode Data Bits and Corresponding Segment Lines)
- Code B decode - в битах D0-D3 закодирован символ (Table 5. Code B Font)
Так как мы работаем с матрицей, второй вариант нам не интересен, поэтомуDECODE MODE
должен стоять в режимеNo decode for digits 7–0
(Table 4. Decode-Mode Register Examples)
No-Op регистр нужен когда мы работаем с цепочкой микросхем. Если, например, имея цепочку из четырех - мы хотим заставить только четвертую выполнить команду - сдвигаем эту команду первой, за ней сдвигаем 3 no-op команды. Когда мы дернем защелку - первые три микросхемы ничего не сделают.
Наброски реализации библиотеки
#pragma once
#include "pinout.hpp"
typedef enum MaxRegister {
noop = 0x00,
d0 = 0x01,
...
scanLimit = 0x0B,
shotDown = 0x0C,
...
} MaxRegister;
static const int defaultIntensity = 0x08;
void softwareSPI(uint8_t A, uint8_t B) {
digitalWrite(csPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, A);
shiftOut(dataPin, clockPin, MSBFIRST, B);
digitalWrite(csPin, HIGH);
}
void displayInit() {
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(csPin, OUTPUT);
digitalWrite(csPin, HIGH);
// !!! выставляем scanLimit на максимум (таблица 8) - это количество колонок матрицы по умолчанию горела бы только одна колонка
softwareSPI(MaxRegister::scanLimit, 0x07);
// !!! выставляем intensity согласно (таблице 7)
...
// отключаем decode-mode, если он вдруг включен (таблица 4)
...
// отключаем dosplay-test (Table 10).
...
// Очищаем дисплей. Документация про это умалчивает, но в SRAM при запуске лежит мусор
displayClear();
// теперь выходим в рабочий режим (таблица 3) и рисуем что хотим.
softwareSPI(MaxRegister::shotDown, 0x01);
}