7 ми сегментный индикатор подключение. Что такое мультиплексинг

  • 04.11.2019

На этот раз, в статье будет рассмотрен один из интереснейших модулей, а именно - многоразрядный семисегментный индикатор на базе микросхемы MAX7219. Почему многоразрядный? Ответ прост - количество разрядов это и есть количество цифр, которое может отобразить модуль. Например, на фото ниже, показаны три вида многоразрядных индикаторов, слева направо - 4-х разрядный, 6-ти разрядный, 8-ми разрядный. Причем первый является 4-х разрядным индикатором часового типа. Отличие индикатора часового типа от обычного в том, что у него есть знак двоеточия, тогда как у обычного любого индикатора этот знак заменяется точкой внизу, рядом с цифрой.

В этой статье, рассматриваемые модули работают на базе микросхемы MAX7219 . Эта микросхема является драйвером для светодиодных семисегментных индикаторов, а также LED матриц 8х8, и мы не будем рассматривать принципиальные схемы подключения этого драйвера. Просто за основу взят готовый модуль, будут приведены примеры подключения к плате Arduino UNO и разобрана работа с функциями библиотеки LedControl . Кстати, как уже было сказано - LED матрицы 8х8 тоже работают на базе драйвера MAX7219 , и кому интересно то добро пожаловать в статьи:

Итак, начнем... Думаю что про многоразрядность было дано хорошее описание, а вот почему семисегментный? Ответ тоже не так уж и сложен - потому что для формирования символа или отображения цифры используется семь светодиодов, проиндексированных буквами A, B, C, D, E, F, G, таблица ниже показывает как это обозначено:

Как видно из таблицы, есть также и восьмой светодиод - DP. Полностью закодировать символ или цифру можно в 1 байте, устанавливая или сбрасывая определенный бит, как это показано с примером кодирования символа J. В примере установлены биты B, C, D, E , что позволяет отобразить заданный символ на семисегментном индикаторе.

От теории к практике - подключим 8-ми разрядный модуль к плате Arduino Uno по указанной ниже схеме:

Для отображения символов используется несколько функций из подключаемой библиотеки LedControl.h. Разберем каждую из этих функций по порядку, начнем с функции setDigit().

Прототип объявления функции для отображения числа и передаваемые функции аргументы:

setDigit(int addr, int digit, byte value, boolean dp);

Где -

i nt addr - адрес модуля на шине SPI 0 SPI начинается с нуля)

int digit - 0 , 7

byte value - значение(число от 0 до 9) которое нужно отобразить в разряде номер которого указан в параметре int digit

boolean dp - int digit . Если параметр равен true то точка отобразится, если false то точка не отобразится.

Прототип объявления функции для отображения символа и передаваемые функции аргументы:

setChar(int addr, int digit, char value, boolean dp);

i nt addr - адрес модуля на шине SPI для которого вызывается функция, если модуль один - то этот параметр равен 0 (по умолчанию адресация устройств на шине SPI начинается с нуля)

int digit - порядковый номер разряда в модуле индикации, по умолчанию для многоразрядных индикаторов нумерация разрядов начинается с крайнего правого разряда, соответственно номер крайнего правого разряда равен 0 , а номер крайнего левого разряда в нашем случае равен 7

char value - символ, который должен отобразиться в разряде номер которого задан параметром int digit

boolean dp - этот параметр отвечает за отображение точки у разряда номер которого указан в параметре int digit . Если параметр равен true то точка отобразится, если false то точка не отобразится.

Отдельным моментом стоит упомянуть, что функция setChar() может отобразить только ограниченный набор символов, таких как:

  • 0 1 2 3 4 5 6 7 8 9 цифра отображается как символ
  • A a
  • B b
  • С с символ отобразится в нижнем регистре
  • D d символ отобразится в нижнем регистре
  • E e символ отобразится в верхнем регистре
  • F f символ отобразится в верхнем регистре
  • H h символ отобразится в нижнем регистре
  • L l символ отобразится в верхнем регистре
  • P p символ отобразится в верхнем регистре
  • - знак "минус"
  • . , отображение точки
  • _ символ подчеркивания
  • <Пробел> установить символ пробела

