Как устроен семисегментный индикатор
Перейти к содержимому

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

  • автор:

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

Первым делом нам нужно получить какое-то средство отладки – чтобы можно было искать ошибки (а они неизбежно появятся) и получать какой-то отзыв от контроллера.
Поэтому займемся сперва дисплеем на семисегментных индикаторах.

Рассмотрим сначала, как работает отдельный семисегментный индикатор:

Рисунок 1. Схема семисегментного индикатора с точкой.

Вот так схематично выглядит семисегментный индикатор с точкой.
Устроен он очень просто: есть восемь выводов (по одному на каждый сегмент + точка) и один (или два, которые объединяются вместе перемычкой – на рисунке это 3 и 8) общий вывод, который подключается либо на ноль (семисегментный индикатор с общим катодом), либо к питанию (семисегментный индикатор с общим анодом).
Вот так выглядит внутренняя схема индикатора:

Рисунок 2. Внутреннее устройство семисегментного индикатора с точкой.

Вот как располагаются сегменты:

Рисунок 3. Расположение сегментов.

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

Чтобы загорелся какой-то из сегментов, нужно подать напряжение между общей точкой и соответствующим выводом. Таким образом, и мы подаём напряжение на выводы A, B и C, то на индикаторе загорится «7».

Отдельные семисегментные индикаторы, как видим, подключаются достаточно просто.
Теперь рассмотрим, как подключить несколько индикаторов.
Здесь есть варианты:

Во-первых, можно найти семисегментные индикаторы на 2-3 и больше разрядов, которые будут выглядеть примерно вот так:

Рисунок 4. Схема трёхразрядного семисегментного дисплея.

У таких дисплеев есть восемь выводов для определения индикации (назовем их шиной данных), и несколько (по количеству разрядов) выводов для выбора разряда (шина адреса). Выводы для выбора разряда являются общими катодами или анодами.
Например, у нас трехразрядный индикатор. Попробуем вывести на нём «123»

  1. Чтобы вывести «1» в старшем (крайнем левом) разряде, нам нужно сначала погасить индикатор (отключаем все общие точки), затем выставить на шине данных нужную комбинацию – в данном случае, выводы B и C подключаем к «+», если индикатор с общим катодом, или к «-«, если индикатор с общим анодом — и только потом подключить соответствующую общую точку. После этого необходимо сделать маленькую паузу, чтобы светодиоды успели зажечься.
  2. Для того, чтобы вывести «2», необходимо снова погасить индикатор; выставить на выводах данных обозначение «2» (выводы A, B, D, E, G), а затем подключить нужную общую точку — вывод CA2. И снова пауза.
  3. Аналогично для «3».
  4. И так до бесконечности

Если мы будем достаточно быстро циклически выполнять 1) — 3), то будет сложно заметить мерцание (выключили все разряды – включили первый – маленькая пауза – выключили все разряды – включили второй – маленькая пауза – выключили все разряды – включили третий – маленькая пауза – выключили все разряды – включили первый — …) – будет казаться, что весь дисплей горит ровно.
Вариант второй – у дисплея есть отдельные выводы a-g и DP для каждого разряда – или мы сами составляем дисплей из отдельных индикаторов.
Наша задача – по сути, реализовать первый вариант из подручных средств: будем использовать общие для всех разрядов восемь выводов данных и выводы адреса для выбора разряда.

Теперь о подключении — у нас индикаторы с общим анодом (на шине данных светодиоды включаются «минусом», а на шине адресации разряд выбирается «плюсом»):

Рисунок 5. Схема подключения нескольких отдельных семисегментных индикаторов.

Упрощенная схема представлена на рисунке.
Так, мы просто объединяем выводы a-g, dp для всех индикаторов; «общими» выводами же управляем выбором конкретного индикатора – а дальше можем работать по алгоритму выше.

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

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

