Меню

Таблица кодов для семисегментного индикатора

Семисегментный индикатор | Программирование микроконтроллеров

Программирование микроконтроллеров Курсы

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

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

Семисегментные индикаторы

По количеству разрядов различают одно-, двух-, трех-, и четырехразрядные индикаторы. Бывает и более разрядов, но они встречаются довольно редко.

Семисегментный индикатор. Принцип работы семисегментного индикатора

Устройство семисегментного индикатора

Любой семисегментный индикатор обязательно состоит из семи сегментов. Отсюда и происходит его название. Каждый сегмент – это обычный отдельный светодиод. Мощные семисегментники могут содержать в одном сегменте несколько, как правило, последовательно соединенных светодиодов.

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

С помощью семи сегментов можно изобразить десять цифр: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 и некоторые буквы, как латиницы, так и кириллицы.

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

Соединение выводов семисегментного индикатора

Вне зависимости от количества разрядов и размеров цифр каждый сегмент имеет название в виде одной из первых букв английского алфавита: a, b, c, d, e, f, g. Точка обозначается dp.

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

Для того чтобы засветить один из светодиодов семисегментного индикатора с общим анодом следует на общий вывод (анод) подать «+», а на соответствующий отдельный вывод – «-» источника питания.

Принцип работы семисегментного индикатора

Если применяется общий катод, – то наоборот – минус подается на общий, а плюс на отдельный вывод.

Чтобы отобразить на индикаторе цифру или букву следует засветить несколько сегментов. Например, для отображения единицы 1 задействуются сегменты b и c. При отображении восьмерки 8 задействуются все символы от a до g. Пятерка получается из таких символов: a, c, d, f, g.

Семисегментный индикатор. Отображение цифр

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

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

Схемы подключения с общим анодом ОА и общим катодом ОК аналогичны, только общий вывод подключается соответственно к плюсу или минусу источника питания.

Схема подключения семисегментного индикатора к микроконтроллеру

Все светодиоды подключаются к выводам микроконтроллера через отдельные резисторы сопротивлением 220…330 Ом.

Не стоит экономить на резисторах и подключать все элементы через один общий резистор. Поскольку в таком случае с изменением числа задействованных сегментов будет изменяться величина тока, протекающего через них. Поэтому цифра 1 будет светиться ярче, чем 8.

Схема подключения семисегментного индикатора к микроконтроллеру ATmega8

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

Распиновка семисегментного индикатора

Теперь создадим модель в Протеусе и соберем схему на макетной плате. Далее по мере написания кода будем проверять работу микроконтроллера на модели и на реальном устройстве.

Семисегментный индикатор и микроконтроллер

Семисегментный индикатор в Proteus находится в категории (Category) Optoelectronics (Оптоэлектроника). Ниже в подкатегории (Sub-category) следует кликнуть по строке 7-Segment Displays. После этого в окне результатов (Results) выбираем одноразрядный семисегментный индикатор 7SEG-MPX1-CC.

Семисегментный индикатор Proteus

Код для микроконтроллера ATmega8

Теперь пишем код. Сначала настраиваем порт D полностью на выход. Для отображения единицы 1 задействуются сегменты b и c, выводы которых подключены к PD1 и PD2. Поэтому соответствующие биты регистр PORTD нужно установить в единицу.

PORTD = 0b00000110; //1

После компиляции кода и прошивки кода результаты мы видим в Proteus и на макетной плате.

Модель семисерментного индикатора в Proteus

Семисегментный индикаторы с общим катодом

Аналогичным образом формируются все цифры.

Давайте сделаем программу более интересной, так, чтобы цифры изменялись в порядке нарастания от нуля до девяти с паузой 0,3 секунды.

#define F_CPU 1000000L

PORTD = 0b00111111; //0

PORTD = 0b00000110; //1

PORTD = 0b01011011; //2

PORTD = 0b01001111; //3

PORTD = 0b01100110; //4

PORTD = 0b01101101; //5

PORTD = 0b01111101; //6

PORTD = 0b00000111; //7

