Счетчик 0-99 на микроконтроллере AVR ATmega32

В этой статье мы рассмотрим счетчик 0-99 на двух символьном семисегментном дисплее под управлением микроконтроллера ATmega32 (семейство AVR). Мы будем подсчитывать число событий основываясь на числе нажатий кнопки.

Счетчик 0-99 на микроконтроллере AVR ATmega32: внешний вид

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

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

Диаграмма контактов семисегментного дисплея

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

Соединение цепей семисегментного дисплея

Как мы можем видеть, в катодном режиме (Common Cathode) отрицательные выводы светодиодов соединены вместе и названы «землей (GND)». В анодном режиме (Common Anode) положительные выводы светодиодов соединены вместе и названы «напряжением постоянного тока (VCC)». Эти режимы имеют значение (то есть их надо учитывать) когда мы объединяем несколько семи сегментных дисплеев в одно целое.

Чтобы человеческий глаз не замечал мерцания светодиодов семисегментного индикатора их необходимо переключать с частотой не менее 50 Гц.

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

Необходимые компоненты

Аппаратное обеспечение

Микроконтроллер ATmega32
Источник питания с напряжением 5 Вольт
Программатор AVR-ISP, USBASP или другой подобный
Семисегментный дисплей HDSP5503 (2 шт.)
Конденсатор 47 пФ
Кнопка (3 шт.)
Резистор 220 Ом (2 шт.)
Резистор 10 кОм (2 шт.)
Резистор 1 кОм
Резистор 100 нФ (3 шт.)
Транзистор 2N2222 (2 шт.)

Программное обеспечение

Atmel Studio версии 6.1 (или выше)
Progisp или flash magic (необязательно)

Работа схемы

Схема устройства приведена на следующем рисунке.

Схема счетчика 0-99 на микроконтроллере AVR ATmega32

Соединения, которые необходимо сделать для семи сегментного дисплея, следующие:
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 мс, а первый в это время будет выключен и т.д. При этом частота переключения дисплеев будет достаточна для того чтобы человеческий воспринимал их как непрерывно горящими, хотя на самом деле это не так.

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

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

Объяснение работы программы

Программа для рассматриваемой схемы представлена следующим фрагментом кода. Комментарии к коду программы поясняют принцип работы отдельных команд.

#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);// выключаем первый транзистор
}
}

Видео, демонстрирующее работу схемы



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

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