Хочу поделится своим первым опытом с разработкой устройства на микроконтроллере. У данной статьи будет 4 части:
часть 1 — теоретическая часть, проектирование устройства
часть 2 — прошивка микроконтроллера
часть 3 — изготовление ПП (фоторезист + FSR-8000)
часть 4 — делаем корпус
Данная статья ориентированна в основном для начинающих, кем я сам и являюсь, для меня это как бы Hello World AVR, поэтому строго не судите.
Для начала расскажу что за «Индикация места ключа» и причина его изготовления. Мне нужно было сдать экзамен по программированию на С++, попутно у меня хобби — электроника, и тут мне захотелось совместить приятное с полезным, преподаватель по С++ как-то говорил об одном устройстве, предлагал сделать его, но так никто и не откликнулся. Суть устройства — на кафедре очень часто бывает что никого нет, а ключ в каком нибудь кабинете с преподавателем, чтобы знали где ключ на дверь вешают бумажку, на которой написан номер кабинета где ключ, устройство должно как-то заменить эту бумажку. И тут я вспомнив это предлагаю преподавателю альтернативу, я устройство в котором буду использовать программирование на С++ вместо экзамена.
Для начала давайте определим основные критерии устройства:
— портативное (на батарейках)
— прочное (чтобы «бешеные» студенты не оторвали)
— должно иметь 2 части (панель управления и внешний индикатор)
— ну и по возможности симпатичное
Следующим шагом придумаем интерфейс устройства:
То, что слева — панель управления (то что внутри кафедры), те кружочки под числами — светодиоды, маленькие черные кружочки — тактовые кнопки, черная круглая — кнопка нажимная с фиксацией, числа в прямоугольнике — семисегментные индикаторы. Кнопка «Выбор разряда» выбирает разряд числа, светодиод под каждым разрядом подсвечивает тот разряд, который выбран, который мы сейчас редактируем. Кнопки «Добавить» и «Уменьшить» изменяют выбранную цифру, сброс обнуляет все числа. Кнопка «ВклВыкл» — тут понятно. То что справа — внешний индикатор, должен быть снаружи кафедры.
Микроконтроллер я выбрал Atmega8-16PU, т.к. лишь он был в наличии дома.
Для создания прошивки микроконтроллера я использовал Atmel Studio 6.0.
Для симуляции схемы и создания ПП использовал Proteus 7 Professional.
Схема устройства:
На схеме J1 — для подключения питания, J2, J3 — для внутрисхемного программирования.
Теперь перейдем к написанию программы, идея проста — есть три переменных, каждая из которых соответствует каждому индикатору, так же есть переменная, которая отвечает за состояние выбранного разряда, программа циклически повторяется и выводит эти переменные на семисегментники и светодиоды, нажатие тактовых кнопок изменяет эти значения, ну проще и быть не может. Перейдем к написанию кода
для начала подключим необходимые модули:
#define F_CPU 1000000UL //тактовая частота микроконтроллера
#include // объявление для всех AVR
#include // для Atmega8
#include // для пауз
Далее напишем основную функцию, весь остальной код будем писать между фигурными скобками
int main(void)
{
}
Настроим порты:
DDRD = 0xFF; // порт D как выход
DDRC = 0xFF; // порт C как выход
DDRB = 0x00; // порт B как вход
Объявим и создадим массив, который будет хранить переменные для порта D, для вывода на семисегментник символов 0,1,2,3,4,5,6,7,9, -:
// 0 1 2 3 4 5 6 7 8 9 —
char SEGMENT[ ] = {0x3F, 0x06, 0x5B, 0x4F, 0x66,0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0b01000000};
Объявим и зададим значения переменным, о которых говорил выше. Поясню n_1 — значение первого индикатора, n_2 — 2-го индикатора, n_3 — 3-го, indickator — это номер выбранного разряда.
int n_1 = 0;
int n_2 = 0;
int n_3 = 0;
char indickator = ‘1’;
Далее пишем бесконечный цикл, в котором будем выводит переменные (n_1, n_2, n_3, indickator) и при нажатии кнопок изменять их значения
while(1)
{
}
Напишем оператор выбора, который будет подсвечивать индикаторы, и светодиоды, логика следующая —
если активен 1-й разряд, то
порту С ставим такое состояние, чтобы горел 1-й светодиод и был подключен лишь первый семисегментник
на порт D выводим символ, который соответствует переменной n_1
делаем паузу, чтобы 1-й семисегментник немного погорел
порту С ставим такое состояние, чтобы горел 1-й светодиод и был подключен лишь второй семисегментник
на порт D выводим символ, который соответствует переменной n_2
делаем паузу, чтобы 2-й семисегментник немного погорел
порту С ставим такое состояние, чтобы горел 1-й светодиод и был подключен лишь третий семисегментник
на порт D выводим символ, который соответствует переменной n_3
делаем паузу, чтобы 3-й семисегментник немного погорел
если активен 2-й разряд, то делаем тоже самое, разница лишь в том что горит 2-й светодиод, аналогично при активном третьем разряде.
switch(indickator)
{
case ‘1’: {
PORTC = 0b00001110; // вывод на 1-й индикатор PORTC = 0b00001011;
PORTD = SEGMENT[n_1];
_delay_ms(5);
PORTC = 0b00001101;// вывод на 2-й индикатор
PORTD = SEGMENT[n_2];
_delay_ms(5);
PORTC = 0b00001011;// вывод на 3-й индикатор
PORTD = SEGMENT[n_3];
} break;
case ‘2’: {
PORTC = 0b00010110; // вывод на 1-й индикатор PORTC = 0b00001011;
PORTD = SEGMENT[n_1];
_delay_ms(5);
PORTC = 0b00010101;// вывод на 2-й индикатор
PORTD = SEGMENT[n_2];
_delay_ms(5);
PORTC = 0b00010011;// вывод на 3-й индикатор
PORTD = SEGMENT[n_3];
} break;
case ‘3’: {
PORTC = 0b00100110; // вывод на 1-й индикатор PORTC = 0b00001011;
PORTD = SEGMENT[n_1];
_delay_ms(5);
PORTC = 0b00100101;// вывод на 2-й индикатор
PORTD = SEGMENT[n_2];
_delay_ms(5);
PORTC = 0b00100011;// вывод на 3-й индикатор
PORTD = SEGMENT[n_3];
} break;
}
Это переключение между семисегментниками невооруженным глазом не уловить (хотя на видео это можно заметить. покажу во второй части статьи) и нам кажется что горят все три индикатора одновременно, этим мы сэкономили 16 выводов микроконтроллера, которых у меня тут просто не найти.
Теперь добавим обработчик нажатия кнопки «Выбор разряда», суть — через резисторы 10кОм течет ток и на порте B каждый вывод равен 1 (плюс). При нажатии тактовой кнопки ток утекает в землю и на соответствующем выводе микроконтроллера возникает 0, т.е. минус. Используем это для описываемой кнопки, логика следующая —
если на соответствующем выводе порта В появился минус, то
если переменная indicator = 1, то делаем ее равную 2
если она равна 2, то делаем ее равную 3
если она равна 3, то делаем ее равную 1
После всего этого делаем паузу в 0,2 секунды, если паузу не сделать, то пока вы будете нажимать кнопку светодиод успеет смениться следующим по циклу несколько десятков или сотен раз, может и пару тысяч, а 0,2 секунды вполне хватает чтобы при однократном нажатии произошел всего один переход.
if (PINB == 0b11111110) // нажатие кнопки установка
{
switch(indickator)
{
case ‘1’: indickator = ‘2’ ; break;
case ‘2’: indickator = ‘3’ ; break;
case ‘3’: indickator = ‘1’ ; break;
}
_delay_ms(200);
}
Следующий у нас на очереди обработчик кнопки «Увеличить», тут тоже все просто, если возник минус на выводе порта В, куда подключена соответствующая кнопка, то если выбран первый разряд, то увеличиваем там число, если 2-й, то увеличиваем второй на единицу и если третий, то третий увеличиваем, после чего также и по той же причине что выше делаем паузу в 0,2 секунды:
if (PINB == 0b11111101) // нажатие кнопки +
{
if (indickator == ‘1’)
{
switch(n_1)
{
case 0: n_1 = 1; break;
case 1: n_1 = 2; break;
case 2: n_1 = 3; break;
case 3: n_1 = 4; break;
case 4: n_1 = 5; break;
case 5: n_1 = 6; break;
case 6: n_1 = 7; break;
case 7: n_1 = 8; break;
case 8: n_1 = 9; break;
case 9: n_1 = 10; break;
case 10: n_1 = 0; break;
}
}
if (indickator == ‘2’)
{
switch(n_2)
{
case 0: n_2 = 1; break;
case 1: n_2 = 2; break;
case 2: n_2 = 3; break;
case 3: n_2 = 4; break;
case 4: n_2 = 5; break;
case 5: n_2 = 6; break;
case 6: n_2 = 7; break;
case 7: n_2 = 8; break;
case 8: n_2 = 9; break;
case 9: n_2 = 10; break;
case 10: n_2 = 0; break;
}
}
if (indickator == ‘3’)
{
switch(n_3)
{
case 0: n_3 = 1; break;
case 1: n_3 = 2; break;
case 2: n_3 = 3; break;
case 3: n_3 = 4; break;
case 4: n_3 = 5; break;
case 5: n_3 = 6; break;
case 6: n_3 = 7; break;
case 7: n_3 = 8; break;
case 8: n_3 = 9; break;
case 9: n_3 = 10; break;
case 10: n_3 = 0; break;
}
}
_delay_ms(200);
}
Аналогично кнопке «Добавить» реализуем кнопочку «Уменьшить»:
if (PINB == 0b11111011) // нажатие кнопки —
{
if (indickator == ‘1’)
{
switch(n_1)
{
case 0: n_1 = 10; break;
case 1: n_1 = 0; break;
case 2: n_1 = 1; break;
case 3: n_1 = 2; break;
case 4: n_1 = 3; break;
case 5: n_1 = 4; break;
case 6: n_1 = 5; break;
case 7: n_1 = 6; break;
case 8: n_1 = 7; break;
case 9: n_1 = 8; break;
case 10: n_1 = 9; break;
}
}
if (indickator == ‘2’)
{
switch(n_2)
{
case 0: n_2 = 10; break;
case 1: n_2 = 0; break;
case 2: n_2 = 1; break;
case 3: n_2 = 2; break;
case 4: n_2 = 3; break;
case 5: n_2 = 4; break;
case 6: n_2 = 5; break;
case 7: n_2 = 6; break;
case 8: n_2 = 7; break;
case 9: n_2 = 8; break;
case 10: n_2 = 9; break;
}
}
if (indickator == ‘3’)
{
switch(n_3)
{
case 0: n_3 = 10; break;
case 1: n_3 = 0; break;
case 2: n_3 = 1; break;
case 3: n_3 = 2; break;
case 4: n_3 = 3; break;
case 5: n_3 = 4; break;
case 6: n_3 = 5; break;
case 7: n_3 = 6; break;
case 8: n_3 = 7; break;
case 9: n_3 = 8; break;
case 10: n_3 = 9; break;
}
}
_delay_ms(200);
}
Осталось добавить обработчик кнопки «Сброс», для этого отследим ее нажатие и просто «обнулим» значения всех переменных и добавим паузу, хотя и она тут особо роли не играет:
if (PINB == 0b11110111) // нажатие кнопки сброс
{
n_1 = 10;
n_2 = 10;
n_3 = 10;
indickator = ‘1’;
_delay_ms(100);
}
Далее компилируем проект и загружаем прошивку в Proteus и симулируем:
Следующее что нам нужно сделать — это прошить микроконтроллер
Прошивать будем программой AlgorithmBuilder через программатор SPA0008, стоит он недорого, я покупал за 731 руб. в магазине ekits, намного дешевле конечно воспользоваться «пятью проводками», но у меня нет LTP порта и USB программатор более мобилен.
Для начала присоединим микроконтроллер к программатору, тут несколько вариантов:
1) можно купить плату-адаптер для данного типа микроконтроллера
2) можно сделать самому плату-адаптер для данного микроконтроллера
3) можно собрать на макетке
Выберем третий вариант, т.к. он самый быстрый.
Подключим VCC микроконтроллера и +5V программатора к плюсу источника, в качестве источника четыре батарейки АА, в сумме 6 Вольт, на 3-х батарейках выдает ошибку — не видит микроконтроллер
GND микроконтроллера и GND программатора к минусу источника. Выводы микроконтроллера SCK, MISO, MOSI соответственно к тем же на программаторе.
Далее самое интересное, процесс прошивки кристалла:
В следующей статье мы создадим довольно красивую печатную плату к данному устройству.
Список радиоэлементовОбозначение
Тип
Номинал
Количество
ПримечаниеМагазинМой блокнот
U1
МК AVR 8-битATmega81
Резистор10 кОм8
Резистор330 Ом8
Резистор130 Ом3
D1-D3
СветодиодЗеленый3
Seg1-Seg3
Индикатор3
SW0-SW4
Кнопка5
J1
Панелька2 Штырька1
J2, J3
Панелька4 Штырька2
Добавить все
Скачать список элементов (PDF)
Прикрепленные файлы:
- AVR_Studio_6_Project.rar (29 Кб)
- ISIS_Project.rar (86 Кб)
- AVR_key_AlgorithmBuilder.rar (6 Кб)