Принцип работы семисегментного дисплея (индикатора)
Но прежде чем идти дальше, кратко остановимся на том, что такое семисегментный дисплей. Этот дисплей получил свое название исходя из того факта, что он имеет семь светящихся сегментов. Каждый из этих сегментов содержит светодиод. Диаграмма контактов семисегментного дисплея показана на рисунке ниже.
Светодиоды в таком дисплее установлены таким образом, что каждый из них содержит свой собственный сегмент. Важная вещь, которую здесь необходимо отметить, светодиоды в семи сегментном дисплее могут быть упорядочены в общем анодном режиме (положительном) или в общем катодном режиме (отрицательном). Соединение цепей семисегментного дисплея для этих режимов показано на следующем рисунке.
Как мы можем видеть, в катодном режиме (Common Cathode) отрицательные выводы светодиодов соединены вместе и названы «землей (GND)». В анодном режиме (Common Anode) положительные выводы светодиодов соединены вместе и названы «напряжением постоянного тока (VCC)». Эти режимы имеют значение (то есть их надо учитывать) когда мы объединяем несколько семи сегментных дисплеев в одно целое.
Чтобы человеческий глаз не замечал мерцания светодиодов семисегментного индикатора их необходимо переключать с частотой не менее 50 Гц.
Более подробно принципы работы с семисегментным индикатором вы можете изучить в следующих статьях на нашем сайте:
- семисегментный светодиодный индикатор: описание, подключение к микроконтроллеру;
- перевод двоичного кода десятичного числа в код семисегментного индикатора. Программа вывода цифры на одноразрядный светодиодный индикатор;
- многоразрядный семисегментный индикатор: организация динамической индикации, алгоритм работы, программа индикации.
Схема расположения контактов ввода/вывода (GPIO) на плате Raspberry Pi показана на следующем рисунке. Более подробно об этих контактах вы можете прочитать в статье про мигание светодиода с помощью Raspberry Pi.
Напряжения +3.3V, подаваемого с контактов ввода/вывода платы Raspberry Pi (GPIO’s pin 1 или 17), будет вполне достаточно для подачи питания на семисегментный индикатор. Чтобы ограничить ток, протекающий по сегментам индикатора, мы использовали резисторы сопротивлением 1 кОм как показано на схеме ниже.
Семисегментный индикатор распиновка
На картинке выше представлена распиновка одноразрядного семисегментного индикатора с общим катодом (минусом). Модуль представляет из себя небольшую led индикатор в котором находится семь светодиодов (благодаря этому индикатор и получил свое название) и восьмой светодиод в виде точки. Включая светодиоды в разной последовательности от Ардуино Уно, можно выводить различные цифры.
Обратите внимание, что панель не имеет резисторов, поэтому при подключении светодиодов используйте внешние резисторы. Если цоколевка семисегментного индикатора с общим анодом, вам непонятна, то можно опытным путем установить распиновку, подключая питание к разным выводам
При неправильном включении ничего страшного не произойдет, а вот без резистора светодиоды могут сгореть.
Исходный код программы на Python
В результате исполнения данной программы на семисегментном индикаторе будут последовательно высвечиваться цифры от 0 до 9.
Python
import RPi.GPIO as IO # подключение библиотеки для работы с контактами ввода/вывода
import time # подключение библиотеки для работы с задержками
DISPLAY = # строка с шестнадцатеричными кодами, которые используются для отображения цифр на семисегментном индикаторе
IO.setwarnings(False) # отключаем показ любых предупреждений
IO.setmode (IO.BCM) # мы будем программировать контакты GPIO по их функциональным номерам (BCM), то есть мы будем обращаться к PIN29 как ‘GPIO5’
IO.setup(13,IO.OUT) # инициализируем контакты GPIO в качестве цифровых выходов
IO.setup(6,IO.OUT)
IO.setup(16,IO.OUT)
IO.setup(20,IO.OUT)
IO.setup(21,IO.OUT)
IO.setup(19,IO.OUT)
IO.setup(26,IO.OUT)
IO.setup(12,IO.OUT)
def PORT(pin): # функция для передачи значения ‘pin’ на выходные контакты
if(pin&0x01 == 0x01):
IO.output(13,1) # если bit0 из 8bit ‘pin’ is true, на PIN13 устанавливаем high
else:
IO.output(13,0) # если bit0 из 8bit ‘pin’ is false, на PIN13 устанавливаем low
if(pin&0x02 == 0x02):
IO.output(6,1) # если bit1 из 8bit ‘pin’ is true, на PIN6 устанавливаем high
else:
IO.output(6,0) # если bit1 из 8bit ‘pin’ is false, на PIN6 устанавливаем low
if(pin&0x04 == 0x04):
IO.output(16,1)
else:
IO.output(16,0)
if(pin&0x08 == 0x08):
IO.output(20,1)
else:
IO.output(20,0)
if(pin&0x10 == 0x10):
IO.output(21,1)
else:
IO.output(21,0)
if(pin&0x20 == 0x20):
IO.output(19,1)
else:
IO.output(19,0)
if(pin&0x40 == 0x40):
IO.output(26,1)
else:
IO.output(26,0)
if(pin&0x80 == 0x80):
IO.output(12,1) # если bit7 из 8bit ‘pin’ is true, на PIN12 устанавливаем high
else:
IO.output(12,0) # если bit7 из 8bit ‘pin’ is false, на PIN12 устанавливаем low
while 1:
for x in range(10): # цикл, который исполняется 10 раз, в нем переменная x инкрементируется от 0 до 9
pin = DISPLAY # присваиваем значение переменной ‘pin’ для каждой цифры
PORT(pin); # показываем каждую цифру на семисегментном индикаторе
time.sleep(1)
1 |
importRPi.GPIO asIO# подключение библиотеки для работы с контактами ввода/вывода importtime# подключение библиотеки для работы с задержками DISPLAY=0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x67# строка с шестнадцатеричными кодами, которые используются для отображения цифр на семисегментном индикаторе IO.setwarnings(False)# отключаем показ любых предупреждений IO.setmode(IO.BCM)# мы будем программировать контакты GPIO по их функциональным номерам (BCM), то есть мы будем обращаться к PIN29 как ‘GPIO5’ IO.setup(13,IO.OUT)# инициализируем контакты GPIO в качестве цифровых выходов IO.setup(6,IO.OUT) IO.setup(16,IO.OUT) IO.setup(20,IO.OUT) IO.setup(21,IO.OUT) IO.setup(19,IO.OUT) IO.setup(26,IO.OUT) IO.setup(12,IO.OUT) defPORT(pin)# функция для передачи значения ‘pin’ на выходные контакты if(pin&0x01==0x01) IO.output(13,1)# если bit0 из 8bit ‘pin’ is true, на PIN13 устанавливаем high else IO.output(13,)# если bit0 из 8bit ‘pin’ is false, на PIN13 устанавливаем low if(pin&0x02==0x02) IO.output(6,1)# если bit1 из 8bit ‘pin’ is true, на PIN6 устанавливаем high else IO.output(6,)# если bit1 из 8bit ‘pin’ is false, на PIN6 устанавливаем low if(pin&0x04==0x04) IO.output(16,1) else IO.output(16,) if(pin&0x08==0x08) IO.output(20,1) else IO.output(20,) if(pin&0x10==0x10) IO.output(21,1) else IO.output(21,) if(pin&0x20==0x20) IO.output(19,1) else IO.output(19,) if(pin&0x40==0x40) IO.output(26,1) else IO.output(26,) if(pin&0x80==0x80) IO.output(12,1)# если bit7 из 8bit ‘pin’ is true, на PIN12 устанавливаем high else IO.output(12,)# если bit7 из 8bit ‘pin’ is false, на PIN12 устанавливаем low while1 forxinrange(10)# цикл, который исполняется 10 раз, в нем переменная x инкрементируется от 0 до 9 pin=DISPLAYx# присваиваем значение переменной ‘pin’ для каждой цифры PORT(pin);# показываем каждую цифру на семисегментном индикаторе time.sleep(1) |
Реализации
Мультиплексированы 4-значный, семисегментный индикатор только с 12 штырьками
Рентгеновский снимок 8-разрядного 7-сегментного мультиплексированного светодиодного дисплея из калькулятора 1970-х годов
Семисегментные дисплеи могут использовать жидкокристаллический дисплей (LCD), светоизлучающий диод (LED) для каждого сегмента, или другие методы генерации света или управления, такие как газовый разряд с холодным катодом (Panaplex), вакуумно-флуоресцентный (VFD), лампы накаливания (Numitron) и другие. Для тотемов с ценами на бензин и других крупных вывесок по-прежнему широко используются лопастные дисплеи, состоящие из отражающих свет сегментов (или «лопаток») с электромагнитным переворачиванием. Предшественником 7-сегментного дисплея в 1950–1970-х годах была никси -лампа с холодным катодом, похожая на неоновую лампу . Начиная с 1970 года, RCA продавала устройство отображения, известное какNumitron, в котором использовались нити накаливания, объединенные в семисегментный дисплей. В СССР первый электронный калькулятор «Вега», выпускавшийся с 1964 года, содержит 20 десятичных знаков с семисегментнымэлектролюминесцентным дисплеем.
В простом корпусе светодиодов обычно все катоды (отрицательные выводы) или все аноды (положительные выводы) сегментных светодиодов подключаются и выводятся на общий вывод; это называется устройством с «общим катодом» или «общим анодом». Следовательно, для пакета из 7 сегментов плюс десятичная точка потребуется только девять контактов, хотя коммерческие продукты обычно содержат больше контактов и / или пробелов, где будут размещаться контакты, чтобы соответствовать стандартным разъемам IC . Также существуют интегрированные дисплеи с одной или несколькими цифрами. Некоторые из этих интегрированных дисплеев имеют собственный внутренний декодер , но большинство из них нет: каждый отдельный светодиод подключается к соединительному контакту, как описано.
Многоразрядные светодиодные дисплеи, используемые в карманных калькуляторах и аналогичных устройствах, использовали мультиплексированные дисплеи для уменьшения количества контактов ввода / вывода, необходимых для управления дисплеем. Например, все аноды сегментов A каждой позиции цифры должны быть соединены вместе и с выводом схемы драйвера , в то время как катоды всех сегментов для каждой цифры будут подключены. Чтобы управлять любым конкретным сегментом любой цифры, управляющая интегральная схема должна включать катодный драйвер для выбранной цифры и анодные драйверы для желаемых сегментов; затем после короткого интервала гашения будет последовательно выбираться следующая цифра и светиться новые сегменты. Таким образом, восьмиразрядный дисплей с семью сегментами и десятичной точкой потребует только 8 катодных драйверов и 8 анодных драйверов вместо шестидесяти четырех драйверов и выводов IC. Часто в карманных калькуляторах линии ввода цифр также используются для сканирования клавиатуры, что обеспечивает дополнительную экономию; однако одновременное нажатие нескольких клавиш приведет к нечетным результатам на мультиплексном дисплее.
Хотя невооруженным глазом все цифры на светодиодном дисплее кажутся горящими, на мультиплексном дисплее в любой момент времени светится только одна цифра. Цифра изменяется с достаточно высокой скоростью, чтобы человеческий глаз не мог видеть мигание (на более ранних устройствах это могло быть видно периферическим зрением).
Программа индикации на многоразрядном семисегментном индикаторе
Как я уже писал в другой статье — АЛГОРИТМ — предшественник программы, и чем продуманнее он будет написан, тем легче будет писать программу.
Назначение переменных:
Давайте посмотрим какие переменные для работы подпрограммы вывода данных на индикатор назначил я:
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.
После проделанной нами предварительной работы, разрешаем микроконтроллеру использовать прерывания и переходим к самому главному — подпрограмме вывода данных на многоразрядный индикатор.
Скетч для управлением индикатором hs420561k-32
Теперь остается только написать скетч, его код приведен ниже, а также доступен для скачивания тут: скачать.
//Пин подключен к SH_CP входу 74HC595 int clockPin = 6; //Пин подключен к ST_CP входу 74HC595 int latchPin = 7; //Пин подключен к DS входу 74HC595 int dataPin = 8; // Пины разрядов цифер int pins_numbers = {2, 3, 4, 5}; // Биты для отображения цифер от 0-9, минуса и символ градуса цельсия byte numbers_array = { B00111111, B00000110, B01011011, B01001111, // 0 1 2 3 B01100110, B01101101, B01111101, B00000111, // 4 5 6 7 B01111111, B01101111, B01000000, B01100011 // 8 9 - о }; void setup() { //устанавливаем режим OUTPUT pinMode(latchPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(dataPin, OUTPUT); for(int i; i<4; i++){ pinMode(pins_numbers, OUTPUT); } } void loop() { // включить сразу несколько цифр нельзя, поэтому очень быстро показываем по одной showNumber(1, 11); showNumber(2, 7); showNumber(3, 2); showNumber(4, 10); } void showNumber(int numNumber, int number){ // зажигаем нужные сегменты digitalWrite(latchPin, LOW); shiftOut(dataPin, clockPin, MSBFIRST, numbers_array); digitalWrite(latchPin, HIGH); // включаем нужный разряд(одну из четырех цифр) int num_razryad = pins_numbers; for(int i; i<4; i++){ // выключаем все digitalWrite(pins_numbers, HIGH); } // включаем нужную digitalWrite(num_razryad, LOW); delay(5); }
Программирование одноразрядного семисегментного индикатора
Использование в конструкции одноразрядного индикатора может потребоваться в разных случаях. К примеру, собираем кодовый замок и есть необходимость высвечивать цифру соответствующую нажатой кнопки, или в охранной сигнализации высвечивать номер сработавшего датчика. Так что сфера применения одноразрядных индикаторов приличная.
Организацию вывода цифр на одноразрядный индикатор мы оформим в виде подпрограммы: «Вывод информации на одноразрядный семисегментный светодиодный индикатор», так, чтобы затем эту подпрограмму с минимальными изменениями можно было использовать в любой программе.
Алгоритм подпрограммы:
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
Управление семисегментными индикаторами
Схема подключения семисегментного индикатора с кнопкой
В следующем примере переключение чисел на индикаторе будет происходить только при нажатии тактовой кнопки. Дойдя до числа 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 в другой.
Заключение. Мы ограничились лишь знакомством с данным модулем и его применением с платой Ардуино. Используя несколько панелек или четырехразрядный семисегментный индикатор можно уже сделать полноценный таймер на Ардуино или часы реального времени. Эти схемы мы разместили в разделе Проекты на Ардуино для начинающих, где любой может найти по своему вкусу проект на микроконтроллере.
Подпрограмма вывода данных на многоразрядный семисегментный индикатор
Присвоим подпрограмме имя, к примеру 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