PORTD = 0b01111111; //8

PORTD = 0b01101111; //9

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

Как читать электрические схемы и создавать электронные устройства

Еще статьи по данной теме

Proteus 8.4

Логические операции | Программирование микроконтроллеров AVR на С

Массивы | Программирование микроконтроллеров

Тут такая засада.
На Atiny2323 все работает нормально, на Atmega8 семисегментный индикатор постоянно мерцает. Правда схема такая же как и на Atiny2323 т.е. без кварца. Не подскажите в чем дело?

Дело в том, что по-умолчанию частота работы встроенного генератора (RC-цепочки) Atiny2323 4 МГц, а ATmega8 – 1 МГц, поэтому на меге заметна частота мерцания.

Дмитрий,
Поизучал даташит, правильно понимаю что для установки 4Мгц нужно установить CKSEL3..0 в 0011?

Дмитрий, и еще вопрос в догонку.
Какие кварцы (частоты, типы, кол-во) стоит прикупить для изучения микроконтроллеров?

Сначало зажги светодиод,потом помигай им,потом подключи кнупку,чтоб программа заработал когда нажал кнопку и т.д.кварц для этого не нужен.От простого к сложному.

Автору большое спасибо. После видео уроков на ютубе появился интерес к МК.
Большая просьба автору. Вы собирались сделать материал по динамической индикации –
семи-сегментного индикатора. Возможно, вы бы, могли бы сделать материал, сегменты индикатора к разным портам. Например к двум портам МК.

Andrei, никто не хочет за это дерьмо с разными портами браться, я сам долго искал, у всех подключение к одному порту (так головняка меньше). То что я смог переварить взято с радиокота https://radiokot.ru/forum/viewtopic.php?f=57&t=131489. Да, через анус, но работает.
код:
/*
* M48_dinamind_radiokot.c
*
* Created: 28.11.2018 10:37:52
* Author: Left
*/

#define F_CPU 1000000UL
#include
#include
#include
//—————————————————————
#define SetBit(reg, bit) reg |= (1 29.11.2018 Ответить

Относительно просто динамическую индикацию подключать, применяя оператор switch case.

Да, просто, но как быть с сегментами на разных портах? да еще и так чтоб начинающий смог понять. То что что я видел, с кучей подключаемых библиотек, где хрен разберешь последовательность и что откуда берется, выглядит (как для начинающего) уж очень муторно. Если у Вас будет свободное время, сделайте урок по динамической индикации с сегментами на разных портах, это будет единственное видео на ютубе и единственный урок с комментариями (если будет конечно;) )

Это нужно быть совсем нубом в прерывании тратить время на перебор 13ти кейсов в свитче.
Все делается одним сдвигом N влево в зависимости от размера кейса и джамп на кейс по получившимся смещению после сдвига N. 2 инструкции чтобы попасть в кейс. Но для этого нужно уметь на ассемблере написать.
Еще гасится весь дисплей, потом куча кода проходит до момента отображения сегмента. Все это время дисплей не горит. Лажа полная, а не пример.
У меня даже на убогом нувотоне, где одна инструкция по 3 такта,а не один как у avr обновление дисплея занимает 4.7микросекунды. То есть я могу его обновлять с частотой аж 200 кГц. И каждая нога тоже отдельно дергается, а не просто в порт кинуть. И между моментом когда все гасится и отображается новый сегмент вообще нет пробела, следующей же ассемблерной инструкцией начинает зажигаться.
Так что хочешь сделать быстро и качественно динамическую индикацию без ассемблера не обойтись.

Что-то не весь код с копировался, напиши почту я сброшу.

Источник



Семисегментный индикатор: программирование

Семисегментный индикатор: программирование работы

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

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

Семисегментный индикатор - программирование работы

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

Подключение светодиодного индикатора

Давайте еще раз посмотрим на схему подключения семисегментного индикатора к микроконтроллеру:
На этой схеме выводы порта PB0. PB7 подключены к выводам индикатора в определенной последовательности. Выводу PB0 соответствует сегмент «А» и далее соответственно по порядковому номеру вывода порта и по алфавиту выводов индикатора, при этом десятичная точка «dp» подсоединена к выводу порта PB7 . Сейчас и далее мы будем рассматривать схемы подключения для индикаторов с общим катодом, а при необходимости я буду вставлять дополнения для индикатора с общим анодом.

Читайте также:  Таблицы демонстрационные история россии обобщающие таблицы

Для того, чтобы высветить определенную цифру на индикаторе, необходимо на соответствующих выводах порта микроконтроллера установить логическую единицу

Соответствие выводов порта сегментам

На рисунке выше, черные цифры от 0 до 7 — выводы порта, зеленные латинские буквы — выводы светодиодного индикатора, красные нули — логические уровни на выходах порта (в данном случае логический уровень «0»). Для того, чтобы, к примеру, высветить на индикаторе цифру «4» и зажечь десятичную точку нам необходимо подать логическую 1 на выводы индикатора B, C, F, G и dp, что соответствует подачи логической единицы на выводы порта 1,2,5,6 и 7:

Логические уровни для цифры

Поэтому, первое что нам необходимо сделать, это определить соответствие каждой десятичной цифре двоичного числа, которое надо выдавать на выход порта микроконтроллера для зажигания соответствующих сегментов индикатора.
Для «четверки» мы уже определили такую комбинацию = 1110 0110, что соответствует шестнадцатиричному числу 66h, определяем и для остальных цифр:

Перевод двоично-десятичного кода в код семисегментного индикатора

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

Данная таблица дана для семисегментных индикаторов с общим катодом (сегмент индикатора зажигается логическим уровнем «1»). Для индикаторов с общим анодом (сегмент индикатора зажигается логическим уровнем «0») двоичные коды необходимо проинвертировать (поменять 0 на 1, и наоборот) и заново вычислить соответствующие значения в шестнадцатиричной системе.

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

Использование в конструкции одноразрядного индикатора может потребоваться в разных случаях. К примеру, собираем кодовый замок и есть необходимость высвечивать цифру соответствующую нажатой кнопки, или в охранной сигнализации высвечивать номер сработавшего датчика. Так что сфера применения одноразрядных индикаторов приличная.
Организацию вывода цифр на одноразрядный индикатор мы оформим в виде подпрограммы: «Вывод информации на одноразрядный семисегментный светодиодный индикатор» , так, чтобы затем эту подпрограмму с минимальными изменениями можно было использовать в любой программе.

Алгоритм подпрограммы:

1. Инициализация индикатора (подпрограмма)
— настройка порта, к которому подключен индикатор на вывод информации
— запись кодов семисегментного индикатора, соответствующих десятичным цифрам в определенные ячейки памяти
Данная подпрограмма должна вызываться отдельно из основной программы
2. Вход в основную подпрограмму
3. Основная часть
— считываем текущую цифру
— определяем какой код семисегментного индикатора соответствует текущей десятичной цифре
— записываем определенный код индикатора в порт микроконтроллера
4. Выход из подпрограммы

Для оформления программы в виде подпрограммы нам необходимо проделать ряд действий:
1. Присваиваем имя подпрограмме инициализации индикатора — Ini_Indiкator_1 (к примеру)
2. Присваиваем имя основной подпрограмме — Indicator_1
3. Присваиваем имена переменным SRAM в которых будут храниться коды семисегментного индикатора, к примеру:
D0 (для цифры 0, и так далее), D1, D2, D3, D4, D5, D6, D7, D8, D9
— присваиваем имя переменной в которой будет хранится адрес ячейки памяти (D0) с кодом первой цифры (0) — D0_9
4. Присваиваем имя переменной, в которой будет хранится текущая цифра, которую необходимо вывести на индикатор. В эту переменную основная программа будет записывать вычисленные данные (цифры), которые мы выводим на индикатор — 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 .
— Следующей командой:
[Y] —> R20 мы записываем содержимое ячейки памяти, расположенной по адресу, который записан в двойном регистре Y (106) , а по этому адресу у нас расположена ячейка памяти переменной D6 . Теперь в рабочем регистре R20 записано число 7Dhкод семисегментного индикатора для вывода цифры 6 .
— Следующей командой:
R20 —> PortB мы выводим содержимое R20 в порт PBвысвечиваем цифру 6
— Возвращаемся из подпрограммы

Надеюсь, что материал изложен доступно, если что-то не понятно, спрашивайте.

(16 голосов, оценка: 4,94 из 5)

Источник

Семисегментный индикатор Ардуино

Семисегментный индикатор подключение к Ардуино

Семисегментный индикатор Ардуино ► подключить можно через макетную плату, главное знать распиновку индикатора, чтобы управлять индикатором от Arduino.

Одноразрядный семисегментный индикатор подключить к Ардуино можно через макетную плату, самое главное знать распиновку (цоколевку индикатора), чтобы управлять сегментами от Arduino Uno. Рассмотрим, как подключить семисегментный индикатор к Ардуино и сделать простую программу с таймером. Будем управлять индикатором напрямую от микроконтроллера, используя тактовую кнопку.

Семисегментный индикатор распиновка

Распиновка (цоколевка) семисегментного индикатора

Распиновка 1-разрядного семисегментного индикатора hdsp 7503 / 5161as

На картинке выше представлена распиновка одноразрядного семисегментного индикатора с общим катодом (минусом). Модуль представляет из себя небольшой led индикатор в котором находится семь светодиодов (благодаря этому индикатор и получил свое название) и восьмой светодиод в виде точки. Включая светодиоды в разной последовательности от Ардуино Уно, можно выводить различные цифры.

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

Как подключить семисегментный индикатор

Для этого занятия нам потребуется:

  • плата Arduino Uno / Arduino Nano / Arduino Mega;
  • одноразрядный семисегментный индикатор 5161as / hdsp 7503;
  • тактовая кнопка;
  • резисторы 220 Ом;
  • макетная плата (breadboard);
  • провода «папа-папа».

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

Схема подключения семисегментного индикатора к Ардуино

Для использования модуля 5161as / hdsp 7503 без сдвигового регистра потребуется использовать большое количество пинов Arduino Uno для включения светодиодов на индикаторе. В первом примере мы будем просто поочередно включать / мигать светодиодами для индикации на панели различных чисел. Соберите схему, как на представленной выше картинке и загрузите следующий скетч в микроконтроллер.

Скетч. Вывод чисел на 7-сегментный индикатор Ардуино

Пояснения к коду:

  1. скетч получается большим, поэтому мы ограничились тремя числами. Вывод других чисел на семисегментный индикатор Arduino не составит труда.
Читайте также:  Геометрические размеры шин таблица

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

Схема подключения семисегментного индикатора с кнопкой

Схема подключения семисегментного индикатора с кнопкой

В следующем примере переключение чисел на индикаторе будет происходить только при нажатии тактовой кнопки. Дойдя до числа 3, таймер вновь обнулится и будет ожидать повторного нажатия на кнопку. Это довольно простые программы для Ардуино и семисегментного индикатора, для более сложных и интересных программ необходимо уже использовать сдвиговый регистр 74hc595 для Ардуино.

Скетч. Одноразрядный семисегментный индикатор и кнопка

Пояснения к коду:

  1. переменная byte v = 0; используется в программе для перехода одного цикла while к другому. При нажатии на кнопку значение переменной v меняется;
  2. в программе поставлена небольшая задержка в каждом условии для защиты от быстрого перехода от одного цикла while в другой.

Заключение. Мы ограничились лишь знакомством с данным модулем и его применением с платой Ардуино. Используя несколько панелек или четырехразрядный семисегментный индикатор можно уже сделать полноценный таймер на Ардуино или часы реального времени. Эти схемы мы разместили в разделе Проекты на Ардуино для начинающих, где любой может найти по своему вкусу проект на микроконтроллере.

Источник

Подключение семисегментных индикаторов к AVR. Динамическая индикация

Автор: AntonChip. Дата публикации: 10 мая 2011 .

Звезда активнаЗвезда активнаЗвезда активнаЗвезда активнаЗвезда активна

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

На рисунке 1 изображен внешний вид индикатора. Принято каждый сегмент индикатора обозначать латинской буквой: a, b, c, d, e, f, g. Точка обозначается буквой h.

По схеме включения семисегментные индикаторы подразделяются на индикаторы с общим катодом и с общим анодом. Схемы включения приведены на рисунке 2.

Подключить один семисегментный индикатор и управлять им с помощью микроконтроллера процедура несложная. Для этого достаточно сегменты индикатора подключить к порту микроконтроллера через токоограничительные резисторы по 150 Ом. Общий вывод подключить к линии другого порта микроконтроллера. В зависимости от того какую цифру надо вывести, в порт выводим двоичный код этой цифры, ссылаясь на тип подключенного индикатора (с общим анодом или катодом) на общий провод подаем плюс или минус. Для удобства можно сделать таблицу кодов для индикатора. Если подключение такое: PD7-h, PD6-g, PD5-f, PD4-e, PD3-d, PD2-c, PD1-b, PD0-a, то для отображения цифры 1 в порт D нужно вывести такой двоичный код: 0b00000110.

Для отображения цифровых данных одного семисегментного индикатора обычно недостаточно. В таких случаях к микроконтроллеру подключают сразу несколько индикаторов. Однако, из-за отсутствия достаточного количества выводов у микроконтроллера применяют специальные методы. Один из таких методов это динамическая индикация. Режим динамической индикации применяют для построения многоразрядных индикаторов. При таком режиме разряды индикатора работают не одновременно, а по очереди. Переключение разрядов происходит с большой скоростью (50 Гц), из-за этого человеческий глаз не замечает , что индикаторы работают по очереди. Так как у светодиодов очень малая инерционность, сменяющиеся разряды сливаютя в одно изображение. В этом режиме в каждый момент времени работает только один разряд, включаются по очереди начиная с первого заканчивая последним, затем все начинается сначала.

Сделаем простой секундомер. Отсчет секунд будет производится на четырехразрядном индикаторе (с общим анодом) от 0 до 9999. В нашей программе используем процедуру прерывания по таймеру, т.е. смена разряда индикатора будет происходить каждый раз когда таймер досчитает до конца(до 255). Используем восьмиразрядный таймер/счетчик Т2, он будет работать в нормальном режиме. Но обычно для реализации динамической индикации используют режим СТС (сброс при совпадении), это режим, при котором частота возникновения прерываний по совпадению значений счетчика таймера и регистра OCR2 определяется содержимым OCR2 и предделителем тактовой частоты таймера. При таком режиме работы таймера можно легко изменять частоту обновления разрядов, записывая в регистр сравнения OCR2 необходимое значение, предварительно расчитанное. Частоту обновления разрядов делают обычно 50Hz или больше, так как у нас 4 разряда, частота обновления будет равна 200Hz. Подсчитаем частоту обновления для нашего примера: тактовая частота равна 8MHz, предделитель сделаем на 8. На вход таймера будут поступать импульсы частотой 1MHz. Тогда таймер будет увеличивать значение каждые 1 микросекунду, переполняться он будет каждые 255*0,000001 = 255 мкс. Частота обновления будет равна 1/255мкс = 3921Hz.

Принцип действия динамической индикации - схема

Каждый раз по прерыванию мы должны в обработчике сначала погасить все индикаторы, затем выбрать из заранее подготовленного массива выводимых символов очередной символ, вывести его в порт D, а потом установить лог. 1 на линию порта В, которая соответствует следующему индикатору. Таким образом мы сможем обновлять поочередно информацию на индикаторах, что создаст эффект их непрерывного свечения. Выводить двоичный код в порт D будем согласно таблице, приведенной ниже.

Источник

Введение