В тестовом скетче можно поставить задачу такого плана:

  1. Отобразить поочередно цифры от 1 до 8 без точки
  2. Заполнить цифрами от 1 до 8 все разряды модуля индикации, плюс отобразить все точки указаных разрядов
  3. Отрисовать поразрядно массив с заранее закодированными в двоичном коде символами, в результате должно получиться "Arduino rules!!!"

Из-за ограниченного набора символов функция setChar() не подходит для тестового скетча, так как она не сможет нормально отрисовать фразу указанную в пункте 3. Вместо этой функции мы будем использовать функцию setRow() . Итак... функция setRow() уже была нами испытана в в статьях про изучение Led матриц 8х8, давайте вновь опишем прототип вызова и параметры данной функции.

Прототип объявления функции setRow() и передаваемые функции аргументы:

setRow(int addr, int row, byte value);

i nt addr - адрес модуля на шине SPI для которого вызывается функция, если модуль один - то этот параметр равен 0 (по умолчанию адресация устройств на шине SPI начинается с нуля)

int row - порядковый номер разряда в модуле индикации, по умолчанию для многоразрядных индикаторов нумерация разрядов начинается с крайнего правого разряда, соответственно номер крайнего правого разряда равен 0 , а номер крайнего левого разряда в нашем случае равен 7

byte value - значение в двоичном формате(пример B00000000, также возможна альтернатива в десятичном и шестнадцатиричном), которым закодирован необходимый символ. Таблица кодирования символов поможет правильно закодировать нужный символ.

Ну и в завершение статьи тестовый скетч и видео, как это работает:

#include "LedControl.h" /* * Подключаем библиотеку LedControl.h * и создаём объект класса LedControl * при этом, 7-ми сегметный дисплей с драйвером MAX72xx * должен быть подключен к плате Arduino следующим образом: * Arduino -> Display Module MAX72xx * Arduino -> Display Module MAX72xx * Arduino -> Display Module MAX72xx * Arduino -> Display Module MAX72xx * Arduino -> Display Module MAX72xx * */ LedControl lc = LedControl(12, 11, 10, 1); //Массив с закодированными символами, //Фраза "Arduino ruLES!!!" byte ar = { B01110111, //A B00000101, //r B00111101, //d B00011100, //u B00010000, //i B00010101, //n B00011101, //o B00000101, //r B00011100, //u B00001100, //l B01001111, //E B01011011, //S B10110000, //! B10110000, //! B10110000 //! }; void setup() { //Устройство(7-ми сегментный дисплей) выводим из спящего режима lc.shutdown(0, false); //Установить яркость дисплея на 8 //Всего возможных режимов яркости от 0 до 15 lc.setIntensity(0,8); //Очистить дисплей lc.clearDisplay(0); } void loop() { //Простейший перебор чисел от 1 до 8 по разрядам for(int i = 0, j = 7; i < 8, j >= 0; i++, j--) { lc.setDigit(0, j, byte(i + 1), false); delay(400); lc.clearDisplay(0); } //Перебор чисел без очистки экрана for(int i = 0, j = 7; i < 8, j >= 0; i++, j--) { lc.setDigit(0, j, byte(i + 1), true); delay(400); } lc.clearDisplay(0); //Отрисовка фразы "Arduino ruLES!!!" int n = 0; for(int i = 0; i < 2; i ++) { for(int j = 7; j >= 0; j --) { if(n > 6 && !(i % 2)) { continue; } else { lc.setRow(0, j, ar[n]); delay(400); n ++; } } lc.clearDisplay(0); } delay(400); lc.clearDisplay(0); }


Пожалуйста, включите javascript для работы комментариев.

PeakCurrent=(8 x LedCurrent) + MAX72XX-Supply

PeakCurrent=(8 x 20mA) + 10mA = 170mA