Так, теперь можно приступать к программе.
Рассмотрим, что должен уметь «кирпичик» работы с дисплеем, что он получает на вход и на выход.
Во-первых, «кирпичик» должен знать выводы, связанные с дисплеем: нам нужно 8 выводов для шины данных (будем использовать порт D) и 6 выводов для шины адреса (выводы B0 – B5) – требуется функция для инициализации дисплея. При этом нужно учитывать, что наш дисплей – индикаторы с общим анодом.
На вход должна поступать строка, которую мы сможем перевести в символы для семисегментного дисплея; соответственно, нужна функция записи строки в «память дисплея» (в роли памяти будет выступать массив на шесть байтовых элементов).
Ещё мы помним, что для того, чтобы наш дисплей постоянно показывал какую-либо строку, нам нужно часто-часто отображать каждый разряд дисплея – значит, нам потребуется функция, которая будет постоянно вызываться в прерывании.

Для начала попробуем просто выводить какие-то символы на дисплей. При этом у нас и шина данных, и шина адресации «включаются» нулем: шина данных потому, что индикаторы с общим анодом, а шина адресации – из-за транзисторов. Шина данных будет размещаться на выводах порта D, адресная шина – на выводах B0-B5; при этом к выводу B0 подключен самый старший разряд, к выводу B5 – самый младший.
Нужно понять, что «единица», «символ единицы» и «код единицы» — три совершенно разные вещи. Если мы проводим какие-то математические вычисления, то мы используем «единицу» — число или цифру; если мы работаем со строкой – то используем «символ единицы» — некий код из таблицы ACSII; а вот «код единицы» — это то значение, которое мы должны подать на шину данных, чтобы на семисегментном индикаторе загорелся символ единицы (хо-хо, мы снова всех запутаем!)

Вот код для самой простой программки, которая будет просто отображать «012345» на дисплее (используем среду IAR):

//выводим на экран "012345" #include "ioavr.h" #include "inavr.h" #include "stdint.h" //ddr и port для работы с уже выбранным индикатором #define DispDdrDatabus DDRD #define DispPortDatabus PORTD //ddr и port для выбора индикатора #define DispDdrChoose DDRB #define DispPortChoose PORTB #define DISP_CHOOSE_MASK 0x3F #define DISP_SEGMENT_COUNT 6 uint8_t DispCurrSegment, DispCurrSegmentMask; //переменные для хранения для номера текущего индикатора и его маски uint8_t DispMemory[DISP_SEGMENT_COUNT] = ; //непосредственно сама память дисплея //функция для перерисовки дисплея void RedrawDisplay(void) < DispPortChoose |= DISP_CHOOSE_MASK; //не выбираем ни одного индикатора DispPortDatabus = DispMemory[DispCurrSegment]; //настраиваем шину данных DispPortChoose = (DispPortChoose | DISP_CHOOSE_MASK) & (˜DispCurrSegmentMask); //выбираем нужный индикатор //определяем следующий сегмент и его маску if (DispCurrSegment < DISP_SEGMENT_COUNT - 1) < DispCurrSegment++; DispCurrSegmentMask = DispCurrSegmentMask else //если переходим на первый сегмент - обнуляем счётчик и меняем маску < DispCurrSegment = 0; DispCurrSegmentMask = 1; >> //функция инициализации дисплея void DisplayInit() < DispDdrChoose |= DISP_CHOOSE_MASK; //все выводы, относящиеся к дисплею - на выход DispPortChoose = 0xFF; //не выбираем ни одного индикатора DispDdrDatabus = 0xFF; DispPortDatabus = 0xFF; //и не выводим ничего на шину данных DispCurrSegment = 0; //определяем, что текущий элемент - нулевой DispCurrSegmentMask = 1; //соответственно, маска для нулевого элемента >void main( void ) < DDRB = 0; PORTB = 0; DDRD = 0; PORTD = 0; DDRC = 0; PORTC = 0; DisplayInit(); while(1) < RedrawDisplay(); >>

Итак, у нас есть память – массив DispMemory; в нем по умолчанию записана строка с кодами символов 012345 (не путать с самими символами!). Чтобы получить эти коды, можно просто вычислять значения с помощью «распиновки» — см. рисунок … — или можно, например, использовать простенькие программки типа приложения «Seven Segment Editor» в среде MikroC.
Также есть переменные DispCurrSegment – показывает номер текущего работающего индикатора (он же номер текущего отображаемого элемента в массиве DispMemory), и DispCurrSegmentMask – соответственно, маска для текущего индикатора для шины адресации.
Для работы используются две функции – функция инициализации (ну, тут все понятно) и функция перерисовки дисплея. Последняя делает следующие действия:

  • выключает дисплей через шину адресации
  • выставляет на шине данных нужное значение
  • включает нужный индикатор
  • переходит на следующий индикатор и изменяет маску

В принципе, все как мы и планировали выше.
Но есть несколько проблем:
Самое главное – это то, что нельзя вызывать функцию перерисовки дисплея в главной функции, так как в main-е в дальнейшем у нас будет вызываться множество функций, а перерисовка дисплея критична ко времени (чтобы убедиться в этом, просто добавьте задержку после вызова функции RedrawDisplay – на 5 мс изображение заметно дрожит, на 10 – раздражающе перемигивает)
Что ж, делать нечего – используем прерывание!

//добавляем прерывание //выводим на экран "012345" #include "ioavr.h" #include "inavr.h" #include "stdint.h" //ddr и port для работы с уже выбранным индикатором #define DispDdrDatabus DDRD #define DispPortDatabus PORTD //ddr и port для выбора индикатора #define DispDdrChoose DDRB #define DispPortChoose PORTB #define DISP_CHOOSE_MASK 0x3F #define DISP_SEGMENT_COUNT 6 uint8_t DispCurrSegment, DispCurrSegmentMask; //переменные для хранения для номера текущего индикатора и его маски uint8_t DispMemory[DISP_SEGMENT_COUNT] = ; //непосредственно сама память дисплея //прерывание для перерисовки дисплея void RedrawDispInterrupt(void) < DispPortChoose |= DISP_CHOOSE_MASK; //не выбираем ни одного индикатора DispPortDatabus = DispMemory[DispCurrSegment]; //настраиваем шину данных DispPortChoose = (DispPortChoose | DISP_CHOOSE_MASK) & (~DispCurrSegmentMask); //выбираем нужный индикатор //определяем следующий сегмент и его маску if (DispCurrSegment < DISP_SEGMENT_COUNT - 1) < DispCurrSegment++; DispCurrSegmentMask = DispCurrSegmentMask else //если переходим на первый сегмент - обнуляем счётчик и меняем маску < DispCurrSegment = 0; DispCurrSegmentMask = 1; >> //функция инициализирует дисплей void DisplayInit() < DispDdrChoose |= DISP_CHOOSE_MASK; //все выводы, относящиеся к дисплею - на выход DispPortChoose = 0xFF; //не выбираем ни одного индикатора DispDdrDatabus = 0xFF; DispPortDatabus = 0xFF; //и не выводим ничего на шину данных DispCurrSegment = 0; //определяем, что текущий элемент - нулевой DispCurrSegmentMask = 1; //соответственно, маска для нулевого элемента >//инициализация таймера Т0 void FastTimerInit() < __disable_interrupt(); TCCR0A = 0; TCCR0B = (1 //прерывание таймера Т0 #pragma vector = TIMER0_OVF_vect __interrupt void FastTimerInterrupt(void) < RedrawDispInterrupt(); //перерисовка дисплея >void main( void ) < DDRB = 0; PORTB = 0; DDRD = 0; PORTD = 0; DDRC = 0; PORTC = 0; DisplayInit(); FastTimerInit(); while(1) < >>

Смотрим, что изменилось, а что нет: функция RedrawDisplay просто поменяла название и стала вызываться в прерывании. Добавились функции для таймера – инициализация (таймер 0 с предделителем 8 и прерыванием по переполнению) и, соответственно, сама функция прерывания.
Так, отлично. Теперь у нас есть возможность делать что-то в основном цикле, и это никак не будет влиять на работу дисплея.
Следующая задача – это писать на дисплее то, что нам хочется.
Есть несколько вариантов реализации: во-первых, можно сделать просто – вызываем функцию, передаём туда код для дисплея, записываем его в массив DispMemory. Но! Работать с кодами очень, очень неудобно – совершенно непонятно, что мы передаём в данный момент.
Гораздо удобней передавать в функцию строку того, что мы хотим отобразить, внутри функции перекодировать эту строку в код и переписывать массив DispMemory. Но тогда нам понадобится хранить «алфавит дисплея» — пары «символ-код». Алфавит наш, конечно, будет несколько… своеобразным: часть букв будет, естественно, пропущена – не все можно отобразить через семисегментный дисплей – также будут присутствовать цифры, точка, пробел и так далее.
Так, пусть мы определили наш алфавит:

//массив "символ-код" //по "договорённости" размещаем сначала цифры от 0 до F #define DISP_SYMBOL_COUNT 37 uint8_t DispSymbolCodeArr[2][DISP_SYMBOL_COUNT] = '>, >;

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

Рисунок 7. Алгоритм функции записи символов в память дисплея.

Вот код новой функции:

//массив "символ-код" //по "договорённости" размещаем сначала цифры от 0 до F #define DISP_SYMBOL_COUNT 37 uint8_t DispSymbolCodeArr[2][DISP_SYMBOL_COUNT] = '>, >; const uint8_t DispBlankSymbol = ' '; const uint8_t DispBlankCodeIndex = 17; const uint8_t DispPointSymbol = '.'; const uint8_t DispPointCodeIndex = 18; … //изменение строки, которая будет записываться на дисплей; строка должна иметь SegmentCount символов минимум или заканчиваться 0 //ключевое слово "__monitor" запрещает прерывания при выполнении функции __monitor void DisplayShowStr(char* Str) < int8_t currDispMemoryIndex, currSymbolIndex; uint8_t* currStrSymbol; currDispMemoryIndex = 0; if (Str) //если строка существует < currStrSymbol = (uint8_t*) Str; //определяем текущий символ - первый while ((currDispMemoryIndex < DISP_SEGMENT_COUNT) && (*currStrSymbol != 0)) //до конца строки или пока есть непереписанные сегменты < //ищем текущий символ в таблице соответствий "Символ-код" currSymbolIndex = 0; while ((*currStrSymbol != DispSymbolCodeArr[0][currSymbolIndex]) && (currSymbolIndex < DISP_SYMBOL_COUNT)) currSymbolIndex++; if (currSymbolIndex < DISP_SYMBOL_COUNT) //если нашли символ DispMemory[currDispMemoryIndex] = DispSymbolCodeArr[1][currSymbolIndex]; else //если не нашли - записываем пробел DispMemory[currDispMemoryIndex] = DispSymbolCodeArr[1][DispBlankCodeIndex]; currDispMemoryIndex++; //перешли на следующее знакоместо currStrSymbol++; //перешли на следующий записываемый символ >> //если строка оказалась меньше 6 символов - дописываем пробелы for (; currDispMemoryIndex < DISP_SEGMENT_COUNT; currDispMemoryIndex++) //до конца памяти дисплея DispMemory[currDispMemoryIndex] = DispSymbolCodeArr[1][DispBlankCodeIndex]; //записываем пробел >void main( void ) < DDRB = 0; PORTB = 0; DDRD = 0; PORTD = 0; DDRC = 0; PORTC = 0; DisplayInit(); FastTimerInit(); while(1) < DisplayShowStr("123456.7"); __delay_cycles(16000000); DisplayShowStr("AB.CD"); __delay_cycles(16000000); >>

Для того, чтобы во время выполнения функции прерывание с перерисовыванием дисплея не вызывалось, используем перед функцией ключевое слово «__monitor» — оно запрещает прерывания при выполнении функции.
Также для упрощения записи пробелов мы отдельно вынесли индекс символа пробела из массива.

Рисунок 8. Отображение строки с отдельно стоящей точкой.

Получилась вот какая проблема: точка стала занимать отдельное место, хотя логичней будет приписать её к предыдущему символу.
Тогда нам добавить в функцию два случая: первый – это когда встречается точка в середине строки – тогда мы дописываем к предыдущему символу код точки (так, код символа «С» без точки – 0хС6 = 11000110; код символа «С» с точкой – 0x46 = 01000110) – иными словами, к предыдущему символу нужно нужно применить побитовое И с кодом точки 0x7F = 01111111.
Второй случай – когда точку нужно добавить в конце строки – то есть когда точка – символ № DISP_SYMBOL_COUNT + 1.

//изменение строки, которая будет записываться на дисплей; строка должна иметь SegmentCount символов минимум или заканчиваться 0 //ключевое слово "__monitor" запрещает прерывания при выполнении функции __monitor void DisplayShowStr(char* Str) < int8_t currDispMemoryIndex, currSymbolIndex; uint8_t* currStrSymbol; currDispMemoryIndex = 0; if (Str) //если строка существует < currStrSymbol = (uint8_t*) Str; //определяем текущий символ - первый while ((currDispMemoryIndex < DISP_SEGMENT_COUNT) && (*currStrSymbol != 0)) //до конца строки или пока есть непереписанные сегменты < //если наш символ - точка, и она стоит не в начале строки, то к предыдущему значению приписываем '.' if ((*currStrSymbol == DispPointSymbol) && (currStrSymbol != (uint8_t*)Str)) < DispMemory[currDispMemoryIndex - 1] &= DispSymbolCodeArr[1][DispPointCodeIndex]; >else //иначе ищем текущий символ в таблице соответствий "Символ-код" < //ищем текущий символ в таблице соответствий "Символ-код" currSymbolIndex = 0; while ((*currStrSymbol != DispSymbolCodeArr[0][currSymbolIndex]) && (currSymbolIndex < DISP_SYMBOL_COUNT)) currSymbolIndex++; if (currSymbolIndex < DISP_SYMBOL_COUNT) //если нашли символ DispMemory[currDispMemoryIndex] = DispSymbolCodeArr[1][currSymbolIndex]; else //если не нашли - записываем пробел DispMemory[currDispMemoryIndex] = DispSymbolCodeArr[1][DispBlankCodeIndex]; currDispMemoryIndex++; //перешли на следующее знакоместо >currStrSymbol++; //перешли на следующий записываемый символ > > //свободные сегменты вроде кончились, но вдруг нам нужно записать ещё только точку? if((*currStrSymbol == DispPointSymbol) && (currDispMemoryIndex == DISP_SEGMENT_COUNT)) DispMemory[currDispMemoryIndex - 1] &= DispSymbolCodeArr[1][DispPointCodeIndex]; //если строка оказалась меньше 6 символов - дописываем пробелы for (; currDispMemoryIndex < DISP_SEGMENT_COUNT; currDispMemoryIndex++) //до конца памяти дисплея DispMemory[currDispMemoryIndex] = DispSymbolCodeArr[1][DispBlankCodeIndex]; //записываем пробел >

Рисунок 9. Отображение строки с точкой, присоединяющейся к предыдущему символу.

Итак, теперь у нас уже есть дисплей, который будет отображать произвольные строки из символов алфавита!
Что нужно ещё для счастья?
Возвращаемся к нашему моделированию – шла речь о том, чтобы при настройке желаемой температуры или таймера значение на дисплее мигало.
Что есть мигание – это попеременное включение и выключение дисплея. Так, за включение-выключение и отображение информации на дисплее отвечает функция, вызываемая в прерывании – её-то и попробуем модифицировать!

Так, прерывание у нас вызывается очень часто – раз в 256 мкс, а мигание должно происходить так, чтобы это было не раздражающе для глаза. Ищем в прерывании место, которое вызывается реже всего:

Рисунок 10. Поиск наиболее редко вызываемого места в прерывании.

Итак, смена адреса текущего индикатора на нулевой (окончание очередной полной отрисовки дисплея) происходит реже всего, а именно:
КОЛИЧЕСТВО_ИНДИКАТОРОВ * ЧАСТОТА_ВЫЗОВА_ПРЕРЫВАНИЯ = 6 * 256 мкс = 1536 мкс ˜ 1.5 мс
Уже неплохо, но все ещё слишком часто для того, чтобы вставить в это место включение-выключение дисплея – при такой частоте мигание будет просто-напросто незаметно, дисплей будет просто тускло светиться.
Что же делать в случаях, когда таймер вызывается слишком часто? Счётчик в счётчике – введем переменную, которая будет увеличиваться каждый раз при попадании в переход на нулевой индикатор. По достижению максимума мы и будем работать с миганием.
Теперь посмотрим, как реализовать это самое мигание, то есть включать-выключать дисплей в нужный момент – и так, чтобы потратить на это минимум времени и изменить минимум кода в основной функции. Пляшем от того, что мы будем редактировать ту часть функции, где происходит переход на нулевой индикатор – именно это и определяет «включенность» дисплея! В этом месте мы задаём маску для текущего индикатора, а дальше весь цикл отображения памяти мы просто эту маску сдвигаем.
А теперь представим, что вместо маски для нулевого индикатора мы не выбираем индикатора вообще – тогда в дальнейшем все сдвиги будут «пустые», и дисплей будет выключен! Вот то, что нам нужно!

Рисунок 11. Алгоритм реализации мигания в прерывании.

Получили следующий код:

//переменные для работы с миганием: флаг включенности режима мигания, текущая фаза мигания (дисплей включён-выключен), счётчик для смены фазы мигания uint8_t DispBlinkEnabled, DispBlinkCurrMode, dispBlinkModeSwitchCounter; #define DISP_BLINK_MODE_SWITCH_MAX_COUNTER 255 //длительность мигания дисплея //прерывание для перерисовки дисплея void RedrawDispInterrupt(void) < DispPortChoose |= DISP_CHOOSE_MASK; //не выбираем ни одного индикатора DispPortDatabus = DispMemory[DispCurrSegment]; //настраиваем шину данных DispPortChoose = (DispPortChoose | DISP_CHOOSE_MASK) & (˜DispCurrSegmentMask); //выбираем нужный индикатор //определяем следующий сегмент и его маску if (DispCurrSegment < DISP_SEGMENT_COUNT - 1) < DispCurrSegment++; DispCurrSegmentMask = DispCurrSegmentMask else //если переходим на первый сегмент - обнуляем счётчик и меняем маску < DispCurrSegment = 0; if(DispBlinkEnabled) //если включён режим мигания < dispBlinkModeSwitchCounter++; //увеличиваем счётчик if (dispBlinkModeSwitchCounter == DISP_BLINK_MODE_SWITCH_MAX_COUNTER) //если выждали время, когда дисплей был включен или выключен - пора интвертироваться < dispBlinkModeSwitchCounter = 0; DispBlinkCurrMode = !DispBlinkCurrMode; //первый бит будет либо 1 (тогда ниже маска будет равняться первому сегменту), либо 0 - тогда будет пройден цикл без отображения на дисплей >DispCurrSegmentMask = DispBlinkCurrMode & 1; > else DispCurrSegmentMask = 1; //если выключен режим мигания, то маска просто для первого сегмента > >

Отлично!
По сути своей, мы сделали то, что хотели – теперь осталось навести красоту: написать отдельные функции для включения-выключения мигания, также впоследствии мы напишем специальные функции для отображения температуры, времени, различных настроек и т.д.
Затем нужно будет вынести функции и переменные, связанные с дисплеем, в отдельную библиотеку (выделить файл заголовка ‘.h’ и файл ‘.c’).
Итак, вот версия с выделенной отдельно библиотекой дисплея – проект сделан в среде IAR Embedded Workbench IDE.

А вот отдельно прошивка.

Пример работы библиотеки

Как видно, мы перевернули последние два индикатора — это сделано для того, чтобы корректно отображать температуру, а именно точку для градуса Цельсия: «°C»; при этом сегменты подключены к основной шине таким образом, чтобы можно было выводить на них символы без искажений, как и для остальных индикаторов.

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

В этой статье мы поговорим о цифровой индикации.
Семисегментные светодиодные индикаторы предназначены для отображения арабских цифр от 0 до 9 (рис.1).
Рис.1. Такие индикаторы бывают одноразрядные, которые отображают только одно число, но семисегментных групп, объединенных в один корпус может быть и больше (многоразрядные). В этом случае цифры разделяются децимальной точкой (рис.2)
Рис.2. Индикатор называется семисегментным из-за того, что отображаемый символ строится из отдельных семи сегментов. Внутри корпуса такого индикатора находятся светодиоды, каждый из которых засвечивает свой сегмент.
Буквы и другие символы на таких индикаторах отображать проблематично, поэтому для этих целей используются 16-сегментные индикаторы. Светодиодные индикаторы бывают двух типов.
В первом из них все катоды, т.е. отрицательные выводы всех светодиодов, объединены вместе и для них выделен соответствующий вывод на корпусе.
Остальные выводы индикатора соединены к аноду каждого из светодиодов (рис.3, а). Такая схема называется «схема с общим катодом».
Также существуют индикаторы, у которых светодиоды каждого из сегментов подключены по схеме с общим анодом (рис.3, б).
Рис.3. Каждый сегмент обозначен соответствующей буквой. На рисунке 4 представлено их расположение.

Рис.4. В качестве примера рассмотрим двухразрядный семисегментный индикатор GND-5622As-21 красного свечения. Кстати существуют и другие цвета, в зависимости от модели.
С помощью трехвольтовой батарейки можно включать сегменты, а если объединить группу выводов в кучку и подать на них питание, то можно даже отображать цифры. Но такой метод является неудобным, поэтому для управления семисегментными индикаторами используют регистры сдвига и дешифраторы. Также, нередко, выводы индикатора подключаются напрямую к выходам микроконтроллера, но лишь в том случае когда используются индикаторы с низким потреблением тока. На рисунке 5 представлен фрагмент схемы с использованием PIC16F876A.
Рис.5. Для управления семисегментным индикатором часто используется дешифратор К176ИД2.
Эта микросхема способна преобразовать двоичный код, состоящий из нулей и единиц в десятичные цифры от 0 до 9. Чтобы понять, как все это работает, нужно собрать простую схему (рис.6). Дешифратор К176ИД2 выполнен в корпусе DIP16. Он имеет 7 выходных вывода (выводы 9 — 15), каждый из которых предназначен для определенного сегмента. Управление точкой здесь не предусмотрено. Также микросхема имеет 4 входа (выводы 2 — 5) для подачи двоичного кода. На 16-й и 8-ой вывод подается плюс и минус питания соответственно. Остальные три вывода являются вспомогательными, о них я расскажу чуть позже.
Рис.6. DD1 — К176ИД2
R1 — R4 ( 10 — 100 кОм)
HG1 — GND-5622As-21 В схеме присутствует 4 тумблера (можно любые кнопки), при нажатии на них на входы дешифратора подается логическая единица от плюса питания. Кстати питается сама микросхема напряжением от 3 до 15 Вольт. В данном примере вся схема питается от 9-вольтовой «кроны». Также в схеме присутствует 4 резистора. Это, так называемые, подтягивающие резисторы. Они нужны, чтобы гарантировать на логическом входе низкий уровень, при отсутствии сигнала. Без них показания на индикаторе могут отображаться некорректно. Рекомендуется использовать одинаковые сопротивления от 10 кОм до 100 кОм. На схеме выводы 2 и 7 индикатора HG1 не подключены. Если подключить к минусу питания вывод DP, то будет светиться децимальная точка. А если подать минус на вывод Dig.2, то будет светиться и вторая группа сегментов (будет показывать тот же символ). Входы дешифратора устроены так, что для отображения на индикаторе чисел 1, 2, 4 и 8 требуется нажатие лишь одной кнопки (на макете установлены тумблеры, соответствующие входам D0, D1, D2 и D3). При отсутствии сигнала отображается цифра ноль. При подаче сигнала на вход D0 отображается цифра 1. И так далее. Для отображения других цифр требуется нажатие комбинации тумблеров. А какие именно нужно нажимать нам подскажет таблица 1.
Таблица 1.

Чтобы отобразить цифру «3» необходимо логическую единицу подать на вход D0 и D1. Если подать сигнал на D0 и D2, то отобразится цифра «5» (рис.6).
Рис.6. Здесь представлена расширенная таблица, в которой мы видим не только ожидаемую цифру, но и те сегменты (a — g), которые составят эту цифру.
Таблица 2. Вспомогательными являются 1, 6 и 7-ой выводы микросхемы (S, M, К соответственно). На схеме (рис.6) 6-ой вывод «М» заземлен (на минус питания) и на выходе микросхемы присутствует положительное напряжение для работы с индикатором с общим катодом. Если используется индикатор с общим анодом, то на 6-ой вывод следует подать единицу. Если на 7-ой вывод «К» подать логическую единицу, то знак индикатора гасится, ноль разрешает индикацию. В схеме данный вывод заземлен (на минус питания). На первый вывод дешифратора подана логическая единица (плюс питания), что позволяет отображать преобразованный код на индикатор. Но если подать на данный вывод (S) логический ноль, то входы перестанут принимать сигнал, а на индикаторе застынет текущий отображаемый знак. Стоит заметить одну интересную вещь: мы знаем, что тумблер D0 включает цифру «1», а тублер D1 цифру «2». Если нажать оба тумблера, то высветится цифра 3 (1+2=3). И в других случаях на индикатор выводится сумма цифр, составляющих эту комбинацию. Приходим к выводу, что входы дешифратора расположены продуманно и имеют очень логичные комбинации. Также вы можете посмотреть видео к этой статье.

rafo Опубликована: 31.05.2015 0 4

Вознаградить Я собрал 0 4

Оценить статью

  • Техническая грамотность

Оценить Сбросить

Средний балл статьи: 4.7 Проголосовало: 4 чел.

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

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

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

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

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

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

12 недорогих наборов электроники для самостоятельной сборки и пайки

Моя личная подборка конструкторов с Aliexpress «сделай сам» для пайки от простых за 153 до 2500 рублей. Дочке 5 лет — надо приучать к паяльнику))) — пусть пока хотя-бы смотрит — переходи посмотреть, один светодиодный куб чего только стоит

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

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

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

Виды семисегментных индикаторов и обозначение на схеме

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

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

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

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

семисегментный индикатор обозначение на схемах

В действительности же, помимо основных выводов, каждый семисегментный индикатор также имеет общий вывод с общим анодом (ОА) или общим катодом (ОК)

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

Внутренняя схема семисегментного индикатора с общим анодом будет выглядеть вот так:

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

а с общим катодом вот так:

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

Если семисегментный индикатор у нас с общим анодом (ОА), то в схеме мы должны на этот вывод подавать «плюс» питания, а если с общим катодом (ОК) — то «минус» или землю.

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

У нас имеются в наличии вот такие индикаторы:

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

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

Как вы видите ниже на фото, у нас загорелся проверяемый сегмент. Таким же образом проверяем и другие сегменты. Если все сегменты горят, то такой индикатор целый и его можно использовать в своих разработках.

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

Иногда напряжения на мультиметре не хватает для проверки сегмента. Поэтому, берем блок питания, и выставляем на нем 5 Вольт. Чтобы ограничить ток через сегмент, проверяем через резистор на 1-2 Килоома.

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

Таким же образом проверяем индикатор от китайского приемника

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

В схемах семисегментные индикаторы соединяются с резисторами на каждом выводе

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

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

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

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

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

Товары из офиса нельзя заказать через интернет или забронировать. Можно только прийти, схватить и бежать. Доступное количество актуально на момент загрузки страницы.

Офис находится в 3 минутах ходьбы от м. Парк культуры по адресу: ул. Тимура Фрунзе, 8/5.

5 шт. Магазин-мастерская, м. Лиговский пр-т
Магазин-мастерская, м. Лиговский пр-т

Товары из магазина-мастерской нельзя заказать через интернет или забронировать. Можно только прийти, схватить и бежать. Доступное количество актуально на момент загрузки страницы.

Магазин-мастерская находится в трёх минутах пешком от метро Лиговский Проспект на территории пространства «Лофт Проект Этажи» по адресу Лиговский проспект 74Д.

Индикатор Kingbright SC56-11GWA состоит из 8 независимых светодиодов: 7 из них формируют различные цифры или символы, а ещё один отображает точку в нижнем правом углу.

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

Подключение

Ножки индикатора позволяют установить его на макетную плату для удобного прототипирования.

Контакты 3 и 8 (общий катод) должны быть соединены с землёй, а на остальные подаётся напряжение, когда нужно зажечь соответствующий сегмент.

Светодиодные сегменты подключаются через токоограничивающие резисторы. Например, для подключения анодов к источнику питания 5 В подойдут резисторы на 220 Ом.

Если подключать индикатор напрямую к микроконтроллеру, это займёт сразу 8 пинов, что слишком накладно для вывода одного разряда. Вместо этого целесообразно взять 7-сегментный драйвер или выходной сдвиговый регистр, чтобы снизить количество занятых цифровых пинов до трёх.

Комплектация

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

Характеристики

  • Модель: Kingbright SC56-11GWA
  • Количество разрядов: 1
  • Цвет светодиодов: зелёный
  • Размеры: 12,7×19×8 мм
  • Размеры (с ногами): 12,7×19×12 мм

Ресурсы

  • Datasheet на Kingbright SC56-11GWA
  • Как подключить семисегментный индикатор к Arduino

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

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