Для отображения цифровой информации в системах на базе микроконтроллеров используются светодиодные семисегментные индикаторы. Они просты в управлении, имеет высокую яркость, широкий диапазон рабочих температур и низкую стоимость. К недостаткам светодиодных индикаторов относятся – высокое энергопотребление, отсутствие управляющего контроллера и скудные возможности по выводу буквенной информации.
Светодиодный семисегментный индикатор представляет собой группу светодиодов расположенных в определенном порядке и объединенных конструктивно. Зажигая одновременно несколько светодиодов можно формировать на индикаторе символы цифр. Индикаторы различаются по типу соединения светодиодов – общий анод, общий катод, по количеству отображаемых разрядов – однораразрядные, двух разрядные и т.д. и по цвету – красные, зеленые, желтые и т.д.

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

Динамическое управление (динамическая индикация) подразумевает поочередное зажигание разрядов индикатора с частотой, не воспринимаемой человеческим глазом. Схема подключения индикатора в этом случае на порядок экономичнее благодаря тому, что одинаковые сегменты разрядов индикатора объединены.

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

Чтобы зажечь на индикаторе какую-то цифру нужно настроить порты, к которым подключен индикатор, в режим выхода, “открыть” транзистор (в данном случае подать на базу “единицу”) и установить в порту микроконтроллера её код.
В зависимости от того, куда подключены сегменты индикатора – коды могут быть разные. Для нашего случая коды цифр будут выглядеть так.

unsigned char number[] =
<
0x3f, //0
0x06, //1
0x5b, //2
0x4f, //3
0x66, //4
0x6d, //5
0x7d, //6
0x07, //7
0x7f, //8
0x6f //9
>;

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

Пример 1. Вывод цифр от 0 до 9
#include
#include

unsigned char number[] =
<
0x3f, //0
0x06, //1
0x5b, //2
0x4f, //3
0x66, //4
0x6d, //5
0x7d, //6
0x07, //7
0x7f, //8
0x6f //9
>;

unsigned char count = 0;
int main( void )
<
//порт, к которому подкл. сегменты
PORTB = 0xff;
DDRB = 0xff;

