Сегодня мы поговорим об очень удобных и полезных микрухах — драйверах MAX7219 и MAX7221. Эти драйвера позволяют управлять семисегментными индикаторами (с общим катодом), светодиодными линейками или просто отдельными светодиодами. Максимум к ним можно подключить по 64 светодиода (ну или, соответственно, по восемь семисегментных индикаторов). Сами драйвера управляются по интерфейсу SPI (режим 0), поддерживая частоту работы интерфейса до 10 МГц. Надо сказать, что драйвер MAX7219 не полностью соответствует нормам SPI (в отличии от MAX7221), но тем не менее его прекрасно можно по SPI программировать, главное — чётко помнить в чём же всё таки заключается несоответствие (позднее расскажу об этом и ещё некоторых отличиях этих микросхем).
Распиновка и назначение ног.
1 — DIN. Последовательный ввод данных. Данные загружаются в 16-ти разрядный сдвиговый регистр по переднему фронту тактового сигнала.
2,3,5-8,10,11 — DIG0-DIG7. Выводы для подключения общих катодов индикаторов. В MAX7219 эти линии при отключении подтягиваются к плюсу, а в MAX7221 переходят в высокоомное состояние (в Z-состояние).
4,9 — GND. Сюда подключается «ноль» питания. Для правильной работы микрухи — к «нулю» должны быть подключены оба вывода.
12 — LOAD у MAX7219 и CS у MAX7221. У MAX7219 данные загружаются в сдвиговый регистр независимо от состояния сигнала LOAD. Запоминаются и поступают к дальнейшей обработке последние 16 принятых бит. Происходит это по переднему фронту сигнала LOAD (то есть только в момент переключения сигнала LOAD из 0 в 1). У MAX7221 данные загружаются в приёмный сдвиговый регистр только когда сигнал CS находится в состоянии низкого уровня (то есть только когда микросхема «выбрана», если говорить в терминах интерфейса SPI). Запоминаются и поступают к обработке также последние 16 принятых бит, происходит это также по переднему фронту сигнала CS.
13 — CLK. Вход тактирования. Как я уже сказал, микросхемы совместимы с SPI Mode 0, т.е. в отсутствии передачи на линии тактирования низкий уровень, по переднему фронту сигнала CLK происходит считывание данных со входа, по заднему — сдвиг (подробнее о том, как это работает — почитайте теорию SPI по ссылке в начале статьи).
14-17, 20-23 — SEG A-SEG G, DP. Выводы для подключения сегментов семисегментных индикаторов. В MAX7219 эти линии при отключении подтягиваются к GND, а в MAX7221 переходят в высокоомное состояние (в Z-состояние).
18 — ISET. К этому выводу подключается резистор (вторая нога резистора — к плюсу), позволяющий задавать пиковый ток сегмента и таким образом устанавливать яркость свечения сегментов. Минимальное сопротивление этого резистора должно быть 9,53 кОм, что примерно соответствует току сегмента 40мА. Ток, текущий через ISET номинально в 100 раз меньше пикового тока сегмента. Из даташита совершенно непонятно, одинаково ли падение напряжения на этом резисторе, но если считать, что оно одинаково, то это даст такую формулу для расчёта резистора: R=9,53*40/Ipk, где Ipk — требуемый пиковый ток сегмента. Подключив к этой ноге переменный резистор — можно регулировать яркость свечения сегментов.
19 — V+. Сюда подключается «+» питания.
24 — DOUT. Последовательный вывод данных. На этом выводе появляются принятые на входе DIN данные c задержкой в 16 с половиной тактов. Почему именно 16.5, а не 16 или 17? Потому что в SPI первая половина такта (после переднего фронта для MODE 0) — чтение, вторая половина такта (задний фронт для режима MODE 0) — сдвиг, а данные появятся на выходе только после сдвига. С помощью DOUT можно каскадно соединить несколько драйверов, при этом выход (DOUT) первого драйвера подключается ко входу (DIN) второго драйвера, выход второго — ко входу третьего и т.д.
Управляется MAX7219/MAX7221 через специальные регистры. Данные, как я уже говорил, загружаются в микросхему по SPI, в виде 16-ти битных пакетов (помните, на входе 16-ти битный сдвиговый регистр), старшим битом вперёд. В пакетах содержится адрес регистра, к которому обращаются, и данные, которые в него нужно загрузить.
Формат пакета:
Карта регистров:
Имя регистра | Адрес регистра | |||||
---|---|---|---|---|---|---|
bin | hex | |||||
D15-D12 | D11 | D10 | D9 | D8 | ||
No-op | XXXX | 0 | 0 | 0 | 0 | X0h |
Digit 0 | XXXX | 0 | 0 | 0 | 1 | X1h |
Digit 1 | XXXX | 0 | 0 | 1 | 0 | X2h |
Digit 2 | XXXX | 0 | 0 | 1 | 1 | X3h |
Digit 3 | XXXX | 0 | 1 | 0 | 0 | X4h |
Digit 4 | XXXX | 0 | 1 | 0 | 1 | X5h |
Digit 5 | XXXX | 0 | 1 | 1 | 0 | X6h |
Digit 6 | XXXX | 0 | 1 | 1 | 1 | X7h |
Digit 7 | XXXX | 1 | 0 | 0 | 0 | X8h |
Decode Mode | XXXX | 1 | 0 | 0 | 1 | X9h |
Intensity | XXXX | 1 | 0 | 1 | 0 | XAh |
Scan Limit | XXXX | 1 | 0 | 1 | 1 | XBh |
Shutdown | XXXX | 1 | 1 | 0 | 0 | XCh |
Display Test | XXXX | 1 | 1 | 1 | 1 | XFh |
После подачи питания все регистры сброшены и MAX7219 / MAX7221 находится в остановленном состоянии. Прежде чем использовать драйвер — сначала нужно его настроить (записать в нужные регистры нужные данные).
Данные, записанные в регистрах «Digit0»-«Digit7» определяют состояния сегментов соответствующих семисегментных индикаторов. В зависимости от выбранного режима («No decode», «BCD code B»), эти данные могут интерпретироваться двумя способами.
В режиме «No decode» каждый бит данных в соответствующем регистре «Digit X» определяет состояние одного из сегментов семисегментного индикатора «X» (0 — сегмент погашен, 1 — сегмент горит). Карта сегментов и соответствующие им биты указаны на рисунке справа.
В режиме «BCD code B» 7 младших бит данных, записанных в регистре «Digit X», кодируют отображаемый на семисегментном индикаторе символ, в соответствии с таблицей ниже, а старший бит данных кодирует состояние сегмента DP (0 — сегмент погашен, 1 — сегмент горит).
Таблица кодировки режима «BCD code B»:
Символ | Данные в регистре Digit X | Состояние сегментов индикатора | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
D6-D4 | D3 | D2 | D1 | D0 | A | B | C | D | E | F | G | |
0 | XXX | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 |
1 | XXX | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 |
2 | XXX | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 0 | 1 |
3 | XXX | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |
4 | XXX | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 |
5 | XXX | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 0 | 1 | 1 |
6 | XXX | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 1 | 1 | 1 | 1 |
7 | XXX | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
8 | XXX | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
9 | XXX | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 |
— | XXX | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
E | XXX | 1 | 0 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 1 |
H | XXX | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 1 | 1 |
L | XXX | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 0 |
P | XXX | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 1 |
пусто | XXX | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Режим выбирается индивидуально для каждого из регистров «Digit 0» — «Digit 7», установкой в 0 («No decode») или 1 («BCD code B») соответствующего бита регистра «Decode Mode».
Данные в регистре «Intensity» определяют средний ток сегмента (в долях от пикового тока, заданного резистором на ноге «ISET») в соответствии с таблицей ниже:
Доля от Ipk | D4 — D7 | D3 | D2 | D1 | D0 | HEX код | |
---|---|---|---|---|---|---|---|
MAX7219 | MAX7221 | ||||||
1/32 | 1/16 | XXXX | 0 | 0 | 0 | 0 | X0h |
3/32 | 2/16 | XXXX | 0 | 0 | 0 | 1 | X1h |
5/32 | 3/16 | XXXX | 0 | 0 | 1 | 0 | X2h |
7/32 | 4/16 | XXXX | 0 | 0 | 1 | 1 | X3h |
9/32 | 5/16 | XXXX | 0 | 1 | 0 | 0 | X4h |
11/32 | 6/16 | XXXX | 0 | 1 | 0 | 1 | X5h |
13/32 | 7/16 | XXXX | 0 | 1 | 1 | 0 | X6h |
15/32 | 8/16 | XXXX | 0 | 1 | 1 | 1 | X7h |
17/32 | 9/16 | XXXX | 1 | 0 | 0 | 0 | X8h |
19/32 | 10/16 | XXXX | 1 | 0 | 0 | 1 | X9h |
21/32 | 11/16 | XXXX | 1 | 0 | 1 | 0 | XAh |
23/32 | 12/16 | XXXX | 1 | 0 | 1 | 1 | XBh |
25/32 | 13/16 | XXXX | 1 | 1 | 0 | 0 | XCh |
27/32 | 14/16 | XXXX | 1 | 1 | 0 | 1 | XDh |
29/32 | 15/16 | XXXX | 1 | 1 | 1 | 0 | XEh |
31/32 | 15/16 | XXXX | 1 | 1 | 1 | 1 | XFh |
В регистре «Scan Limit» можно выбрать обслуживаемые драйвером семисегментные индикаторы. Они определяются четырьмя младшими битами загруженного в этот регистр байта. Количество обслуживаемых драйвером индикаторов связано с их частотой обновления. Если задействованы все 8 семисегментных индикаторов, то частота обновления составляет 800 Гц, если меньше, то 8*800/N (N — количество задействованных индикаторов). Поскольку количество обслуживаемых индикаторов влияет на яркость, то не рекомендуется показывать пустые старшие символы простым отключением их от обслуживания в регистре «Scan Limit».
Таблица (обслуживаемые индикаторы, в зависимости от значения в регистре «Scan Limit»):
Номера обслуживаемых индикаторов | Данные в регистре «Scan Limit» | ||||
---|---|---|---|---|---|
D3 — D7 | D2 | D1 | D0 | HEX | |
0 | XXXXX | 0 | 0 | 0 | X0h |
0,1 | XXXXX | 0 | 0 | 1 | X1h |
0,1,2 | XXXXX | 0 | 1 | 0 | X2h |
0,1,2,3 | XXXXX | 0 | 1 | 1 | X3h |
0,1,2,3,4 | XXXXX | 1 | 0 | 0 | X4h |
0,1,2,3,4,5 | XXXXX | 1 | 0 | 1 | X5h |
0,1,2,3,4,5,6 | XXXXX | 1 | 1 | 0 | X6h |
0,1,2,3,4,5,6,7 | XXXXX | 1 | 1 | 1 | X7h |
Регистр «Display test» позволяет провести тестирование исправности сегментов всех подключенных семисегментных индикаторов. При установки младшего бита этого регистра в 1 — драйвер включает все сегменты всех подключенных индикаторов. Чтобы прекратить тест и вернуться в нормальное состояние — нужно записать в младший бит регистра «Display test» ноль.
Регистр «No-op» используется при каскадном подключении драйверов. Для того, чтобы обратиться, например, к третьему драйверу в цепочке, не влияя на работу первых двух, — нужно для первых двух обратиться к регистру «No-op». Поскольку адрес этого регистра равен нулю, то сделать это очень просто: сначала за 16 тактов отправляем данные для третьего регистра, потом устанавливаем линию данных в ноль и отщёлкиваем ещё 2 раза по 16 тактов. В результате первый отправленный пакет будет загружен в третий регистр, а следующие два пакета (загруженные в первый и второй регистры) будут иметь адрес ноль, то есть будут обращаться к регистру «No-op».
А теперь небольшой пример того, как к этим драйверам подключать семисегментные индикаторы. Вместо семисегментных индикаторов могут быть просто диоды (собственно, семисегментный индикатор с общим катодом — это и есть всего лишь восемь светодиодов, у которых объединены катоды). Схема подключения семисегментных индикаторов к драйверу:
Пример готовой платы (лицевая панель контроллера ICPCon) с пятью семисегментными индикаторами и драйвером MAX7219:
Вот и всё. Реализацию SPI на микроконтроллере можно посмотреть по этой ссылке: