Программа индикации на многоразрядном семисегментном индикаторе
Как я уже писал в другой статье — АЛГОРИТМ — предшественник программы, и чем продуманнее он будет написан, тем легче будет писать программу.
Назначение переменных:
Давайте посмотрим какие переменные для работы подпрограммы вывода данных на индикатор назначил я:
Data0, Data1 и Data2 — переменные, в которые основная программа записывает вычисленное значение (трехзначное)Data — переменная, в которой записан адрес первой переменной данных — Data0@Data — эта запись означает, что в переменной Data будет храниться адрес первой переменной данных — Data0DataIndex — эта переменная хранит текущий номер переменной данных, которая выводилась на индикацию последней (0, 1 или 2, соответственно для Data0, Data1 или Data2)PortDigits — эта переменная хранит данные о том, какой разряд индикатора зажигался последним
Настройка стека:
Стек настраивается в самом начале основной программы, мы его рассматривать не будем, так как к нашей подпрограмме он не относится
Настройка восьмиразрядного таймера Taimer0:
Taimer0 в подпрограмме используется как средство обеспечивающее динамическую индикацию разрядов индикатора
Настроенный таймер через определенные промежутки времени вызывает прерывание, в результате чего происходит остановка основной программы и осуществляется переход в подпрограмму обработки прерывания. В нашем случае — вызывается подпрограмма вывода данных на индикатор.Как настраивается таймер: Частота переключения разрядов должна быть в пределах 100 Гц для предотвращения мерцания индикаторов при их поочередном зажигании (дело это в принципе индивидуальное, и зависит от особенностей вашего зрения).Тактовая частота микроконтроллера — 1 мГц, или 1 000 000 Гц Устанавливаем внутренний делитель частоты таймера в СК/8 — рабочая частота таймера будет в 8 раз меньше тактовой частоты микроконтроллера Получаем: 1000 000/8 = 125 000 Гц, или 125 кГц — тактовая частота таймера Настраиваем вызов прерывания по переполнению счетчика таймера (счетчик таймера восьмиразрядный и считает до 255, после этого сбрасывается в ноль и вызывается прерывание) Получаем: 125 000/255 = 490 Гц (что соответствует времени приблизительно в 2 миллисекунды) Мы поочередно зажигаем три разряда: Получаем: 490/3 = 163 Гц — разряды индикатора будут переключаться с частотой 163 Гц.
Настройка таймера производится соответствующей настройкой соответствующих регистров таймера.Давайте посмотрим как это происходит в Algorithm Builder:
Инициализация индикатора
Инициализация индикатора — эта фраза подразумевает настройку разрядов портов, к которым подключены выводы индикатора на вывод, а также обнуление переменных данных Data0…2 и запись первоначальных данных в остальные переменные. Процесс инициализации индикатора прописывается в начале основной программы.
Назовем подпрограмму инициализации Ini_Indikator2/Давайте посмотрим этот процесс на примере:
В первой строке разряды порта РВ с 0 по 6 (к которым подключены семь сегментов индикатора) настраиваются на вывод информации (десятичную точку индикатора не используем).Во второй строке разряды порта PD с 0 по 2 (к которым подключены управляющие транзисторы) также настраиваются на вывод.Третьей строкой на выходах порта РВ устанавливается логический ноль — сегменты индикатора погашены для индикаторов с общим катодом).Четвертая строка — обнуляем переменную DataIndexПятая строка — в переменную PortDigits записываем единицуСледующие три строки — обнуляем переменные данных
Теперь нам необходимо куда-то записать двоичные коды цифр которые будут подаваться на разряды порта PB для высвечивания соответствующей цифры на индикаторе.
В статье по программированию работы одноразрядного семисегментного индикатора, мы эти коды записывали программным путем в ОЗУ микроконтроллера. Сейчас мы сделаем по-другому — запишем двоичные коды в теле самой программы.
Для этого создадим таблицу двоичных кодов и присвоим ей имя, к примеру D0_9:
В этой таблице размещены двоичные коды (хотя и записаны в шестнадцатиричной системе) цифр от 0 до 9.
После проделанной нами предварительной работы, разрешаем микроконтроллеру использовать прерывания и переходим к самому главному — подпрограмме вывода данных на многоразрядный индикатор.
Управление семисегментными индикаторами
Схема подключения семисегментного индикатора с кнопкой
В следующем примере переключение чисел на индикаторе будет происходить только при нажатии тактовой кнопки. Дойдя до числа 3, таймер вновь обнулится и будет ожидать повторного нажатия на кнопку. Это довольно простые программы для Ардуино и семисегментного индикатора, для более сложных и интересных программ необходимо уже использовать сдвиговый регистр 74hc595 для Ардуино.
Скетч. Одноразрядный семисегментный индикатор и кнопка
#define A 8 #define B 7 #define C 6 #define D 5 #define E 4 #define F 3 #define G 2 #define BUTTON 12 byte v = 0; void setup() { pinMode(A, OUTPUT); pinMode(B, OUTPUT); pinMode(C, OUTPUT); pinMode(D, OUTPUT); pinMode(E, OUTPUT); pinMode(F, OUTPUT); pinMode(G, OUTPUT); pinMode(BUTTON, INPUT); } void loop() { digitalWrite(A, HIGH); //цифра нуль digitalWrite(B, HIGH); digitalWrite(C, HIGH); digitalWrite(D, HIGH); digitalWrite(E, HIGH); digitalWrite(F, HIGH); digitalWrite(G, LOW); if (digitalRead(BUTTON) == HIGH) { delay(500); v = 1; } while (v == 1) { digitalWrite(A, LOW); //цифра один digitalWrite(B, HIGH); digitalWrite(C, HIGH); digitalWrite(D, LOW); digitalWrite(E, LOW); digitalWrite(F, LOW); digitalWrite(G, LOW); if (digitalRead(BUTTON) == HIGH) { delay(500); v = 2; } } while (v == 2) { digitalWrite(A, HIGH); //цифра два digitalWrite(B, HIGH); digitalWrite(C, LOW); digitalWrite(D, HIGH); digitalWrite(E, HIGH); digitalWrite(F, LOW); digitalWrite(G, HIGH); if (digitalRead(BUTTON) == HIGH) { delay(500); v = 3; } } while (v == 3) { digitalWrite(A, HIGH); //цифра три digitalWrite(B, HIGH); digitalWrite(C, HIGH); digitalWrite(D, HIGH); digitalWrite(E, LOW); digitalWrite(F, LOW); digitalWrite(G, HIGH); if (digitalRead(BUTTON) == HIGH) { delay(500); v = 0; } } }
Пояснения к коду:
- переменная используется в программе для перехода одного цикла while к другому. При нажатии на кнопку значение переменной v меняется;
- в программе поставлена небольшая задержка в каждом условии для защиты от быстрого перехода от одного цикла while в другой.
Заключение. Мы ограничились лишь знакомством с данным модулем и его применением с платой Ардуино. Используя несколько панелек или четырехразрядный семисегментный индикатор можно уже сделать полноценный таймер на Ардуино или часы реального времени. Эти схемы мы разместили в разделе Проекты на Ардуино для начинающих, где любой может найти по своему вкусу проект на микроконтроллере.
Программирование одноразрядного семисегментного индикатора
Использование в конструкции одноразрядного индикатора может потребоваться в разных случаях. К примеру, собираем кодовый замок и есть необходимость высвечивать цифру соответствующую нажатой кнопки, или в охранной сигнализации высвечивать номер сработавшего датчика. Так что сфера применения одноразрядных индикаторов приличная.
Организацию вывода цифр на одноразрядный индикатор мы оформим в виде подпрограммы: «Вывод информации на одноразрядный семисегментный светодиодный индикатор», так, чтобы затем эту подпрограмму с минимальными изменениями можно было использовать в любой программе.
Алгоритм подпрограммы:
1. Инициализация индикатора (подпрограмма)
— настройка порта, к которому подключен индикатор на вывод информации
— запись кодов семисегментного индикатора, соответствующих десятичным цифрам в определенные ячейки памятиДанная подпрограмма должна вызываться отдельно из основной программы2. Вход в основную подпрограмму3. Основная часть
— считываем текущую цифру
— определяем какой код семисегментного индикатора соответствует текущей десятичной цифре
— записываем определенный код индикатора в порт микроконтроллера4. Выход из подпрограммы
Для оформления программы в виде подпрограммы нам необходимо проделать ряд действий:1. Присваиваем имя подпрограмме инициализации индикатора — Ini_Indiкator_1 (к примеру)2. Присваиваем имя основной подпрограмме — Indicator_13. Присваиваем имена переменным SRAM в которых будут храниться коды семисегментного индикатора, к примеру:
— D0 (для цифры 0, и так далее), D1, D2, D3, D4, D5, D6, D7, D8, D9
— присваиваем имя переменной в которой будет хранится адрес ячейки памяти (D0) с кодом первой цифры (0) — D0_94. Присваиваем имя переменной, в которой будет хранится текущая цифра, которую необходимо вывести на индикатор. В эту переменную основная программа будет записывать вычисленные данные (цифры), которые мы выводим на индикатор — Data (к примеру).
Вот как, к примеру, в Algorithm Builder (остальные примеры тоже для этой программы), объявляются имена переменных в памяти программ (ОЗУ, SRAM):
В графе «Name» перечислены все имена переменных. В графе «Adress» запись «@D0_9» означает, что в переменной D0_9 хранится адрес первой переменной (D0)
Подпрограмма инициализации индикатора (подпрограмма вызывается из основной программы до обращения к подпрограмме вывода информации на индикатор):
А теперь давайте посмотрим основную часть программы и расшифруем ее:
Основная программа записала в назначенную нами переменную Data текущую цифру (для примера — цифра 6) и для вывода ее на индикатор вызвала подпрограмму Indikator_1.
Работа подпрограммы:
— Содержимое переменной Data записывается в рабочий регистр R20, теперь в регистре число 6 (рабочий регистр может быть любой)
— Допустим, первая переменная с кодом цифры у нас находится в ячейки памяти по адресу 100. На самом деле мы не знаем адреса ячеек памяти где хранятся значения D0…D9, но они точно следуют друг за другом. Поэтому была назначена переменная D0_9, в которой, как мы назначили, хранится адрес ячейки памяти D0 (в данный момент адрес =100).- Следующей командой:@D0_9 —> Y мы загружаем в двойной регистр Y адрес переменной D0 и получаем, что в регистре Y записалось число — 100.- Следующей командой:Y + R20 мы складываем число 100 с числом 6, результат = 106 при этом сохраняется в двойном регистре Y.- Следующей командой: —> R20 мы записываем содержимое ячейки памяти, расположенной по адресу, который записан в двойном регистре Y (106), а по этому адресу у нас расположена ячейка памяти переменной D6. Теперь в рабочем регистре R20 записано число 7Dh — код семисегментного индикатора для вывода цифры 6.- Следующей командой:R20 —> PortB мы выводим содержимое R20 в порт PB — высвечиваем цифру 6- Возвращаемся из подпрограммы
Надеюсь, что материал изложен доступно, если что-то не понятно, спрашивайте.
Часть 1: Семисегментный светодиодный индикатор: описание, подключение к микроконтроллеруЧасть 3: Многоразрядный семисегментный индикатор: организация динамической индикации, алгоритм работы, программа индикации
Семисегментный индикатор: программированиеСемисегментный индикатор: подключение, программирование, перевод двоичного кода числа в код семисегментного индикатора
Published by: Мир микроконтроллеров
Date Published: 10/02/2015
Семисегментный индикатор распиновка
На картинке выше представлена распиновка одноразрядного семисегментного индикатора с общим катодом (минусом). Модуль представляет из себя небольшую led индикатор в котором находится семь светодиодов (благодаря этому индикатор и получил свое название) и восьмой светодиод в виде точки. Включая светодиоды в разной последовательности от Ардуино Уно, можно выводить различные цифры.
Обратите внимание, что панель не имеет резисторов, поэтому при подключении светодиодов используйте внешние резисторы. Если цоколевка семисегментного индикатора с общим анодом, вам непонятна, то можно опытным путем установить распиновку, подключая питание к разным выводам
При неправильном включении ничего страшного не произойдет, а вот без резистора светодиоды могут сгореть.
Реализация
Есть три способа воплотить данный декодер в жизнь.
-
Из готовых микросхем логических вентилей, например серия микросхем 74HCxx. Данный способ самый простой, не самый практичный, но вполне допустимый. Также его будет просто модернизировать для n-разярдных индикаторов. И отлично подходит для тестов.
-
Более сложный, но более «крутой» способ, создание всех логических вентилей на ТТЛ, отлично подойдут транзисторы BC546 и его комплементарная пара BC556. Этот способ потребует дополнительного создания схемы на транзисторах, для их корректной работы. Будет занимать больше пространства, но можно сделать прозрачный корпус и поставить на полочку. Ведь применение ТТЛ в наше время, дело совсем незаурядное.
-
Промышленный способ — изготовление полноценных кремниевых интегральных схем. Этот способ не самый быстрый, но позволяет наладить массовое производство. НО стоит отметить, что уже давно выпускаются подобные микросхемы, и это будет не слишком целесообразно.
Модуль часов реального времени DS3231
Внешний вид данного модуля представлен на следующем рисунке.
Модуль предназначен для хранения времени и даты даже когда общее питание схемы выключено – для этой цели в его состав входит элемент питания CR2032. В состав модуля DS3231 входит также датчик температуры, поэтому его можно использовать в различных встраиваемых устройствах, например, в цифровых часах с индикатором температуры и т.д. Модуль работает по интерфейсу I2C. На нашем сайте вы можете посмотреть следующие проекты с использованием данного модуля:
- автоматический напоминатель приема лекарств на Arduino;
- автоматическая кормушка для животных на Arduino;
- логгер данных (температуры, влажности) на SD карту и компьютер с помощью Arduino.
Назначение контактов (распиновка) модуля DS3231 приведена в следующей таблице.
Наименование контакта | Назначение контакта |
VCC | напряжение питания |
GND | общий провод (земля) |
SDA | контакт последовательной передачи данных (I2C) |
SCL | контакт синхронизации (тактирования) (I2C) |
SQW | выход прямоугольного сигнала (программируемый меандр) |
32K | выход меандра с частотой 32.768кГц |
Теперь перейдем непосредственно к схеме нашего проекта.
Декодирование
Использование двоичной системы счисления, предпологает использование булевой логики. Поэтому будет целесообразно использовать ее. Поэтому для начала мы сделаем таблицу истинности для декодера.
Пока что мы будем использовать простую шину из 4 проводов, по каждому из которых будет передаваться сигнал. В нашем случае 5V — логическая единица, а GND — логический нуль. В таблице первый столбец только для ясности, какую цифру мы хотим отобразить. Исходя из этой таблицы нам надо создать устройство, которое при входных значениях в шине, на выходе выдавало бы 7 значений для индикатора. Для этого, мы будем использовать операции над булевыми значениями: конъюнкция (и, &), дизъюнкция (или, |), отрицание (не, ¬). Итак, приступим к созданию цепи логических вентилей.
Улучшение
Данная схема полностью рабочая, но в ней много повторяющихся элементов, и она будет занимать слишком много места, даже если делать отдельную интегральную схему. Поэтому ее стоит доработать.
Для начала, взглянем на таблицу истинности. Можно заметить, что для сегмента е больше логических , так что для него, можно не инвертировать выход (!! — двойное отрицание, то есть ничего не меняем). Также использование одного и того же модуля для цифры 1 происходит 4 раза! А для цифры 9 можно не делать модуль вообще (количество повторений одного модуля для цифры вынесено в последнюю колонку). Это существенная трата пространства и логических вентилей. После реинжинеринга, на выходе будет примерно такая схема:
Управление семисегментными индикаторами
В следующем примере переключение чисел на индикаторе будет происходить только при нажатии тактовой кнопки. Дойдя до числа 3, таймер вновь обнулится и будет ожидать повторного нажатия на кнопку. Это довольно простые программы для Ардуино и семисегментного индикатора, для более сложных и интересных программ необходимо уже использовать сдвиговый регистр 74hc595 для Ардуино.
Пояснения к коду:
Заключение. Мы ограничились лишь знакомством с данным модулем и его применением с платой Ардуино. Используя несколько панелек или четырехразрядный семисегментный индикатор можно уже сделать полноценный таймер на Ардуино или часы реального времени. Эти схемы мы разместили в разделе Проекты на Ардуино для начинающих, где любой может найти по своему вкусу проект на микроконтроллере.
Источник
Что такое 4-разрядный 7-сегментный индикатор hs420561k-32
Как можно увидеть на фото, 4-разрядный 7-сегментный индикатор идеально подходит для задуманного прибора. Один разряд будет отвечать за вывод минуса, при необходимости, второй и третий разряд оставим для вывода градусов, а четвертый будет просто для красоты, всегда выводить значок градусов.
В первую очередь нужно разобраться, как работает индикатор. У модуля 12 ног, 4 из них являются катодами, и каждый отвечает за один разряд из четырех – на какую ногу будет подан минус, тот разряд и будет активным. 8 других являются анодами и каждая отвечает за один из 7 сегментов и за точку внизу цифры. Таким образом, мы можем управлять каждым сегментом и разрядом. Единственная проблема кроется в том, что выводить можно одновременно только одну цифру на каждом разряде. Побороть это не сложно, достаточно просто за очень короткий промежуток времени по очереди выводить нужную информацию на каждый из разрядов. Человеческий глаз не сможет уловить переключение и будет казаться, что одновременно горят все разряды. Даже фотокамера не смогла это уловить – это видно по фотографии, которую я прикладывал выше.
Посмотреть какая нога индикатора за что отвечает, можно по картинке ниже.
Для удобства работы и чтобы закрепить знания из прошлой статьи про сдвиговый регистр я решил использовать в схеме микросхему 74HC595. Это снизит количество задействованных пинов ардуино. Ниже я привел схему подключений, она получилось кривая, надеюсь, со временем я научусь рисовать их качественней :). P.S. На схеме я не нарисовал 3 резистора — пропустил, их нужно добавить между пинами arduino и ножками hs420561k-32 с именами A, F и B.
Принцип работы
Семисегментный индикатор — это просто набор обычных светодиодов в одном корпусе. Просто они выложены восьмёркой и имеют форму палочки-сегмента. Можно подключить его напрямую к 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 и быстро инкрементировать значение по единице до заданного. Глазу это не заметно.
Подпрограмма вывода данных на многоразрядный семисегментный индикатор
Присвоим подпрограмме имя, к примеру Indikator2, посмотрим на нее и разберем построчно:Хочу сразу отметить, что в этой подпрограмме вывод данных начинается не с первого разряда индикатора, а со второго — так удобнее реализовать алгоритм.
В переменной DataIndex храниться номер ячейки памяти (0, 1 или 2) с данными (Data0, Data1 или Data2) которые необходимо вывести на разряд индикатора в текущий момент. Первоначально мы записали в нее ноль.Первой строкой мы записываем содержимое DataIndex в регистр R20, теперь в нем соответственно то-же ноль.Во второй строчке мы увеличиваем содержимое регистра R20 на единицу (r20++), теперь в R20 записана единица, означающая, что данные мы будем брать из переменной Data1. При втором прерывании R20 увеличится еще на единицу, станет равным 2, и соответственно следующие данные мы будем брать из переменной Data2. При следующем прерывании R20 станет равным 3.Следующей строчкой (r20<3) мы проверяем какая цифра записана в регистре R20 — если меньше трех (0,1 или 2), то переходим по стрелке, а если равно трем, то обнуляем регистр R20 и данные теперь берем из переменной Data0.Далее записываем содержимое R20 в переменную DataIndex.Следующей командой @Data -> Y записываем адрес переменной Data0 в двойной регистр Y (R28, R29).Затем складываем содержимое двойного регистра Y с содержимым R20 (0,1 или 2).Командой -> r21 записываем содержимое переменной данных (или Data0, или Data1, или Data2 — в зависимости от значения r20) в рабочий регистр R21. Теперь в регистре R21 записана цифра из соответствующей переменной данных (к примеру цифра 5).Следующей командой @D0_9*2 -> Z мы загружаем начальный адрес таблицы с двоичными кодами в двойной регистр Z (R30, R31). По начальному адресу у нас находится двоичный код для цифры 0.Теперь мы складываем содержимое Z с R21 (с пятеркой) и получаем в регистре Z адрес в таблице двоичного кода с цифрой 5.Следующей командой LPM -> R21 мы записываем двоичный код цифры 5 в рабочий регистр R21.Команду NOP — холостой ход, можно и не прописывать — она вставлена для разделения отдельных кусков программы для наглядности.Следующей командой PortDidgit -> R20 мы загружаем в рабочий регистр R20 содержимое переменной PortDidgit, а в нее мы предварительно записали единицу. Теперь в R20 записана единица (#b 0000 0001).Следующей командой <<R20 мы производим сдвиг содержимого регистра R20 на один разряд влево (получаем #b 0000 0010).Следующей командой R20 -> PortD мы подаем напряжение на второй разряд индикатора. При следующем прерывании произойдет еще один сдвиг влево (#b 0000 0100) и будет подключен третий разряд индикатора.С помощью команды R20.3=1 записанной в овале, мы проверяем — достигла ли логическая единица при сдвигах третьего разряда регистра, и если — да, то записываем в R20 единицу (начинается новый круг).Командой R21 -> PortB мы выводим двоичный код соответствующей цифры на подключенный разряд индикатора.Командой R20 -> PortDigits — мы сохраняем текущее значение в переменной (последний зажженный разряд индикатора).
Вот так полностью выглядит подпрограмма вывода данных на семисегментный индикатор с динамической индикацией и первоначальными настройками:
Вот, в принципе, и все. Если что-то не очень понятно, или совсем непонятно, пишите, отвечу на все вопросы.
Предыдущие статьи:Часть 1: Семисегментный светодиодный индикатор: описание, подключение к микроконтроллеруЧасть 2: Перевод двоичного кода десятичного числа в код семисегментного индикатора. Программа вывода цифры на одноразрядный светодиодный индикатор.
Многоразрядный семисегментный индикаторПодключение многоразрядного семисегментного индикатора, организация динамической индикации, алгоритм работы программы, программа индикации на многоразрядном семисегментном индикаторе
Published by: Мир микроконтроллеров
Date Published: 04/20/2015