В этой статье мы рассмотрим счетчик 0-99 на двух символьном семисегментном дисплее под управлением микроконтроллера ATmega32 (семейство AVR). Мы будем подсчитывать число событий основываясь на числе нажатий кнопки.
Принцип работы семисегментного дисплея
Но прежде чем идти дальше, кратко остановимся на том, что такое семисегментный дисплей. Этот дисплей получил свое название исходя из того факта, что он имеет семь светящихся сегментов. Каждый из этих сегментов содержит светодиод. Диаграмма контактов семисегментного дисплея показана на рисунке ниже.
Светодиоды в таком дисплее установлены таким образом, что каждый из них содержит свой собственный сегмент. Важная вещь, которую здесь необходимо отметить, светодиоды в семи сегментном дисплее могут быть упорядочены в общем анодном режиме (положительном) или в общем катодном режиме (отрицательном). Соединение цепей семисегментного дисплея для этих режимов показано на следующем рисунке.
Как мы можем видеть, в катодном режиме (Common Cathode) отрицательные выводы светодиодов соединены вместе и названы "землей (GND)". В анодном режиме (Common Anode) положительные выводы светодиодов соединены вместе и названы "напряжением постоянного тока (VCC)". Эти режимы имеют значение (то есть их надо учитывать) когда мы объединяем несколько семи сегментных дисплеев в одно целое.
Чтобы человеческий глаз не замечал мерцания светодиодов семисегментного индикатора их необходимо переключать с частотой не менее 50 Гц.
Более подробно подключение семисегментного дисплея к микроконтроллеру AVR вы можете изучить в следующих статьях на нашем сайте:
- семисегментный светодиодный индикатор: описание, подключение к микроконтроллеру;
- перевод двоичного кода десятичного числа в код семисегментного индикатора. Программа вывода цифры на одноразрядный светодиодный индикатор;
- многоразрядный семисегментный индикатор: организация динамической индикации, алгоритм работы, программа индикации.
Необходимые компоненты
Аппаратное обеспечение
- Микроконтроллер ATmega32 (купить на AliExpress).
- Программатор AVR-ISP (купить на AliExpress), USBASP (купить на AliExpress) или другой подобный.
- Семисегментный дисплей HDSP5503 (2 шт.) (купить на AliExpress).
- Конденсатор 47 мкФ (купить на AliExpress).
- Конденсатор 100 нФ (3 шт.) (купить на AliExpress).
- Кнопка (3 шт.).
- Резистор 220 Ом (2 шт.) (купить на AliExpress).
- Резистор 10 кОм (2 шт.) (купить на AliExpress).
- Резистор 1 кОм (купить на AliExpress).
- Транзистор 2N2222 (2 шт.) (купить на AliExpress).
- Источник питания с напряжением 5 Вольт.
Реклама: ООО "АЛИБАБА.КОМ (РУ)" ИНН: 7703380158
Программное обеспечение
- Atmel Studio версии 6.1 (или выше).
- Progisp или flash magic (необязательно).
Работа схемы
Схема устройства приведена на следующем рисунке.
Соединения, которые необходимо сделать для семи сегментного дисплея, следующие:
PIN1 или e to PIN (A, 4)
PIN2 или d to PIN (A, 3)
PIN4 или c to PIN (A, 2)
PIN5 или h или DP to PIN (A, 7) /// не обязательно поскольку мы не используем десятичную запятую
PIN6 или b to PIN (A, 1)
PIN7 или a to PIN (A, 0)
PIN9 или f to PIN (A, 5)
PIN10 или g to PIN (A, 6)
PIN3 или PIN8 или CC к коллектору транзистора
На представленной схеме два семисегментных дисплея делят один и тот же порт данных микроконтроллера AVR ATmega32, общие катоды дисплеев соединены с двумя коллекторами разных транзисторов. С учетом принципа мультиплексирования мы будем включать и выключать с нужной частотой светодиоды дисплеев.
На схеме у нас есть два транзистора, на каждый из которых подается управляющий ток с дисплеев. Мы будем включать и выключать оба дисплея попеременно с интервалом времени 10 мс. Таким образом, сначала первый дисплей будет включен на 10 мс, а второй в это время будет выключен, потом второй дисплей будет включен на 10 мс, а первый в это время будет выключен и т.д. При этом частота переключения дисплеев будет достаточна для того чтобы человеческий воспринимал их как непрерывно горящими, хотя на самом деле это не так.
В схеме присутствуют две кнопки: одна используется для увеличения значения счетчика, а другая – для уменьшения. Конденсаторы, включенные параллельно кнопкам, используются для устранения эффектов биений при нажатии кнопок. Если их удалить, то возможны ситуации, когда микроконтроллер будет воспринимать однократные нажатия кнопок как многократные.
Резисторы, подключенные к контактам микроконтроллера, служат для ограничения тока, когда происходит нажатие кнопки на эти контакты подается "земля". Аналогично, на контакты микроконтроллера, к которым подключены кнопки, при их нажатии подается "земля" – таким образом микроконтроллер узнает о том, что была нажата кнопка и предпринимает соответствующие действия (в зависимости от того какая кнопка была нажата).
Объяснение работы программы
Программа для рассматриваемой схемы представлена следующим фрагментом кода. Комментарии к коду программы поясняют принцип работы отдельных команд.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
#include <avr/io.h> // заголовок чтобы разрешить контроль данных на контактах #define F_CPU 1000000 // задание тактовой частоты #include <util/delay.h> // заголовок чтобы задействовать функции задержки в программе int main(void) { DDRB = 0x00; // установка portB в режим ввода данных DDRA = 0xFF; // установка porta в режим вывода данных DDRD = 0b11111111; // установка portd в режим вывода данных int DISPLAY1 [10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x67}; // значения символов на дисплее в диапазоне 0-9 int c = 0; int i=0; int d = 0; int one = 0; // память (переменная) для хранения числа единиц int ten =0; // память (переменная) для хранения числа десятков while(1) { if (bit_is_clear(PINB,0)) // когда кнопка 1 нажата { if (i<21) { i++; // увеличение целого числа ‘i’ на единицу если оно меньше 21 } } if (bit_is_clear(PINB,1)) // когда кнопка 2 нажата { if (d<21) { d++; // увеличение целого числа ‘d’ на единицу если оно меньше 21 } } if (i>20) // если ‘i’ было выполнено более чем 21 раз { if (c<99) // если значение счетчика меньше 99 { c++; // увеличение значения счетчика } i=0; // присваиваем i ноль } if (d>20) // если ‘d’ было выполнено более чем 21 раз { if (c>0) // если значение счетчика больше чем 0 { c--; // уменьшение значения счетчика на 1 } d=0; // присваиваем d ноль } if (c<10) // если значение счетчика меньше 10 { one = c; // числу единиц присваиваем значение счетчика ten = 0; // числу десятков присваиваем 0 поскольку c<10 } if (c>=10) // если значение счетчика больше или равно 10 { ten = c/10; // вычисляем значение числа десятков one = c-(ten*10); // вычисление числа единиц } PORTD |=(1<<PIND6); // включаем второй транзистор (отображение числа единиц) PORTA = DISPLAY1[one]; // записываем в porta соответствующее значение для отображения его на дисплее _delay_ms(10); // задержка 10 мс PORTD &=~(1<<PIND6); // выключаем второй транзистор PORTD |=(1<<PIND5); // включаем первый транзистор (отображение числа десятков) PORTA = DISPLAY1[ten]; // записываем в porta соответствующее значение для отображения его на дисплее _delay_ms(10); PORTD &=~(1<<PIND5);// выключаем первый транзистор } } |
в протеусе собрал правда с одним индикатором не работает.
К сожалению, по этому поводу не могу ничего дельного подсказать, слишком маленький опыт работы в протеусе
при продолжительном нажатии на кнопку счет идет, а как сделать чтобы счет шел только от количества нажатий?
Да по идее ничего больше не нужно делать, представленная программа должна корректно обрабатывать одиночные нажатия кнопок
Здравствуйте. А как сделать что б считал до 999?
Здравствуйте, добавить третий семисегментный дисплей по аналогии и третий транзистор для него. И распространить описанный в статье принцип мультиплексирования для трех дисплеев