Многоразрядный семисегментный индикатор

Admin 20.04.2015

Доброго дня уважаемые друзья!
Приветствую Вас на сайте «Мир микроконтроллеров»


Программирование работы многоразрядного семисегментного индикатора

Подключение многоразрядного семисегментного индикатора
Организация динамической индикации
Алгоритм работы программы
Программа индикации на многоразрядном семисегментном индикаторе

Во второй части статьи о семисегментных индикаторах мы рассмотрели вопросы подключения одноразрядного индикатора к микроконтроллеру, перевели десятичные цифры в коды семисегментного индикатора, создали программу для ввода данных на индикатор. Сегодня мы узнаем как подключить к микроконтроллеру многоразрядный семисегментный индикатор, организовать динамическую индикацию и напишем программу для вывода информации на многоразрядный индикатор

Многоразрядный семисегментный индикатор

Подключение многоразрядного семисегментного индикатора

Давайте еще раз посмотрим схему подключения многоразрядного семисегментного индикатора к микроконтроллеру:

Схема включения многоразрядного индикатора

На этой схеме выводы порта РВ (РВ0 — РВ7) микроконтроллера через токоограничительные резисторы подключены к соответствующим сегментам (a-g) многоразрядного семисегментного индикатора. Соответствующие сегменты всех разрядов индикатора соединены параллельно. Катоды (аноды) каждого разряда индикатора подключены через транзисторы к выводам порта PD.


 Организация динамической индикации

Работа многоразрядного индикатора осуществляется следующим образом:

1. На управляющий транзистор первого разряда индикатора (7Seg1), с вывода порта микроконтроллера PD0 подается логическая единица, которая открывает транзистор, в результате чего подается напряжение питания на данный разряд индикатора. На базах остальных транзисторов — логический ноль, транзисторы закрыты.
2. На выводах порта РВ0-РВ7 выставляется двоичный код соответствующей десятичной цифры — высвечивается нужная цифра в первом разряде.
3. На управляющий транзистор второго разряда (7Seg2) с вывода порта PD1 подается логическая единица (на остальные транзисторы — логический ноль) — подается питание на второй разряд индикатора.
4. На выводах порта РВ0-РВ7 выставляется двоичный код следующей (второй) десятичной цифры — высвечивается нужная цифра во втором разряде.
5. На управляющий транзистор третьего разряда (7Seg3) с вывода порта PD2 подается логическая единица (на остальные транзисторы — логический ноль) — подается питание на третий разряд индикатора.
6. На выводах порта РВ0-РВ7 выставляется двоичный код следующей (третьей) десятичной цифры — высвечивается нужная цифра во втором разряде.
7. И так, по кругу

Такая работа многоразрядного семисегментного индикатора называется —динамическая индикация.
Частота переключения разрядов должна быть в пределах 100 герц, тогда не будет заметно мерцание разрядов.

Для переключения разрядов можно задействовать (на примере микроконтроллера ATtiny2313) таймер «TIMER 0«.
Настройка таймера производится следующим образом (при тактовой частоте 1 мГц — заводская установка):
— предделитель таймера устанавливаем в СК/8
— вызов прерывания по переполнению счетчика таймера

Вот так настройка таймера выглядит в программе:
Программирование таймера в Algorithm BuilderГде:
SP — настройка стека
Timer 0 — настройка параметров таймера
TIMSK — настройка прерывания


Алгоритм работы программы

Рассмотрим алгоритм программы для осуществления динамической индикации и вывода данных в многоразрядный семисегментный индикатор:

Алгоритм программы семисегментного индикатора

Этот алгоритм, в принципе, иллюстрирует организацию динамической индикации данных на многоразрядном индикаторе. При этом надо учитывать, что при первом прерывании выполняется первый «прямоугольник», а затем происходит выход из подпрограммы, при втором прерывании выполняется второй «прямоугольник» и тоже выход из подпрограммы и при третьем прерывании — нижний «прямоугольник» с выходом из подпрограммы, и далее по кругу.

Ну а теперь — самое легкое. Напишем программу вывода данных на многоразрядный семисегментный индикатор с динамической индикацией.


Программа индикации на многоразрядном семисегментном индикаторе

Как я уже писал в другой статье — АЛГОРИТМ — предшественник программы, и чем продуманнее он будет написан, тем легче будет писать программу.

Назначение переменных:

Давайте посмотрим какие переменные для работы подпрограммы вывода данных на индикатор назначил я:

Назначение переменных в программе

