Декодер для 7-сегментного индикатора

7-сегментный индикатор

7-сегментный индикатор - один из самых популярных и простых видов отображение арабских цифр и других символов. Запатентованный еще в 1910 Фрэнком Вудом, он остается востребованным и по сей день.

Так как чаще всего в подобных индикаторах используются светодиоды, а как известно у них есть катод и анод, следовательно, и сами дисплеи делятся на 2 подтипа: с общим катодом и с общим анодом. Отличия минимальные, но иногда есть случаи, когда есть один более приоритетный вариант.

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

Допустим, для примера мы возьмем дисплей с общим катодом. Давайте попробуем вывести несколько цифр на дисплей. Для начала возьмем 0; для того, чтобы вывести нам надо подключить пины 7, 6, 4, 2, 1, 9 (a, b, c, d, e, f - соответственно) к "+" питания, и не забываем про резисторы, чтобы светодиоды не перегорели; если вы используете питание 5V, то будет достаточно подключить резистор на 330Ohm от пина 3, 8 к GND. И вот, на индикаторе можно наблюдать 0. Также можно вывести 1; подключаем пины 6, 4 (b, c) к положительному контакту питания и можно видим единичку на дисплее. Остальные цифры выводятся аналогично.

Возникающие проблемы

Мы разобрались, как можно выводить различные символы на индикатор, но представим, что у нас есть какое-то электронное устройство, которое должно считать числа, и для удобства мы хотим использовать индикатор, но вот незадача, у нас осталось всего 4 свободных I/0 линии, или мы намеренно хотим это оптимизировать, чтобы не писать код на микроконтроллере для представления цифр на экране или более удобным для нас способом. Напомню, при простом подключении необходимо 8 таких линий.

Кодирование

Так как самая привычная для нас система счисления это десятичная, то будем использовать ее и цифры от 0 до 9. При желании также можно продолжить и для 16-ричной системы. Поскольку у нас все строится пока что на 5V логике, то было бы странно не использовать двоичную систему счисления. У нас есть 10 цифр, следовательно, нам нужно минимум 4 бита для представления всех возможных вариантов. Для удобства предлагаю сделать таблицу.

Decimal

0

1

2

3

4

5

6

7

8

9

Binary

0000

0001

0010

0011

0100

0101

0110

0111

1000

1001

Представим, что у нас есть 4-bit шина, по которой наше устройство передает сигнал в двоичном представлении. Теперь надо декодировать и передать его на дисплей.

Декодирование

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

Пока что мы будем использовать простую шину из 4 проводов, по каждому из которых будет передаваться сигнал. В нашем случае 5V - логическая единица, а GND - логический нуль. В таблице первый столбец только для ясности, какую цифру мы хотим отобразить. Исходя из этой таблицы нам надо создать устройство, которое при входных значениях в шине, на выходе выдавало бы 7 значений для индикатора. Для этого, мы будем использовать операции над булевыми значениями: конъюнкция (и, &), дизъюнкция (или, |), отрицание (не, ¬). Итак, приступим к созданию цепи логических вентилей.

Цепь для сегмента 'а'

Из таблицы истинности видно, что сегмент а должен быть включен всегда, кроме цифры 1 и 4. Для упрощения можно сделать так, чтобы логическая единица была только в этих 2 состояниях, и на выход добавить логическое НЕ. Тогда у нас всегда будет 1, кроме 2-ух состояний. Вот схема:

Я добавил дополнительную инвертированную шину для удобства и наглядности.

На выходе должен быть логический 0 при входных значениях 0 0 0 1 и 0 1 0 0 (на линиях 3, 2, 1, 0 соответственно). Поэтому я взял не инвертированную первую линию, а все остальные инвертированные, и получилось, что 0 0 0 1 трансформируется в 1' 1' 1' 1 ( ' - инвертированный сигнал), после все эти сигналы группируются в один общий, который идет в вентиль ИЛИ-НЕ, который на конце и инвертирует логическую 1 в 0, чтобы при этих входных параметрах сегмент а не был включен. То же самое проделывается для другого случая: 0 1 0 0 преобразуется в 1' 1 1' 1' и также идет в тот же вентиль ИЛИ-НЕ, как и при первом случае.

По такой схеме делаются остальные модули для других сегментов индикатора. В итоге у вас должно получиться нечто подобное:

Улучшение

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

Для начала, взглянем на таблицу истинности. Можно заметить, что для сегмента е больше логических 0, так что для него, можно не инвертировать выход (!! - двойное отрицание, то есть ничего не меняем). Также использование одного и того же модуля для цифры 1 происходит 4 раза! А для цифры 9 можно не делать модуль вообще (количество повторений одного модуля для цифры вынесено в последнюю колонку). Это существенная трата пространства и логических вентилей. После реинжинеринга, на выходе будет примерно такая схема:

Реализация

Есть три способа воплотить данный декодер в жизнь.

  1. Из готовых микросхем логических вентилей, например серия микросхем 74HCxx. Данный способ самый простой, не самый практичный, но вполне допустимый. Также его будет просто модернизировать для n-разярдных индикаторов. И отлично подходит для тестов.

  2. Более сложный, но более "крутой" способ, создание всех логических вентилей на ТТЛ, отлично подойдут транзисторы BC546 и его комплементарная пара BC556. Этот способ потребует дополнительного создания схемы на транзисторах, для их корректной работы. Будет занимать больше пространства, но можно сделать прозрачный корпус и поставить на полочку. Ведь применение ТТЛ в наше время, дело совсем незаурядное.

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

Эпилог

В конце, хотелось отметить, что данный декодер являются не плохой практической работой для тренировки создания логических схем и для понимаю как устроенные простые электронные устройства. Идейным вдохновителем для создания данного исследования стал Ben Eater.

Комментарии 48

    0
    В этом деле не всё так просто, потому что при смене цифр на параллельной шине будут возникать промежуточные состояния и, как следствие, могут мигать лишние сегменты (например, при переходе от 1 к 2 будет некрасиво выглядеть мигание сегмента f, если второй разряд будет не поспевать за первым и на шине будет кратковременно образовываться 0). Также и длина пути до разных сегментов разная, что не очень хорошо. Как упражнение в минимизации булевых функций описанное нормально, но в реальной жизни желательно всё-таки стробирование данных.
      +2

      Как по мне — для начинающих как раз хорошо показана суть. А остальное — это уже для второго урока :)

        +7

        В статье описана попытка минимизации булевых функций, и ни слова не сказано о нормальных формах, СДНФ, СКНФ и картах Карно. Куда после это статьи читать начинающему? Какая суть показана?

        +4

        В тегах стоит схемотехника. Оптимизация булевых функций в ней проработана- до 5ти термов оптимизируются на картах Карно вручную матаматически строго. Где это все?

          0
          Для сегмента «а» таблица для карт Карно имеет вид
          x1=0 x1=1 x1=1 x1=0
          x0=0 x0=0 x0=1 x0=1
          x3=0 x2=0| 1 1 1 0
          x3=1 x2=0| 1 x x 1
          x3=1 x2=1| x x x x
          x3=0 x2=1| 0 1 1 1
          где x- факультативные значения (не заданы в целевой функции, и могут быть выбраны нами по произволу)
          давайте возьмем их такими:
          x1=0| x1=1 x1=1 x1=0
          x0=0| x0=0 x0=1 x0=1
          x3=0 x2=0| 1 1 1 0
          x3=1 x2=0| 1 1 1 1
          x3=1 x2=1| 1 1 1 1
          x3=0 x2=1| 0 1 1 1
          тогда видим, что в центре у нас большой крестик, образованный пересчением столбца с X1=1 и строки с Х3=1, в котором все значения целевой функции равны 1. то есть, наша итоговая функция имеет вид X1 or X3 or Something. оставшиеся вне крестика две единички тоже можно объединить с соседними
          x1=0 x1=1 x1=1 x1=0
          x0=0 x0=0 x0=1 x0=1
          x3=0 x2=0| 1 1 1 0
          x3=1 x2=0| 1 1 1 1
          x3=1 x2=1| 1 1 1 1
          x3=0 x2=1| 0 1 1 1
          и тогда для нашего Something получается выражение
          (!x2 and !x0) or (x2 and x0)
          в итоге для нашего сегмента получаем вот такую логическую функцию:
          a = X1 or X3 or (!x2 and !x0) or (x2 and x0).

          Вся фишка карт Карно в том, что любые две соседние ячейки отличаются только в одном терме (бите), и если в двух соседних ячейках находится одинаковое значение- то от соответствующего переменного бита ничего не зависит и он для данных значений может быть исключен. А если есть две соседних пары таких парных ячеек- то исключается еще один бит, и так далее. И для совсем одаренных можно составить трафаретики из картона, которые можно просто накладывать на таблицу истинности логической функции, и если в трафаретике видны только единички (или только нули)- то сразу видно, во что сворачивается покрытая трафаретом область. но если термов 5 или более- то уже нарисовать такую красивую карту, как в рассмотренном случае- нельзя, нужно рисовать или в трех измерениях, или раскидывать как-то, и метод становится сложно применим.
            0
            спасибо конечно, в том, что дали удостоверится в моих расщетах. Я хотел рассказать как я делал декодер, но в статью решил не включать карты Карно, решив, что стоит продолжить в следуйщей статье.
        +2

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

          +1

          Не менее 11 вентилей лишние, если я правильно ошибаюсь.

          +2

          3 пункт неплохо бы дополнить словами 176ид2 и CD4511

            0
            Можно еще плисину взять, или диодный сделать
              +1
              Вот!
              Диоды — сила.
              +2
              Кто-нибудь может ответить, почему нет ни одного дешифратора/драйвера, который бы отображал шестнадцатеричные цифры после 9? Все популярные микрухи просто гасят все разряды индикатора, даже в этой статье инорируют оставшиеся 6 комбинаций. Что мешало сделать их отображение, даже если использоваться будет редко? Печально брать ПЛИС или МК для такого элементарного действия.
                +1
                DM9368 была для этого, еще что-то менее известное попадалось.
                  0
                  Спасибо, я про такую не знал. Даже на али есть, отлично!
                  0
                  Для не больших индикаторов использовал 74HC595 управление кучей индикаторов через SPI.
                    0
                    Как вариант да, но это всегда плюсом МК идёт.
                    0
                    Потому что нет общепринятого способа отображения этих символов.
                    Как минимум, у нас был 490ИП2 — индикатор со встроенным дешифратором.
                      +2


                      Какие ещё могут быть варианты?
                        0
                        С — нижними сегментами.
                          +1
                          g как отраженная от вертикали девятка, h- тут очевидно.
                            0
                            Вы это серьезно?
                        0
                        490ИП2 — у неё вроде вместо шестнадцатеричных символов свои особенные?
                      0
                      Нередко проще MAX7219 ставить. Если свыше четырех разрядов, то точно проще.
                        0
                        Иногда динамическая индикация не вариант, например, когда рядом радиотракт.
                          0
                          На экране любого смартфона индикация динамическая, и радиотракт рядом.
                          Вы вообще о чем? Какая связь между 800Гц MAX7219 и радиотрактом?
                          Или Вы индикаторы со светодиодными лампами попутали, где амплитуда напряжения на порядок больше, а ток больше в разы? Но даже здесь проблема сильно преувеличена. По крайней мере никакого влияния светодиодого освещения на качество WiFi или мобильной связи я никогда не замечал.
                      +3
                      Способ 4. Поставить К176ИД2 / К155ПП5.
                      Вероятно, в их справочных листках и схема будет пооптимальнее.

                      А способ 2 правильнее колхозить на мосфетах, типа bs170, 2n7002.
                        0
                        В третьем пункте у автора указано: «стоит отметить, что уже давно выпускаются подобные микросхемы, и это будет не слишком целесообразно.»
                        +6
                        На практике можно взять MAX7219/MAX7221 и подключить по SPI (3 провода, MISO не нужен).
                        Бонусом будет возможность их каскадирования, экономия места на плате и софтовая+аппаратная регулировка яркости из коробки.
                          0
                          Это в теории можно. А на практике — фиг их достанешь. У нас, например в наличии ни в одном магазине нет. Только под заказ. И цена что-то вроде 700-1200р. Тогда как BCD и сдвиговых регистров — полно по 5-6р за штуку.

                          А нет, вру MAX7219 по 280 в DIP, MAX7221 по 390.
                            +1
                            На алиэкспрессе покупаются без проблем хоть в DIP корпусе, хоть в SOP
                              0
                              На алиэкспрессе за такие деньги можно их десяток заказать с бесплатной доставкой. И еще останется. Только что посмотрел. Партия из пяти штук MAX7219 с бесплатной доставкой от 110 рублей за SOP и от 134 рублей за DIP. Получается от 11 до 14 рублей за штуку.
                            +1
                            Данная схема полностью рабочая, но в ней много повторяющихся элементов, и она будет занимать слишком много места, даже если делать отдельную интегральную схему. Поэтому ее стоит доработать.


                            Оптимизировать вам помогут карты Карно.
                              0
                              Конечно, понятно что в статье приведено хард-решение, но было бы интересно сравнить и с софт-решением, когда у нас всё же есть свободные выводы у контроллера (тем более, что это обычно просто надо взять другой корпус того же самого MCU). Особенно интересно сравнить стоимость разных решений…
                                +3
                                а что там сравнивать? быстродействие? энергопотребление? занимаемую площадь на плате?
                                это просто хард-решение, которое позволяет вместо 8ми ног контроллера забрать под управлением сегментом только 4 ноги. Лет дцать назад, когда логическая часть собиралась из рассыпухи вручную- это было актуально. Сейчас на каждую такую задачу есть специализированная микросхема и с практической точки зрения такая реализация только ухудшает конечное изделие- вместо разводки десятка дорожек под запайку одной микрухи с 14ю ногами нужно разводить сотню дорожек под запайку трех десятков вентилей с пересечениями, что вдесятеро удорожает производство. Но знать и уметь- полезно, ибо гимнастика для мозгов, как жим лежа для грудака- в жизни нафиг не надо, но сайдэффекты- приятные.
                                  0
                                  Ну вот только что (месяц назад) использовал 3-местный 7-сегментный индикатор в связке с stm32f042g6. Нужно было максимально удешевить — обошелся вообще без всего, даже резисторы не вставил, работает вполне нормально, процессор практически не занимает, можно регулировать яркость (шим получился, честно не хотел, но так уж вышло)…
                                  А вы пишите — микруха, разводка…
                                    0
                                    ну, у Вас же не было задачи минимизировать число ног, занятых светодиодами- вот Вы и обошлись без микрухи и разводки. И индикатор Ваш потреблял по 50мА на вход, а не по 300, и питание индикатора от 5В, а не от 24В. под каждую задачу- свое решение.
                                +11

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

                                  +4
                                  Ни разу не видел схемы с одним резистором «от пина 3, 8 к GND». А вот схем с восьмью резисторами видел великое множество. Автор точно «в теме»?
                                    –3
                                    У тебя есть схема: источник питания -> резистор -> светодиод -> обратно в источник питания. То если ты поменяешь резистор и светодиод местами, что-то изменится? -Нет. Поэтому не вижу смысла подключать «миллионами» резисторов это все.
                                      +4
                                      Оно то так, но только до тех пор пока 1 светодиод. А тут их 7. И резисторов тоже нужно 7. Иначе яркость единицы будет в 4 раза больше яркости восьмёрки.
                                      0
                                      А я наоборот, чаще встречал схемы с одним резистором, чем с восемью. Выглядит это отвратно, конечно.
                                      +2
                                      Ну зачем так сложно? Проще использовать однократно программируемые ПЗУ типа К155РЕ3 в качестве дешифратора на все случаи жизни для 7-сегментных индикаторов (http://nauchebe.net/2010/05/deshifratory-na-mikrosxemax-k155rez/). Вывести на индикатор можно все, что хочешь, в том числе и символы от A до F для 16-ричного исчисления.
                                        +3
                                        Есть же специализированные микросхемы давно
                                        Тот же MAX7219 про который выше писали или TM1637/38.
                                        Ну на крайний случай, сдвиговые регистры 495
                                        Зачем это хардкор на россыпухе? Чтобы деменция не развивалась?
                                          +1
                                          Видимо в качестве головоломки
                                        0
                                        А смысл городить такой огород?
                                        Не проще ли воспользоваться TM1637, и небольшим кодом?
                                        Причем, будет достаточно всего двух проводов (синхро и даты)
                                          0
                                          А я б заколхозил сдвиговый регистр. На один сегмент — один регистр.
                                          Из плюсов: во первых можно выводить любой возможный символ, а не ограничеваться цифрами, во вторых для управления любым количеством семисегментных индикаторов (восьми, если считать ещё и точку) достаточно трёх ног микроконтроллера.
                                            +1
                                            Еще больше (moar) декодеров семисегментных индикаторов на Хабре!

                                            habr.com/ru/post/453544

                                            habr.com/ru/post/548288

                                            habr.com/ru/post/535936
                                              0

                                              Я смог сделать за 31 NAND гейт, кто меньше?


                                              vi segment(int x, int y, int z, int w) {
                                                  auto G = [] (int lhs, int rhs) {
                                                      return 1 ^ (lhs & rhs);
                                                  };
                                              
                                                  int xn = G(x, 1);
                                                  int yn = G(y, 1);
                                                  int zn = G(z, 1);
                                                  int xz_and_n = G(x, z);
                                                  int xy_and_n = G(x, y);
                                                  int xn_y_or = G(yn, x);
                                                  int xy_or = G(yn, xn);
                                                  int xz_or = G(zn, xn);
                                                  int zw_or = G(G(w, 1), zn);
                                                  int yn_x_and_z_or = G(zn, xn_y_or);
                                              
                                                  return vi{
                                                          (G(G(xy_or, zw_or), yn_x_and_z_or)),
                                                          (G(xy_and_n, G(G(y, z), xz_and_n))),
                                                          (G(G(xz_or, 1), y)),
                                                          (G(G(G(G(xz_and_n, y), xn_y_or), zw_or), yn_x_and_z_or)),
                                                          (G(G(xn, y), xz_or)),
                                                          (G(G(xy_and_n, G(zn, G(x, w))), xy_or)),
                                                          (G(G(xy_and_n, zw_or), G(zn, y)))
                                                  };
                                              }
                                              

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

                                              Самое читаемое