Плата имеет отверстия для установки штыревого разъема - с одной стороны для подключения к контролеру, с другой - для подключения еще такого же индикатора. Получается паравозиком друг к дружке можно подключить до 15 таких устройств (вроде так если я чего не напутал). Подключение - 5 проводов: 3 провода управление, 2 провода питание.
Мне разъем не нужен, потому я индикатор подключил припаяв куском IDE шлейфа - очень дешевый и гуманный способ продления «жизни» старым компьютерным комплектующим.
Платформа работает на базе Arduino и для работы экрана была использована библиотека «LedControl.h»
Библиотека достаточно простая, имеет некоторые ограничения на отображение символом, но на то она и библиотека;) Описание и возможности библиотеки можно прочесть .
Библиотека леко устанавливается через Arduino IDE, там же в примере LCDemo7Segment можно подсмотреть подключение и вывод информации на индикатор.
Все просто и красиво если бы небольшой казус. У меня индикатор работал как то не стабильно. При изменении информации на экране могли хаотично зажигаться какие то сторонние сегменты или же индикатор мог просто отключиться. Я долго не мог понять в чем дело. Пересмотрел и переписал код, перемерил напряжение питания и сигналов - все было в норме. В коде я уменьшил частоту вывода информации на экран - это помогло, экран работал стабильнее. Но все-равно в какой то момент экран мог отключиться. У меня уже было желание выбросить этот экран и поставить старый проверенный ЖК 16х2.
Сегодня утром на свежую голову я еще раз почитал описание и обратил внимание на схему подключения. Вернее на часть текста:
Both capacitors must be placed as near as possible to the V+ and the Gnd pins of the MAX72XX.
На моей плате был лишь один керамический конденсатор.


Прозвонив и выяснив полярность цепи питания к которой подключен этот конденсатор, я паралельно ему подпаял первый попавшийся электролитический конденсатор (47mF x 50v).


Экран заработал отлично без малейших сбоев и выключений. Эврика!!! ©
Вот уже весь день экран работает на максимальной яркости и без задержек обновления, а мой проект движется к завершению.
Потому имейте ввиду если будете использовать аналогичный контролер и возможно такие же казусы, теперь Вы осведомлены и вооружены.

Товар не предоставлен магазином, потому пришлось покупать за свои без применения П. 18.

Всем отличного здоровья и минимального delay.

При таком подходе, для вывода числа с любым количеством разрядов используется всего 2 цифровых выхода Arduino.

Для примера будем выводить на индикаторы количество секунд, прошедших с момента старта работы.

Исходные компоненты

Принцип работы

Семисегментный индикатор - это просто набор обычных светодиодов в одном корпусе. Просто они выложены восьмёркой и имеют форму палочки-сегмента. Можно подключить его напрямую к Arduino, но тогда будет занято 7 контактов, а в программе будет необходимо реализовать алгоритм преобразования числа из двоичного представления в соответствующие «калькуляторному шрифту» сигналы.

Для упрощения этой задачи существует 7-сегментный драйвер. Это простая микросхема с внутренним счётчиком. У неё есть 7 выходов для подключения всех сегментов (a, b, c, d, e, f, g pins), контакт для сбрасывания счётчика в 0 (reset pin) и контакт для увеличения значения на единицу (clock pin). Значение внутреннего счётчика преобразуется в сигналы (включен / выключен) на контакты a-g так, что мы видим соответствующую арабскую цифру.

На микросхеме есть ещё один выход, обозначенный как «÷10». Его значение всё время LOW за исключением момента переполнения, когда значение счётчика равно 9, а его увеличивают на единицу. В этом случае значением счётчика снова становится 0, но выход «÷10» становится HIGH до момента следующего инкремента. Его можно соединить с clock pin другого драйвера и таким образом получить счётчик для двузначных чисел. Продолжая эту цепочку, можно выводить сколь угодно длинные числа.

Микросхема может работать на частоте до 16 МГц, т.е. она будет фиксировать изменения на clock pin даже если они будут происходить 16 миллионов раз в секунду. На той же частоте работает Arduino, и это удобно: для вывода определённого числа достаточно сбросить счётчик в 0 и быстро инкрементировать значение по единице до заданного. Глазу это не заметно.

Подключение