Data0, Data1 и  Data2 — переменные, в которые основная программа записывает вычисленное значение (трехзначное)
Data — переменная, в которой записан адрес первой переменной данных — Data0
@Data — эта запись означает, что в переменной Data будет храниться адрес первой переменной данных — Data0
DataIndex — эта переменная хранит текущий номер переменной данных, которая выводилась на индикацию последней (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.

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


Подпрограмма вывода данных на многоразрядный семисегментный индикатор

Присвоим подпрограмме имя, к примеру 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).
Командой [Y] -> r21 записываем содержимое переменной данных (или Data0, или Data1, или Data2 — в зависимости от значения r20) в рабочий регистр R21. Теперь в регистре R21 записана цифра из соответствующей переменной данных (к примеру цифра 5).
Следующей командой @D0_9*2 -> Z мы загружаем начальный адрес таблицы с двоичными кодами в двойной регистр Z (R30, R31). По начальному адресу у нас находится двоичный код для цифры 0.
Теперь мы складываем содержимое Z с R21 (с пятеркой) и получаем в регистре Z адрес в таблице двоичного кода с цифрой 5.
Следующей командой LPM[Z] -> 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 — мы сохраняем текущее значение в переменной (последний зажженный разряд индикатора).

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

Общий вид программы в Algorithm Builder

Вот, в принципе, и все. Если что-то не очень понятно, или совсем непонятно, пишите, отвечу на все вопросы.


Предыдущие статьи:
Часть 1: Семисегментный светодиодный индикатор: описание, подключение к микроконтроллеру
Часть 2: Перевод двоичного кода десятичного числа в код семисегментного индикатора. Программа вывода цифры на одноразрядный светодиодный индикатор.


(14 голосов, оценка: 4,86 из 5)
Загрузка...


Подключение многоразрядного семисегментного индикатора, организация динамической индикации, алгоритм работы программы, программа индикации на многоразрядном семисегментном индикаторе
Published by: Мир микроконтроллеров
Date Published: 04/20/2015


Комментарии

Многоразрядный семисегментный индикатор — 6 комментариев

  1. Выставили сегменты в разряде 1. Подождали;
    Переключили на разряд 2 (но горят сегменты разряда 1!);
    Выставили сегменты в разряде 2;

    Хоть сегменты «не того разряда» горят и долю секунды, но все равно неприятно выглядит такое мерцание. Это дилетанство. Нужно перед переключением гасить все сегменты полностью.

    • Здравствуйте Макс!
      Можно, конечно, и гасить сегменты перед переходом на новый разряд.
      Но когда устанавливать нужные сегменты? Получается — после перехода к новому разряду.
      Следуя Вашей логике получается следующее:
      — высвечиваем 1-й разряд
      — в конце гасим сегменты
      — переходим ко 2-му разряду
      — зажигаем нужные сегменты
      И что получается? В два раза хуже — два временных интервала будут с погашенными сегментами — до перехода к новому разряду и после перехода до установки нужных сегментов
      Оптимальный вариант — устанавливать нужные сегменты после перехода к новому разряду.
      Кстати, если устанавливать сегменты (не гася их) до перехода к новому разряду — будет заметно мерцание.
      С уважением, Admin.

  2. Благодарю, добрые человеки!! Эту тему и дс18б20 ещё не освоил, но с такими доходчиво разъяснениями — думаю дело стронется!
    Будьте Здравы!

  3. Добрый день!
    Спасибо за объяснения.В опциях проекта — компилятор — регистр Z установлен как двойной регистр. В мануле в разделе непосредственное размещение данных в памяти программ приведен пример. Согласно примера строка @D0_9*2 ->z ,представлена как
    D0_9*2 -> z. Если убрать значок «@»,ошибки не выдает. В вашем примере этот значок присутствует.Может это опечатка? Спасибо.

  4. Добрый день! В принципе алгоритм понятен.Только при компилировании в строке @D0_9*2`в Z, выдает ошибку,неизвестное имя @D0_9. Подскажите пожалуйста,что я делаю не так.Спасибо.`

    • Доброго дня Александр!
      Я тоже когда-то нарвался на такую штуку и долго мучился, пока внимательно не прочел инструкцию.
      Дело в том, что «Z» имеет два назначения:
      1. Двойной регистр Z
      2. Флаг Z регистра SREG
      По умолчанию в АБ Z подразумевается как флаг регистра SREG (поэтому и выдается ошибка).
      Есть два пути устранения ошибки:
      1. В меню ОПЦИИ -> ОПЦИИ ПРОЕКТА -> КОМПИЛЯТОР поменять «Интерпритацию шаблона»
      2. Выделить Z жирным шрифтом нажав клавишу F2, и тогда Z будет интерпритироваться как двойной регистр Z.
      С уважением, Admin.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *