Машина для голосования на микроконтроллере AVR ATmega32

Наверное, вы в своей жизни на различных выборах видели специальные машины для голосования. В этой статье мы постараемся собрать упрощенную модель подобной машины на микроконтроллере ATmega32A (семейство AVR). На данном микроконтроллере можно собрать машину для голосования 32 людей, однако в целях упрощения мы в данной статье ограничимся схемой для голосования 4 людей. У нас будет 4 кнопки для 4 людей и всегда, когда кнопка будет нажата, голос от соответствующего человека будет засчитан и количество голосов от каждого человека будет показываться на жидкокристаллическом (ЖК) дисплее.

Машина для голосования на микроконтроллере AVR ATmega32: внешний вид

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

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

Микроконтроллер ATmega32
Источник питания с напряжением 5 Вольт
Программатор AVR-ISP или
JHD_162ALCD (ЖК дисплей 16×2)
Конденсаторы 100 нФ capacitor (5 шт.), 100 мкФ (подсоединенный через источник питания)
Кнопки (5 шт.),
Резистор 10 кОм (5 шт.).

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

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

Работа схемы

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

Схема машины для голосования на микроконтроллере AVR ATmega32

Как видно из представленной схемы, PORTA микроконтроллера ATmega32 соединен с портом данных ЖК дисплея 16×2 (более подробно о подключении ЖК дисплея к микроконтроллеру ATmega32 можно прочитать в этой статье. Но следует помнить о том, что необходимо деактивировать интерфейс JTAG (отладки микроконтроллера) при помощи изменения фьюзов (fuse bytes) если вы хотите использовать PORTC в качестве обычного коммуникационного порта. В ЖК дисплее (если мы не хотим использовать черный цвет) можно задействовать только 14 его контактов: 8 контактов для передачи данных (7-14 или D0-D7), 2 контакта для подачи питания (1&2 или VSS&VDD или gnd&+5v), 3-й контакт для управления контарстностью, 3 контакта для управления (RS&RW&E).

В представленной схеме мы использовали только 2 контакта управления для лучшего понимания работы схемы. Бит контраста и READ/WRITE используются нечасто, поэтому они могут быть замкнуты на землю. Это обеспечивает ЖК дисплею максимальную контрастность и переводит его в режим чтения. Теперь нам всего лишь нужно контролировать контакты ENABLE и RS чтобы передать на ЖК дисплей символы и данные.

В схеме необходимо сделать следующие соединения с ЖК дисплеем:
PIN1 или VSS — земля
PIN2 или VDD или VCC — +5v питание
PIN3 или VEE — земля (обеспечивает максимальный контраст ЖК дисплею)
PIN4 или RS (Register Selection) – контакт PD6 микроконтроллера
PIN5 или RW (Read/Write) — земля (переводит ЖК дисплей в режим чтения что упрощает взаимодействие с ним для начинающих)
PIN6 или E (Enable) — контакт PD5 микроконтроллера
PIN7 или D0 — контакт PA0 микроконтроллера
PIN8 или D1 — контакт PA1 микроконтроллера
PIN9 или D2 — контакт PA2 микроконтроллера
PIN10 или D3 — контакт PA3 микроконтроллера
PIN11 или D4 — контакт PA4 микроконтроллера
PIN12 или D5 — контакт PA5 микроконтроллера
PIN13 или D6 — контакт PA6 микроконтроллера
PIN14 или D7 — контакт PA7 микроконтроллера

В схеме мы использовали 8-битную связь (D0-D7) ЖК дисплея с микроконтроллером, хотя можно было ограничиться и 4-битной – но в этом случае код программы стал бы немного сложнее.

Таким образом, мы использовали 10 контактов ЖК дисплея, 8 из которых будут использоваться для передачи данных и 2 для управления. 4 кнопки на схеме используются для подсчета (увеличения) числа голосов кандидатов и пятая кнопка – для сброса числа голосов.

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

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

При нажатии кнопки, соответствующей какому-нибудь человеку, микроконтроллер распознает это и увеличивает соответствующую переменную в своей памяти, затем передает значение этой переменной на ЖК дисплей 16×2.

Исходный код программы на языке C (Си) с пояснениями

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

/*
C Program for AVR Microcontroller Based Electronic Voting Machine
*/
#include <avr/io.h> //заголовок чтобы разрешить контроль данных на контактах
#define F_CPU 1000000 //задание тактовой частоты
#include <util/delay.h> //заголовок чтобы задействовать функции задержки в программе
#define E 5 //задействуем 5-й контакт PORTD (“enable”), поскольку он соединен с контактом “enable” ЖК дисплея
#define RS 6 //задействуем выбор регистра (“registerselection”) на 6-м контакте PORTD, поскольку он соединен с контактом RS ЖК дисплея

void send_a_command(unsigned char command);
void send_a_character(unsigned char character);
int main(void)
{
DDRA = 0xFF; //установка porta и port d в качестве выходных контактов
DDRD = 0xFF;
_delay_ms(50); //задержка в 50ms
DDRB = 0; //установка portB на ввод.

int16_t COUNTA = 0; // число голосов от персоны 1
char SHOWA [16]; // отображаемый символ голосования персоны 1 на ЖК дисплее
int16_t COUNTB = 0; // число голосов от персоны 2
char SHOWB [16]; // отображаемый символ голосования персоны 2 на ЖК дисплее
int16_t COUNTC = 0; // число голосов от персоны 3
char SHOWC [16]; // отображаемый символ голосования персоны 3 на ЖК дисплее
int16_t COUNTD = 0; // число голосов от персоны 4
char SHOWD [16]; // отображаемый символ голосования персоны 4 на ЖК дисплее

send_a_command(0x01); //очистить экран ЖК дисплея 0x01 = 00000001
_delay_ms(50);
send_a_command(0x38); // говорим ЖК дисплею что мы будем использовать 8-битный режим команд/данных
_delay_ms(50);
send_a_command(0b00001111); //включаем экран и мигание курсора на ЖК дисплее

while(1)
{
send_a_string ("A="); // отображение имени персоны 1
send_a_command(0x80 + 2); // сдвигаем курсор на 3-ю позицию
itoa(COUNTA,SHOWA,10); // устанавливаем номер переменной на ЖК дисплее, используем базу 10
send_a_string(SHOWA); // говорим дисплею чтобы он отобразил символ
send_a_command(0x80 + 8); // сдвигаем курсор на 9-ю позицию
send_a_string ("B="); // отображение имени персоны 2
send_a_command(0x80 + 10); // сдвигаем курсор на 11-ю позицию
itoa(COUNTB,SHOWB,10); // преобразуем целое число COUNTB в строку SHOWB,  10 - десятичная система счисления
send_a_string(SHOWB); ); // говорим дисплею чтобы он отобразил символ.
send_a_command(0x80 + 0x40 + 0); // сдвигаем курсор на 1-ю позицию второй строки
send_a_string ("C="); // отображение имени персоны 3
send_a_command(0x80 + 0x40 + 2); // сдвигаем курсор на 3-ю позицию второй строки
itoa(COUNTC,SHOWC,10);
send_a_string(SHOWC);
send_a_command(0x80 + 0x40 + 8); // сдвигаем курсор на 9-ю позицию второй строки
send_a_string ("D="); // отображение имени персоны 4
send_a_command(0x80 + 0x40 + 10); // сдвигаем курсор на 11-ю позицию второй строки
itoa(COUNTD,SHOWD,10);
send_a_string(SHOWD);
send_a_command(0x80 + 0); // сдвигаем курсор на 0-ю позицию
if (bit_is_clear(PINB,0))// когда нажата кнопка 1
{
COUNTA++; // увеличение числа голосов первой персоны на единицу
}
if (bit_is_clear(PINB,1)) // когда нажата кнопка 2
{
COUNTB++; // увеличение числа голосов второй персоны на единицу
}
if (bit_is_clear(PINB,2)) // когда нажата кнопка 3
{
COUNTC++; // увеличение числа голосов третьей персоны на единицу
}
if (bit_is_clear(PINB,3)) // когда нажата кнопка 4
{
COUNTD++; // увеличение числа голосов четвертой персоны на единицу
}
if (bit_is_clear(PINB,4)) // когда нажата кнопка 5
{
COUNTA=COUNTB=COUNTC=COUNTD=0; // очистка голосов всех персон
}
}
}

void send_a_command(unsigned char command)
{
PORTA = command;
PORTD &= ~ (1<<RS); // установка 0 на контакте RS чтобы сообщить ЖК дисплею что мы будем передавать команду
PORTD |= 1<<E; // говорим ЖК дисплею принять команду
_delay_ms(50);
PORTD &= ~1<<E; // сообщаем ЖК дисплею что мы закончили передачу команды
PORTA= 0;
}

void send_a_character(unsigned char character)
{
PORTA= character;
PORTD |= 1<<RS; // сообщаем ЖК дисплею что мы будем передавать данные
PORTD |= 1<<E; // говорим ЖК дисплею что мы начали передачу данных
_delay_ms(50);
PORTD &= ~1<<E; // сообщаем ЖК дисплею что мы закончили передачу данных
PORTA = 0;
}
}

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

(1 голосов, оценка: 5,00 из 5)
Загрузка...
21 просмотров


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

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