//вывод, к которому подкл. катод
PORTD |= (1 while (1) <
PORTB = number[count];
count++;
if (count == 10) count = 0;
__delay_cycles (8000000);
>
return 0;
>
Эта программа каждую секунду выводит значение переменной count на семисегментный индикатор. Индикация в данном случае — статическая.

Идем дальше – вывод двух цифр. Настройка портов и коды цифр остаются без изменений, но теперь нам нужно добавить кусок кода, который будет зажигать разряды индикатора по очереди. Частота смены разрядов должна быть достаточно высокой, чтобы свечение индикатора воспринималось без мерцания.

Пример2. Вывод цифр от 0 до 99
#include
#include

Читайте также:  Население и история индии таблица

unsigned char number[] =
<
0x3f, //0
0x06, //1
0x5b, //2
0x4f, //3
0x66, //4
0x6d, //5
0x7d, //6
0x07, //7
0x7f, //8
0x6f //9
>;

unsigned char
count = 0;

//числа для вывода на индикатор
unsigned char data1 = 2;
unsigned char data2 = 5;

int main( void )
<
//порт, к которому подкл. сегменты
PORTB = 0xff;
DDRB = 0xff;

//порт, к которому подкл. катод
PORTD = 0;
DDRD = (1 while (1)<

//гасим оба разряда
PORTD &=

((1 //выводим в порт код цифры
//и зажигаем следующий разряд
if (count == 0) <
PORTB = number[data2];
PORTD |= (1 if (count == 1) <
PORTB = number[data1];
PORTD |= (1 if (count == 2) count = 0;

//частота смены разрядов будет 100 Гц при кварце 8МГц
__delay_cycles (800000);
>
return 0;
>
Эта программа просто выводит любое поразрядно заданное число от 0 до 99.
Частота смены разрядов семисегментного индикатора задается с помощью программной задержки __delay_cycles(). Это не самое удачное решение, потому что добавление каких-нибудь других задач в цикл while будет мешать выводу на индикатор. Давайте организуем смену разрядов индикатора с помощью аппаратного таймера/счетчика Т0

Пример3. Вывод цифр от 0 до 99. Смена разрядов выполняется в прерывании таймера
#include
#include

unsigned char number[] =
<
0x3f, //0
0x06, //1
0x5b, //2
0x4f, //3
0x66, //4
0x6d, //5
0x7d, //6
0x07, //7
0x7f, //8
0x6f //9
>;

//числа для вывода на индикатор
volatile unsigned char data1 = 0;
volatile unsigned char data2 = 0;

int main( void )
<
//порт, к которому подкл. сегменты
PORTB = 0xff;
DDRB = 0xff;

//порт, к которому подкл. катод
PORTD = 0;
DDRD |= (1 //инициализация таймера Т0
//частота прерываний 100Гц при кварце 8МГц
TIMSK = (1 __enable_interrupt ();
while (1) <
//программный счетчик секунд
data1++;
if (data1 == 10) <
data1 = 0;
data2++;
if (data2 == 10) data2 = 0;
>
__delay_cycles (8000000);
>
return 0;
>

//прерывания таймера Т0 — вывод на индикатор
#pragma vector = TIMER0_OVF_vect
__interrupt void Timer0_Ovf( void )
<
static unsigned char count = 0;
TCNT0 = 0xb2;

//гасим оба разряда
PORTD &=

((1 //выводим в порт код цифры
//и зажигаем следующий разряд
if (count == 0) <
PORTB = number[data2];
PORTD |= (1 if (count == 1) <
PORTB = number[data1];
PORTD |= (1 if (count == 2) count = 0;
>
Переменные data1, data2 объявлены с ключевым словом volatile, потому что они используются и в основном коде и в прерывании. В проекте под GCC я забыл поставить его поставить, и компилятор выкинул обе переменные, посчитав их ненужными!

Прерывания таймера происходят параллельно выполнению цикла while. Это позволяет выполнять в цикле какую-нибудь полезную задачу. В данном примере с помощью двух переменных в цикле организован программный счетчик от 0 до 99.
Использовать две восьмиразрядные переменные для организации счетчика от 0 до 99 неудобно и расточительно, ведь такой счетчик можно сделать и на одной переменной типа unsigned char. Хорошо, счетчик мы сделаем, а как вывести его значение на семисегментный индикатор? Нужен код “разбивающий” десятичное число на отдельные разряды и вот как он выглядит:

//программный счетчик
unsigned char counterProg = 35;

//”разбиваем” значение счетчика на отдельные разряды
data1 = counterProg % 10;
data2 = counterProg/10;

data1 = counterProg % 10 – это операция деления по модулю 10 (деление с остатком). Результатом этого выражения будет остаток от деления переменной counterProg на 10, то есть для нашего случая 5.

counterProg/10 – это целочисленное деление на 10. Результатом этого выражения будет число 3.

Таким образом, в переменные data2, data1 будут записаны числа 3 и 5 соответственно, значение счетчика counterProg при этом не изменится.

Пример 4. Вывод цифр от 0 до 99.
Преобразование двоичных чисел в двоично-десятичные (BCD)

#include
#include

unsigned char number[] =
<
0x3f, //0
0x06, //1
0x5b, //2
0x4f, //3
0x66, //4
0x6d, //5
0x7d, //6
0x07, //7
0x7f, //8
0x6f //9
>;

//числа для вывода на индикатор
volatile unsigned char data1 = 0;
volatile unsigned char data2 = 0;

//программный счетчик секунд
unsigned char counterProg = 0;

int main( void )
<
//порт, к которому подкл. сегменты
PORTB = 0xff;
DDRB = 0xff;

//порт, к которому подкл. катод
PORTD = 0;
DDRD |= (1 //инициализация таймера Т0
TIMSK = (1 __enable_interrupt ();
while (1) <
//программный счетчик секунд
counterProg++;
if (counterProg == 100) counterProg = 0;
data1 = counterProg % 10;
data2 = counterProg/10;
__delay_cycles (8000000);
>
return 0;
>

//прерывания таймера Т0 — вывод на индикатор
#pragma vector = TIMER0_OVF_vect
__interrupt void Timer0_Ovf( void )
<
static unsigned char count = 0;
TCNT0 = 0xb2;

//гасим оба разряда
PORTD &=

((1 //выводим код цифры в порт
//и зажигаем следующий разряд
if (count == 0) <
PORTB = number[data2];
PORTD |= (1 if (count == 1) <
PORTB = number[data1];
PORTD |= (1 if (count == 2) count = 0;
>
Следующий этап работы над программой – выделение кода обслуживающего светодиодный семисегментный индикатор в отдельные функции. Какой минимальный набор функций нам необходим? Функция инициализации, функция вывода на индикатор и функция преобразования чисел и записи их в буфер.

Функция инициализации

#define PORT_IND PORTB
#define DDR_IND DDRB
#define PORT_K PORTD
#define DDR_K DDRD
#define KAT1 0
#define KAT2 1

volatile unsigned char data[2];

void IND_Init( void )
<
//порт к которому подкл. сегменты
PORT_IND = 0xff;
DDR_IND = 0xff;

//порт, к которому подкл. катоды
PORT_K &=

((1 //очистка буфера
data[0] = 0;
data[1] = 0;
>

Порты, к которым подключен семисегментный индикатор, определены с помощью директивы #define – в будущем это позволит быстро править код. Вместо двух переменных data1, data2 удобнее использовать массив unsigned char data[2].

Функция преобразования

void IND_Conv( unsigned char value)
<
unsigned char tmp;
tmp = value % 10;
data[0] = number[tmp];
tmp = value/10;
data[1] = number[tmp];
>

Процедура преобразования чисел аналогична описанной выше. Единственное отличие – в буфере (data[]) мы теперь сохраняем не результат преобразования, а коды цифр. Зачем делать в прерывании то, что можно сделать в основном цикле программы?

Функция вывода на индикатор

void IND_Update( void )
<
static unsigned char count = 0;

//гасим оба разряда
PORT_K &=

((1 //выводим в порт код цифры
PORT_IND = data[count];

//зажигаем нужный разряд
if (count == 0) PORT_K |= (1 if (count == 1) PORT_K |= (1 if (count == 2) count = 0;
>

Эта функция будет вызываться в прерывании таймера. В принципе, для экономии ресурсов ее можно было бы сделать встраиваемой.

Пример 5. Код программы с использованием этих функций //программный счетчик секунд
unsigned char counterProg = 0;

int main( void )
<
IND_Init();

//инициализация таймера Т0
TIMSK = (1 __enable_interrupt ();
while (1) <
counterProg++;
if (counterProg == 100) counterProg = 0;
IND_Conv(counterProg);
__delay_cycles (8000000);
>
return 0;
>

//прерывания таймера Т0 – вывод на индикатор
#pragma vector = TIMER0_OVF_vect
__interrupt void Timer0_Ovf( void )
<
TCNT0 = 0xb2;
IND_Update();
>
И, наконец – разбиение программы на модули.

Создаем два файла – indicator.h и indicator.c. Сохраняем их в папке проекта.
В хидер файле у нас будут директивы условной компиляции, макроопределения и прототипы функций.

#ifndef INDICATOR_H
#define INDICATOR_H

#define PORT_IND PORTB
#define DDR_IND DDRB
#define PORT_K PORTD
#define DDR_K DDRD
#define KAT1 0
#define KAT2 1

void
IND_Init( void );
void IND_Conv( unsigned char value);
void IND_Update( void );

#endif //INDICATOR_H

В сишном файле – #include “indicator.h”, объявления переменных и реализация трех функций. Функции описаны выше, поэтому здесь их не привожу.

Подключаем файл indicator.c к проекту.
В файл main.c инклюдим заголовочный файл нашего драйвера семисегментного индикатора — #include “indicator.h”

Все. Теперь мы можем использовать функции для работы с индикатором в файле main.
Полный код драйвера смотрите в проектах.

Продолжение следует… Скоро будет дополнение к этой статье — описание вольтметра на микроконтроллере – в проекте используется 4-ех разрядный семисегментный индикатор.

Источник

Adblock
detector