Сначала установим индикаторы и драйверы на breadboard. У всех них ноги располагаются с двух сторон, поэтому, чтобы не закоротить противоположные контакты, размещать эти компоненты необходимо над центральной канавкой breadboard’а. Канавка разделяет breadboard на 2 несоединённые между собой половины.

    16 - к рельсе питания: это питание для микросхемы

    2 «disable clock» - к рельсе земли: мы его не используем

    3 «enable display» - к рельсе питания: это питание для индикатора

    8 «0V» - к рельсе земли: это общая земля

    1 «clock» - через стягивающий резистор к земле. К этому контакту мы позже подведём сигнал с Arduino. Наличие резистора полезно, чтобы избежать ложного срабатывания из-за окружающих помех пока вход ни к чему не подключен. Подходящим номиналом является 10 кОм. Когда мы соединим этот контакт с выходом Arduino, резистор не будет играть роли: сигнал притянет к земле микроконтроллер. Поэтому если вы знаете, что драйвер при работе всегда будет соединён с Arduino, можете не использовать резистор вовсе.

    15 «reset» и 5 «÷10» пока оставим неподключенными, но возьмём на заметку - нам они понадобятся в дальнейшем

Контакты 3 и 8 на индикаторе обозначены как «катод», они общие для всех сегментов, и должны быть напрямую соединены с общей землёй.

Далее следует самая кропотливая работа: соединение выходов микросхемы с соответствующими анодами индикатора. Соединять их необходимо через токоограничивающие резисторы как и обычные светодиоды. В противном случае ток на этом участке цепи будет выше нормы, а это может привести к выходу из строя индикатора или микросхемы. Номинал 220 Ом подойдёт.

Соединять необходимо сопоставляя распиновку микросхемы (выходы a-g) и распиновку индикатора (входы a-g)

Повторяем процедуру для второго разряда

Теперь вспоминаем о контакте «reset»: нам необходимо соединить их вместе и притянуть к земле через стягивающий резистор. В последствии, мы подведём к ним сигнал с Arduino, чтобы он мог обнулять значение целиком в обоих драйверах.

Также подадим сигнал с «÷10» от правого драйвера на вход «clock» левого. Таким образом мы получим схему, способную отображать числа с двумя разрядами.

Стоит отметить, что «clock» левого драйвера не стоит стягивать резистором к земле, как это делалось для правого: его соединение с «÷10» само по себе сделает сигнал устойчивым, а притяжка к земле может только нарушить стабильность передачи сигнала.

Железо подготовленно, осталось реализовать несложную программу.

Программирование

7segment.pde #define CLOCK_PIN 2 #define RESET_PIN 3 /* * Функция resetNumber обнуляет текущее значение * на счётчике */ void resetNumber() { // Для сброса на мгновение ставим контакт // reset в HIGH и возвращаем обратно в LOW digitalWrite(RESET_PIN, HIGH) ; digitalWrite(RESET_PIN, LOW) ; } /* * Функция showNumber устанавливает показания индикаторов * в заданное неотрицательное число `n` вне зависимости * от предыдущего значения */ void showNumber(int n) { // Первым делом обнуляем текущее значение resetNumber() ; // Далее быстро «прокликиваем» счётчик до нужного // значения while (n-- ) { digitalWrite(CLOCK_PIN, HIGH) ; digitalWrite(CLOCK_PIN, LOW) ; } } void setup() { pinMode(RESET_PIN, OUTPUT) ; pinMode(CLOCK_PIN, OUTPUT) ; // Обнуляем счётчик при старте, чтобы он не оказался // в случайном состоянии resetNumber() ; } void loop() { // Получаем количество секунд в неполной минуте // с момента старта и выводим его на индикаторы showNumber((millis() / 1000 ) % 60 ) ; delay(1000 ) ; }

Результат

Подключаем контакт 2 с Arduino к контакту clock младшего (правого) драйвера, контакт 3 - к общему reset’у драйверов; разводим питание; включаем - работает!

Проект основан на 7-ми сегментном двойном дисплее и плате Arduino Diecimila.

Реализован счетчик от 20. Когда счетчик завершает работу, загорается светодиод на 13 пине. В проекте не использовано никакого дополнительного оборудования. Для реализации счетчика на двух дисплеях вам понадобится 9 пинов на плате.

Необходимы детали для проекта

Для проекта вам понадобится следующее:

  • Плата Arduino (какая -не принципиально);
  • Двойной 7-ми сегментный дисплей или два отдельных 7-ми сегментных дисплея;
  • 2 резистора (номинал зависит от вашего дисплея);
  • Макетная плата;
  • Около 50 см провода.

Инструменты вроде отверток, паяльника для распайки коннекторов, может пригодиться изолента и т.п.

Что такое мультиплексинг?

Мультиплексинг - это управление большим количеством светодиодов с помощью нескольких пинов.

Если два или больше 7-сегментных дисплея подключить совместно, примером того, что они отобразят будет: 00, 11, 22, 33, 44, 55, 66, 77, 88, 99.

В данном случае мы контролируем каждую землю (GND) отдельно и получаем мультиплексинг.

Мы будем включать дисплеи каждые 0.5 миллисекунды, что обеспечит управление каждым отдельно.

Это очень полезное решение, когда вы создаете проект с большим количеством компонентов и ограниченным количеством пинов на плате управления.

В данном примере мы будем управлять двумя семисегментными дисплеями с помощью 9 пинов. Без мультиплексинга нам пришлось бы использовать в данном случае 14 пинов.

Подключение 7-ми сегментного двойного дисплея

Проект не самый простой. Для реализации вам понадобятся базовые знания в электронике.

Для начала вам надо правильно распаять коннекторы на задней части дисплея. Можно это реализовать и на макетной плате. Дальше уже можно подключать дисплей к Arduino следующим образом:

Segment A к пину 7

Segment B к пину 8

Segment C к пину 4

Segment D к пину 3

Segment E к пину 2

Segment F к пину 6

Segment G к пину 5

Gnd1 через резистор к пину 11

Gnd2 через резистор к пину 9

Программирование Arduino

Пришло время написания программы.

Основные пояснения вынесены в коде. Общая структура следующая:

Сначала происходит инициализация пинов и переменных.

В теле функции Void Setup всем пинам присваивается значение Output - работа в режимы передачи данных на выход.

Также там куча циклов For Loop, которые используются, когда светодиоды включены.

По просьбе трудящихся решил я рассказать о замечательной вещи под названием 7-ми сегментный светодиодный индикатор. Для начала что это такое. Вот такая вот штука. Это один разряд, так же бывают двух разрядные, трех и четырех разрядные. Видел еще шести разрядные. После каждого разряда стоит десятичная точка. Если разрядов четыре, то чаще всего после второго разряда можно встретить двоеточие для индикации секунд, при выводе времени. Разобравшись с железками давайте перейдем к изучению схемы. Что вообще такое динамическая индикация и зачем она нужна. Так-как индикатор 7-ми сегментный, то для отображения цифры используется всего 7 сегментов. Обозначаются они всегда латинскими буквами A, B, C, D, E, F, G и DP Смотрим картинку. Под каждым сегментом расположен светодиод. Все светодиоды одним концом объеденены. Либо анодами либо катодами, а противоположные концы выведены наружу. Легко заметить что для отображения цифры необходимо использовать 8 выводов. Один общий и семь для сегментов. Если это касается одного разряда, то тут думать не о чем, просто вешаем все на один порт. А если разрядов четыре? Восемь помножим на четыре будет тридцать два. О... Да над таким индикатором 32 мега будет одна корпеть. Так дело не пойдет. Есть два решения. Наша с вами динамическая индикация либо статическая. Что бы дальше разбираться, давайте посмотрим схему включения индикатора.

Данная схема подразумевает динамическую индикацию. Да что я все динамическая да статическая. В чем разница?. Статическая индикация - это когда мы задали каждому разряду по своей цифре и она постоянно горит, а динамическая - это когда мы выводим цифру в первый разряд, потом его гасим и выводим во второй разряд, потом его гасим и выводим в третий разряд и так далее пока не закончатся разряды. После последнего разряда переходим опять к первому и так по кругу. Если это делать медленно то можно будет лицезреть цифровую бегущую строку, а если увеличить скорость к примеру до 50 Гц, то уже мерцания глаз не увидит. Вот таким образом и работает динамическая индикация. Давайте теперь разберем схему. Слева МК ATmega8 за ней на порту D висит микросхема 74ALS373. Зачем она нужна? Дело в том что индикатор это просто 8 светодиодов собранных в некую матрицу. То есть индикатор можно представить в виде линейки из 8 светодиодов. А как известно светодиоды кушают по отношению к МК ого го сколько. Конечно не возбраняется подключение напрямую, но лучше поставить между МК и индикатором какой-нибудь ретранслятор. Вот для этих целей я и решил использовать 8-и разрядный буфер с защелкой. Почему именно его. С учетом того что индикатор я использую с общим анодом, то есть для задачи цифры активный уровень 0, то можно было бы смело использовать микросхему ULN2003A(7 транзисторных сборок по схеме Дарлингтона) и не париться с буфером, но... Но в том что ULN2003A имеет на борту только NPN транзисторы и я могу использовать индикатор только с общим анодом, а если нужно поставить с общим катодом? Вот тут и поможет буфер, так как что я туда напишу, то и будет на выходе. Хочешь 0, хочешь 1. Управляющие ножки подключены в режиме транслятора. То есть буфер выводит на выход тоже самое что и на входе. Аля псевдо гальваническая развязка. За буфером следуют токоограничивающие резисторы. Помним, это светодиоды и без резисторов сгорят. Номинал резисторов нужно подбирать чуть меньше чем допустимо. Дело в том что динамическая индикация выводит символы с некой частотой и она с родни ШИМу, то есть чем выше частота, тем выше так сказать контрастность. И при максимально комфортной контрастности цифры будут светить чуть тускнее. По этому резисторы нужно брать чуть меньшего номинала. Я использовал 360Ом только потому что у меня такие были в наличии. Далее после резисторов наш индикатор. С другой стороны, где аноды, я подключил первые четыре разряда порта С. Так, со схемой вроде разобрались. Теперь давайте обсудим алгоритм программы. Для того чтобы поочередно включать разряды индикатора, напишем отдельную функцию и будем ее бесконечно вызывать в основном теле программы. Конкретнее, функция будет получать число от 0 до 9999, рабирать его на разряды и потом выводить каждый разряд на своем месте. Если число имеет количество разрядов меньше 4, то пустышки слева будем заполнять нулями. Ровняемся по правому краю. Бегать по разрядам будем слева направо. Чтобы было видно какие-нибудь действия, то мы используя прерывания от счетчика, раз в секунду будем увеличивать выводимое число на единицу. Так задача поставлена, к бою. #define F_CPU 7372800UL // Частота кварца #include #include #include volatile unsigned int test = 9980; // Переменная для вывода на индикатор ISR(TIMER1_COMPA_vect) // Обработчик прерывания по совпадению таймера 1 { test++; // Увеличить выводимое число if(test > 9999) test = 0; // Если вышел за пределы четырех разрядов, обнулить TCNT1H=0x00; // Сброс регистра TCNT1L=0x00; // счета } void dig_out(int num); // Объявление функции вывода на индикатор int main(void) { DDRC = 0x0F; // Настройка портов DDRD = 0xFF; // для работы с индикатором Порт С для разрядов, Порт D для цифр TCCR1A=0x00; // Настройка таймера TCCR1B=0x04; TCNT1H=0x00; TCNT1L=0x00; OCR1AH=0x70; OCR1AL=0x80; TIMSK=0x10; sei(); // Разрешение прерываний while(1) { dig_out(test); //Постоянно вызываем функцию вывода текущего числа } } void dig_out(int num) // Функция для вывода на индикатор 4-х разрядов { unsigned char i = 0; // Переменная счетчика unsigned char raz = 1; // Номер разряда unsigned char dig_num = {0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10}; // Коды цифр для индикатора с общим анодом unsigned char dig = {0, 0, 0, 0}; // Массив для значения разряда if(num { dig =0; dig =0; dig =0; } if(num // Для заполнения нулями левых разрядов { dig =0; dig =0; } if(num // Для заполнения нулями левых разрядов { dig =0; } while(num > 999) // Получение количества тысяч { dig++; num -= 1000; } while(num > 99) // Получение количества сотен { dig++; num -= 100; } while(num > 9) // Получение числа десятков { dig++; num -= 10; } dig = num; // Получения количества единиц while(raz // Крутимся пока не заполним все 4 разряда { PORTC = raz; // Выбираем разряд PORTD = dig_num]; // Выводим цифру raz = raz// Сдвигаемся на следующий разряд i++; // Увеличиваем индекс следующей цифры _delay_ms(1); // Задержка 1 мс } } Вот и весь код. Расписывать его не буду так как он имеет комментарии к каждой строке. Ниже можно скачать архив с проектом под AtmelStudio6.2 Если все же возникнут вопросы, то милости просим на форум. Ну и для самых привередливых ниже видео все этой балалайки))).