Dotmatrix на MAX7219

Даташит 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);  
}