Как загрузить программу на микроконтроллер

Напоминаю: Об основах и тонкостях электроники и схемотехники читайте в настольной книге электронщика: П.Хоровиц, У.Хилл. Искусство схемотехники на РУССКОМ языке.

Я советую прошивать микроконтроллер прямо из программатора встроенного в компилятор CodeVisionAVR через простейший адаптер — буквально «пять проводков» соединяющих принтерный порт ПК с прошиваемым микроконтроллером AVR.

ПОДРОБНО: Результат написания и компиляции программы — файл-прошивку с расширением .hex (и возможно файл с содержимым для
EEPROM МК) нужно записать («зашить») в МК . МК AVR многократно программируются прямо в устройстве в котором будут работать — такое программирование называют — «ин систем программинн» или ISP.

Для этого установите на плате вашего устройства 6 контактов, а лучше 6-ти штырьковый разъем для ISP

вид сверху платы на штырьки.
выводы подсоединить к МК в соответствии с указанными названиями.
Подробней по ISP разъемам посмотрите Апликейшн Ноут AVR910.

Программирование микроконтроллеров

Вывод 2 нужно подключить к + питания МК если вы собираетесь использовать программатор питающийся от вашего же устройства — например фирменный ISP AVR.

Для «5 проводов» этот вывод не подключается. Для программирования достаточно 5 контактов. Соответственно и разъем который вы будете использовать может быть любым удобным для размещения на плате и имеющий минимум 5 контактов. Все контакты ISP разъема подсоединяются к ножкам МК в соответствии с названиями .

ВНИМАНИЕ ! в ATmega64 и ATmega128 выводы MOSI и MISO не применяют для ISP Внимательно смотрите ДатаШит ! Например для ATmega 128 сигналы MISO подключают к ножке PE1, MOSI подключают к ножке PE0

Я советую вам пользоваться интерфейсом программирования встроенным в компилятор CodeVisionAVR и конечно же в нем разрабатывать программу для МК. Дело в том, что вам вряд ли удастся сразу написать программу без ошибок, даже после прогона в софт эмуляторе — симуляторе ваше устройство может делать не то, что вы от него ожидаете — значит в программу нужно будет вносить изменения и снова зашивать в МК , и так раз 20 и более.

Вы можете в компиляторе CodeVisionAVR открыть меню «Проджект -> Конфига -> Афта Мэйк» и отметить чек бокс «Program the chip» затем ОК. Еще нужно в меню «Сеттинс -> Программер» выбрать ваш адаптер (подробней ниже) для программирования.

Теперь после безошибочной компиляции программы вам будет доступна кнопка «Program» — нажмите на нее и произойдет программирование МК — т.е. файл .hex будет загружен в память программ МК. Затем МК будет «сброшен» (на ножку RESET будет подан лог. 0 а затем опять «1») и начнет выполнять только что прошитую (загруженную в него) программу. Вам даже не нужно будет отсоединять адаптер программирования от вашего устройства если вы не используете в устройстве последовательный интерфейс SPI . . и так до окончательной отладки устройства.

Как прошить микроконтроллер? Легко))

В А Ж Н О ! В диалоге настройки программирования не трогайте галочки установки фьюзов МК если не разобрались четко что они делают! Иначе вы можете отключить режим ISP или внутренний RC-генератор и для следующего программирования вам понадобится ставить кварц с конденсаторами или даже искать Параллельный программатор для AVR . Но популярному AT tiny2313 даже параллельный программатор не поможет!

в ATmega XXX с завода включен внутренний RC генератор на частоте 1 МГц ( уточните это по ДШ и его возможные частоты ) Если вам нужна другая частота или нужно включить внешний кварцевый или керамический резонатор — вам нужно запрограммировать некоторые фьюзы по таблицам из ДШ или по таблице фьюзов на стр. 2

З а п о м н и т е :
НЕ запрограммированный фьюз 1
ЗАпрограммированный фьюз 0

Пример: Чтобы включить в ATmega16 внешний кварцевый резонатор с частотой от 3 до 8 МГц с конденсаторами (по схеме рис. 12 ДШ) найдите в ДШ раздел » System Clock «.

В таблице 2 указаны комбинации фьюзов для разных источников тактового сигнала. Далее написано что с завода МК поставляется с такой комбинацией фьюзов

SKSEL 0001 SUT 10 CKOPT 1

По таблице 4 находим :
Для кварца с частотой от 3 до 8 МГц нужны конденсаторы от 12 до 22 пФ и вот такая комбинация фьюзов :

SKSEL 111 1 SUT 10 CKOPT 1
Установка фьюзов в программаторе компилятора CVAVR

Для прошивания МК нажмите кнопку » Program All »

Для использования ATmega16 (и других мег) с внешним кварцевым или керамическим резонатором на частотах выше 8 МГц вам нужно установить фьюзы как в примере выше но запрограммировать CKOPT — значит сделать его «0». Т.е. вам нужна такая комбинация:

SKSEL 111 1 SUT 10 CKOPT 0

CKOPT 0 — нужен и тогда когда вы хотите подключить к XTAL2 другой микроконтроллер или тактируемый прибор.

Фьюзы SUT — определяют запуск генератора тактового сигнала, в большинстве случаев их установку можно оставить «как с завода» — SUT 10 — более детально это описано в даташите в таблицах до 12.
Для соединения компьютера с ISP разъемом устройства на AVR Советую сделать адаптер от STK200 — это «правильные 5 проводков» с микросхемой буфером снижающим вероятность случайного повреждения порта ПК. В установках компилятора CodeVisionAVR интерфейс «5-проводков» называется «Канда системз STK200+/300»

Программа узнаёт адаптер STK200 по перемычкам на разъеме параллельного порта к которому он подключается — должны быть соединены двумя перемычками пары выводы: 2 и 12, 3 и 11.

Программирование микроконтроллеров AVR с помощью программатора USBASP и Atmel Studio 7.0

Существует несколько способов программирования микроконтроллеров семейства AVR. В данной статье мы рассмотрим один из наиболее популярных в настоящее время способов программирования данных микроконтроллеров – с помощью программатора USBASP v2.0 и программы Atmel Studio 7.0. Хотя на нашем сайте уже есть достаточно подробные статьи про программатор USBASP и программу Atmel Studio 7.0 я все таки решил перевести с иностранного сайта и эту статью – вдруг кто то найдет в ней для себя что то интересное.

USBASP и Atmel Studio 7.0 - инструменты для программирования микроконтроллеров AVR

В данной статье будут рассмотрены следующие вопросы:

  1. Установка драйвера USBASP.
  2. Скачивание и установка Atmel Studio.
  3. Установка WinAVR для Atmel Studio.
  4. Установка микроконтроллера Atmega16 с кварцевым генератором и одним светодиодом.
  5. Создание и загрузка программного кода в Atmega16.
Читайте также:
Программа чтобы нарисовать стрелки

Рассмотрим подробно все эти вопросы. Установку драйвера для программатора USBASP будем рассматривать на примере операционной системы Windows10 – но все сказанное в этом разделе будет справедливо и для других версий Windows.

Установка драйвера для USBASP в Windows 10

Если вы используете интерфейс JTAG, вам может потребоваться установка драйвера для USBASP если он не установился автоматически. Если вы не установите этот драйвер, то вы не сможете найти порт USBASP в программе Atmel Studio. Скачать драйвер USBASP можно по этой ссылке — http://www.mediafire.com/file/z576zrku371qyjs/windows-8-and-windows-10-usbasp-drivers-libusb_1.2.4.0-x86-and-x64-bit.zip/file.

После скачивания драйвера выполните следующую последовательность действий:

1. Распакуйте из архива скачанные файлы и поместите их на рабочий стол.

2. Подсоедините модуль USBASP v2.0 к своему компьютеру.

3. Откройте в Windows диспетчер устройств (Device Manager).

4. Теперь вы можете увидеть подсоединенный USBASP в списке устройств.

USBASP в диспетчере устройств

5. Кликните правой кнопкой мыши по “USBasp” и выберите “Обновить драйвер (Update Driver)”.

Меню обновления драйвера для USBASP

6. Select “Произвести поиск драйвера на своем компьютере (Browse my computer for driver software)”.

Выбор способа обновления драйвера для USBasp

7. Найдите в открывшемся окне распакованную папку с драйвером для USBASP и щелкните «Открыть».

Выбор папки с драйвером для USBASP

8. Если установка драйвера прошла успешно, то вы увидите сообщение примерно такое же как на нижеприведенном рисунке – в этом случае вам уже не нужно выполнять дальнейшие инструкции в этом разделе статьи.

Драйвер для USBASP успешно установлен

9. Если вы увидите сообщение об ошибке как на приведенном рисунке, то вы в этом случае должны отключить цифровую подпись драйвера.

Произошла ошибка при установке драйвера для USBASP

Чтобы сделать выполните следующие шаги:

— нажмите кнопку Shift и удерживая ее нажатой перезагрузите свой компьютер (кликните Restart в меню Windows пока держите ее нажатой);

— когда ваш компьютер перезагрузится не отпускайте кнопку Shift до тех пор пока не увидите “Advanced Options (Расширенные настройки)” на синем экране;

Выбор расширенных настроек

— отпустите кнопку Shift и кликните на “Startup Settings”;

— кликните на “Troubleshoot (Устранение проблем)”;

Выбор устранения проблем

— выберите “Advanced Options (Расширенные настройки)”;

Выбор расширенных настроек при устранении проблем

— после этого вы увидите на экране список расширенных опций и кнопку “Restart” в правом нижнем углу – кликните на ней;

Список расширенных опций перезагрузки

— подождите пока компьютер снова перезагрузится. После этого вы увидите на экране ряд настроек;

— в открывшемся списке настроек выберите пункт “Disable Driver Signature Enforcement (Отключить цифровую подпись драйвера)”. Чтобы ее выбрать просто нажмите кнопку «7» на вашей клавиатуре (не путать с кнопкой «F7»);

Отключение цифровой подписи драйвера при перезагрузке

— после нажатия этой кнопки компьютер перезагрузится и цифровая подпись драйвера будет отключена;

— после этого снова выполните шаги 1-8 из данного раздела статьи и драйвер для программатора USBASP будет успешно установлен.

Скачивание и установка Atmel Studio

Выполните следующую последовательность действий:

2. Также вам необходимо скачать приложение WinAVR чтобы иметь возможность загружать программы в микроконтроллер AVR с помощью USBASP.

После этого вам необходимо создать тестовый проект в Atmel Studio 7.0. Для этого выполните нижеследующую последовательность действий.

3. Подсоедините USBASP v2.0 к USB порту вашего компьютера и подождите пока он правильно определится.

4. Откройте Atmel Studio.

5. Выберите пункт меню “File”, в нем “New” и выберите “project”.

Создание нового проекта в Atmel Studio

6. Теперь назовите ваш проект, выберите место расположения проекта и выберите компилятор “GCC C Executable Project”. Кликните на “Ok” и продолжайте.

Выбор компилятора в Atmel Studio

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

Выбор типа микроконтроллера в Atmel Studio

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

Но после создания проекта финальный шаг, который вам необходимо выполнить – это установить внешние инструментальные средства (WinAVR).

Установка WinAVR в Atmel Studio

1. В пункте меню “Tools (Инструменты)” выберите “External Tools (Внешние инструменты)”.

Выбор внешних инструментов в Atmel Studio

2. У вас откроется окно, где вы должны будете ввести имя вашего инструментального средства.

3. В пункте “Title (название)” введите имя вашего внешнего инструментального средства. Можно выбрать любое имя, но в рассматриваемом примере мы выбрали имя “USBasp”. Поставьте галочку в пункте ”Use Output Window” и снимите галочку с пункта “Prompt for arguments” как показано на нижеприведенном рисунке.

4. Теперь ведите “Command”. Там будет необходимо указать путь к “avrdude.exe” – его вы можете найти в папке где установлена WinAvr. Просто найдите “WinAVR-20100110” на диске “C” вашего компьютера – куда вы устанавливали WinAvr.

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

6. Больше аргументов можно найти по этой ссылке.

7. Введите аргументы в поле для ввода аргументов. Оставьте поле “Initial directory (Начальный директорий)” без изменений.

Окно для ввода аргументов

8. После заполнения всех полей нажмите “Apply” и затем “Ok”.

В результате этих шагов вы сможете использовать внешние инструментальные средства чтобы загружать программы в микроконтроллер. Проверим это с помощью тестового проекта (программы) “blink.c”. Файл main.c вы можете найти в конце этой статьи. Теперь скопируйте main.c в Atmel studio.

Схема устройства с мигающим светодиодом для Atmega16

Схема устройства, которую необходимо собрать, приведена на следующем рисунке. Соедините кварцевый генератор и светодиод с микроконтроллером Atmega16.

Схема конструкции с мигающим светодиодом

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

Внешний вид макетной платы с собранной конструкцией

Также вы должны соединить микроконтроллер и USBASP как показано на следующей схеме:

Схема соединений USBASP и микроконтроллера AVR ATmega16

Компоновка и загрузка программного кода в Atmega16

1. Сохраните файл main.c.

2. Подсоедините светодиод к контакту PORTA0 микроконтроллера Atmega16 как было показано на вышеприведенном рисунке.

3. Выберите пункт меню “Build” и затем выберите “Build Blink”.

Компоновка проекта в Atmel Studio

4. Если программа не содержит ошибок, то вы увидите сообщение как на представленном рисунке.

Успешная компиляция проекта в Atmel Studio

5. Теперь выберите пункт меню “Tools” и выберите в ней созданные внешние инструментальные средства. В нашем случае это будет “USBasp”. Кликните по нему.

Выбор USBASP в Atmel Studio

6. Если после этого вы увидите сообщение об успешности операции (как показано на рисунке ниже), то значит вы успешно загрузили программу в микроконтроллер. Если вы получили сообщение об ошибке, то проверьте правильность выполнения всех предыдущих шагов, а также проверьте исправность соединительных проводов между USBASP и Atmega16.

Загрузка программы в микроконтроллер AVR с помощью программатора USBASP и Atmel Studio 7.0

7. Вы успешно загрузили тестовую программу с мигающим светодиодом в микроконтроллер используя USBASP v2.0 and Atmel Studio 7.0 и можете увидеть как мигает светодиод в собранной схеме. Теперь вы можете аналогичным образом загружать в микроконтроллер любые другие программы.

Читайте также:
В какой программе можно совместить два лица

Источник: microkontroller.ru

Вы еще не программируете микроконтроллеры? Тогда мы идем к вам!

Здравствуйте, уважаемые Хабражители!

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

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

1. Программатор

На рынке предлагается много вариантов — от самых дешевых ISP (In-System Programming) программаторов за несколько долларов, до мощных программаторов-отладчиков за пару сотен. Не имея большого опыта в этом деле, для начала я решил попробовать один из самых простых и дешевых — USBasp. Купил в свое время на eBay за $12, сейчас можно найти даже за $3-4.

На самом деле это китайская версия программатора от Thomas Fischl. Что могу сказать про него? Только одно — он работает. К тому же поддерживает достаточно много AVR контроллеров серий ATmega и ATtiny. Под Linux не требует драйвера.

Для прошивки надо соединить выходы программатора VCC, GND, RESET, SCK, MOSI, MISO с соответствующими выходами микроконтроллера. Для простоты я собрал вспомогательную схему прямо на макетной плате:

image

Слева на плате — тот самый микроконтроллер, который мы собираемся прошивать.

2. Микроконтроллер

С выбором микроконтроллера я особо не заморачивался и взял ATmega8 от Atmel — 23 пина ввода/вывода, два 8-битных таймера, один 16-битный, частота — до 16 Мгц, маленькое потребление (1-3.6 мА), дешевый ($2). В общем, для начала — более чем достаточно.

image

Под Linux для компиляции и загрузки прошивки на контроллер отлично работает связка avr-gcc + avrdude. Установка тривиальная. Следуя инструкции, можно за несколько минут установить все необходимое ПО. Единственный ньюанс, на который следует обратить внимание — avrdude (ПО для записи на контроллер) может потребовать права супер-пользователя для доступа к программатору. Выход — запустить через sudo (не очень хорошая идея), либо прописать специальные udev права. Синтаксис может отличаться в разных версиях ОС, но в моем случае (Linux Mint 15) сработало добавление следующего правила в файл /etc/udev/rules.d/41-atmega.rules :

# USBasp programmer SUBSYSTEM==»usb», ATTR==»16c0″, ATTR==»05dc», GROUP=»plugdev», MODE=»0666″

После этого, естественно, необходим перезапуск сервиса

service udev restart

Компилировать и прошивать без проблем можно прямо из командной строки (кто бы сомневался), но если проектов много, то удобнее поставить плагин AVR Eclipse и делать все прямо из среды Eclipse.

Под Windows придется поставить драйвер. В остальном проблем нет. Ради научного интереса попробовал связку AVR Studio + eXtreme Burner в Windows. Опять-таки, все работает на ура.

Начинаем программировать

Программировать AVR контроллеры можно как на ассемблере (AVR assembler), так и на Си. Тут, думаю, каждый должен сделать свой выбор сам в зависимости от конкретной задачи и своих предпочтений. Лично я в первую очередь начал ковырять ассемблер.

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

После знакомства с архитектурой и основными принципами, решил собрать что-то полезное и интересное. Тут мне помогла дочурка, она занимается шахматами и в один прекрасный вечер заявила, что хочет иметь часы-таймер для партий на время. БАЦ! Вот она — идея первого проекта!

Можно было конечно заказать их на том же eBay, но захотелось сделать свои собственные часы, с блэк… эээ… с индикаторами и кнопочками. Сказано — сделано!

В качестве дисплея решено было использовать два 7-сегментных диодных индикатора. Для управления достаточно было 5 кнопок — “Игрок 1” , “Игрок 2” , “Сброс” , “Настройка” и “Пауза” . Ну и не забываем про звуковую индикацию окончания игры. Вроде все. На рисунке ниже представлена общая схема подключения микроконтроллера к индикаторам и кнопкам. Она понадобится нам при разборе исходного кода программы:

Разбор полета

Начнем, как и положено, с точки входа программы — функции main . На самом деле ничего примечательного в ней нет — настройка портов, инициализация данных и бесконечный цикл обработки нажатий кнопок. Ну и вызов sei() — разрешение обработки прерываний, о них немного позже.

int main(void) < init_io(); init_data(); sound_off(); sei(); while(1) < handle_buttons(); >return 0; >

Рассмотрим каждую функцию в отдельности.

void init_io() < // set output DDRB = 0xFF; DDRD = 0xFF; // set input DDRC = 0b11100000; // pull-up resistors PORTC |= 0b00011111; // timer interrupts TIMSK = (1<

Настройка портов ввода/вывода происходит очень просто — в регистр DDRx (где x — буква, обозначающая порт) записивается число, каждый бит которого означает, будет ли соответствующий пин устройством ввода (соответствует 0) либо вывода (соответствует 1).

Таким образом, заслав в DDRB и DDRD число 0xFF, мы сделали B и D портами вывода. Соответственно, команда DDRC = 0b11100000; превращает первые 5 пинов порта C во входные пины, а оставшиеся — в выходные. Команда PORTC |= 0b00011111; включает внутренние подтягивающие резисторы на 5 входах контроллера. Согласно схеме, к этим входам подключены кнопки, которые при нажатии замкнут их на землю. Таким образом контроллер понимает, что кнопка нажата.

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

Обработка прерываний

ISR (TIMER0_OVF_vect) < display(); if (_buzzer >0) < _buzzer—; if (_buzzer == 0) sound_off(); >> ISR(TIMER1_COMPA_vect) < if (ActiveTimer == 1 Timer1 >0) < Timer1—; if (Timer1 == 0) process_timeoff(); >if (ActiveTimer == 2 Timer2 > 0) < Timer2—; if (Timer2 == 0) process_timeoff(); >>

При срабатывании таймера управление передается соответствующему обработчику прерывания. В нашем случае это обработчик TIMER0_OVF_vect, который вызывает процедуру вывода времени на индикаторы, и TIMER1_COMPA_vect, который обрабатывает обратный отсчет.

Читайте также:
Как пользоваться программой инвестиции

Вывод на индикаторы

void display() < display_number((Timer1/60)/10, 0b00001000); _delay_ms(0.25); display_number((Timer1/60)%10, 0b00000100); _delay_ms(0.25); display_number((Timer1%60)/10, 0b00000010); _delay_ms(0.25); display_number((Timer1%60)%10, 0b00000001); _delay_ms(0.25); display_number((Timer2/60)/10, 0b10000000); _delay_ms(0.25); display_number((Timer2/60)%10, 0b01000000); _delay_ms(0.25); display_number((Timer2%60)/10, 0b00100000); _delay_ms(0.25); display_number((Timer2%60)%10, 0b00010000); _delay_ms(0.25); PORTD = 0; >void display_number(int number, int mask)

Функция display использует метод динамической индикации. Дело в том, что каждый отдельно взятый индикатор имеет 9 контактов (7 для управления сегментами, 1 для точки и 1 для питания). Для управления 4 цифрами понадобилось бы 36 контактов. Слишком расточительно. Поэтому вывод разрядов на индикатор с несколькими цифрами организован по следующему принципу:

Напряжение поочередно подается на каждый из общих контактов, что позволяет высветить на соответствующем индикаторе нужную цифру при помощи одних и тех же 8 управляющих контактов. При достаточно высокой частоте вывода это выглядит для глаза как статическая картинка. Именно поэтому все 8 питающих контактов обоих индикаторов на схеме подключены к 8 выходам порта D, а 16 управляющих сегментами контактов соединены попарно и подключены к 8 выходам порта B. Таким образом, функция display с задержкой в 0.25 мс попеременно выводит нужную цифру на каждый из индикаторов. Под конец отключаются все выходы, подающие напряжение на индикаторы (команда PORTD = 0; ). Если этого не сделать, то последняя выводимая цифра будет продолжать гореть до следующего вызова функции display, что приведет к ее более яркому свечению по сравнению с остальными.

Обработка нажатий

void handle_buttons() < handle_button(KEY_SETUP); handle_button(KEY_RESET); handle_button(KEY_PAUSE); handle_button(KEY_PLAYER1); handle_button(KEY_PLAYER2); >void handle_button(int key) < int bit; switch (key) < case KEY_SETUP: bit = SETUP_BIT; break; case KEY_RESET: bit = RESET_BIT; break; case KEY_PAUSE: bit = PAUSE_BIT; break; case KEY_PLAYER1: bit = PLAYER1_BIT; break; case KEY_PLAYER2: bit = PLAYER2_BIT; break; default: return; >if (bit_is_clear(BUTTON_PIN, bit)) < if (_pressed == 0) < _delay_ms(DEBOUNCE_TIME); if (bit_is_clear(BUTTON_PIN, bit)) < _pressed |= key; // key action switch (key) < case KEY_SETUP: process_setup(); break; case KEY_RESET: process_reset(); break; case KEY_PAUSE: process_pause(); break; case KEY_PLAYER1: process_player1(); break; case KEY_PLAYER2: process_player2(); break; >sound_on(15); > > > else < _pressed >>

Эта функция по очереди опрашивает все 5 кнопок и обрабатывает нажатие, если таковое случилось. Нажатие регистрируется проверкой bit_is_clear(BUTTON_PIN, bit) , т.е. кнопка нажата в том случае, если соответствующий ей вход соединен с землей, что и произойдет, согласно схеме, при нажатии кнопки. Задержка длительностью DEBOUNCE_TIME и повторная проверка нужна во избежание множественных лишних срабатываний из-за дребезга контактов. Сохранение статуса нажатия в соответствующих битах переменной _pressed используется для исключения повторного срабатывания при длительном нажатии на кнопку.
Функции обработки нажатий достаточно тривиальны и полагаю, что в дополнительных комментариях не нуждаются.

Полный текст программы

#define F_CPU 4000000UL #include #include #include #define DEBOUNCE_TIME 20 #define BUTTON_PIN PINC #define SETUP_BIT PC0 #define RESET_BIT PC1 #define PAUSE_BIT PC2 #define PLAYER1_BIT PC3 #define PLAYER2_BIT PC4 #define KEY_SETUP 0b00000001 #define KEY_RESET 0b00000010 #define KEY_PAUSE 0b00000100 #define KEY_PLAYER1 0b00001000 #define KEY_PLAYER2 0b00010000 volatile int ActiveTimer = 0; volatile int Timer1 = 0; volatile int Timer2 = 0; volatile int _buzzer = 0; volatile int _pressed = 0; // function declarations void init_io(); void init_data(); int number_mask(int num); void handle_buttons(); void handle_button(int key); void process_setup(); void process_reset(); void process_pause(); void process_timeoff(); void process_player1(); void process_player2(); void display(); void display_number(int mask, int number); void sound_on(int interval); void sound_off(); // interrupts ISR (TIMER0_OVF_vect) < display(); if (_buzzer >0) < _buzzer—; if (_buzzer == 0) sound_off(); >> ISR(TIMER1_COMPA_vect) < if (ActiveTimer == 1 Timer1 >0) < Timer1—; if (Timer1 == 0) process_timeoff(); >if (ActiveTimer == 2 Timer2 > 0) < Timer2—; if (Timer2 == 0) process_timeoff(); >> int main(void) < init_io(); init_data(); sound_off(); sei(); while(1) < handle_buttons(); >return 0; > void init_io() < // set output DDRB = 0xFF; DDRD = 0xFF; // set input DDRC = 0b11100000; // pull-up resistors PORTC |= 0b00011111; // timer interrupts TIMSK = (1<void init_data() < Timer1 = 0; Timer2 = 0; ActiveTimer = 0; >int number_mask(int num) < switch (num) < case 0 : return 0xC0; case 1 : return 0xF9; case 2 : return 0xA4; case 3 : return 0xB0; case 4 : return 0x99; case 5 : return 0x92; case 6 : return 0x82; case 7 : return 0xF8; case 8 : return 0x80; case 9 : return 0x90; >; return 0; > void process_setup() < Timer1 += 60; Timer2 += 60; // overflow check (5940 seconds == 99 minutes) if (Timer1 >5940 || Timer2 > 5940) < Timer1 = 0; Timer2 = 0; >> void process_reset() < init_data(); >void process_timeoff() < init_data(); sound_on(30); >void process_pause() < ActiveTimer = 0; >void process_player1() < ActiveTimer = 2; >void process_player2() < ActiveTimer = 1; >void handle_button(int key) < int bit; switch (key) < case KEY_SETUP: bit = SETUP_BIT; break; case KEY_RESET: bit = RESET_BIT; break; case KEY_PAUSE: bit = PAUSE_BIT; break; case KEY_PLAYER1: bit = PLAYER1_BIT; break; case KEY_PLAYER2: bit = PLAYER2_BIT; break; default: return; >if (bit_is_clear(BUTTON_PIN, bit)) < if (_pressed == 0) < _delay_ms(DEBOUNCE_TIME); if (bit_is_clear(BUTTON_PIN, bit)) < _pressed |= key; // key action switch (key) < case KEY_SETUP: process_setup(); break; case KEY_RESET: process_reset(); break; case KEY_PAUSE: process_pause(); break; case KEY_PLAYER1: process_player1(); break; case KEY_PLAYER2: process_player2(); break; >sound_on(15); > > > else < _pressed >> void handle_buttons() < handle_button(KEY_SETUP); handle_button(KEY_RESET); handle_button(KEY_PAUSE); handle_button(KEY_PLAYER1); handle_button(KEY_PLAYER2); >void display() < display_number((Timer1/60)/10, 0b00001000); _delay_ms(0.25); display_number((Timer1/60)%10, 0b00000100); _delay_ms(0.25); display_number((Timer1%60)/10, 0b00000010); _delay_ms(0.25); display_number((Timer1%60)%10, 0b00000001); _delay_ms(0.25); display_number((Timer2/60)/10, 0b10000000); _delay_ms(0.25); display_number((Timer2/60)%10, 0b01000000); _delay_ms(0.25); display_number((Timer2%60)/10, 0b00100000); _delay_ms(0.25); display_number((Timer2%60)%10, 0b00010000); _delay_ms(0.25); PORTD = 0; >void display_number(int number, int mask) < PORTB = number_mask(number); PORTD = mask; >void sound_on(int interval) < _buzzer = interval; // put buzzer pin high PORTC |= 0b00100000; >void sound_off() < // put buzzer pin low PORTC >

Прототип был собран на макетной плате:

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

Ниже показан окончательный вид устройства. Часы питаются от 9-вольтовой батарейки типа “Крона”. Потребление тока — 55 мА.

Потратив $20-25 на оборудование и пару вечеров на начальное ознакомление с архитектурой микроконтроллера и основными принципами работы, можно начать делать интересные DIY проекты. Статья посвящается тем, кто, как и я в свое время, думает, что начать программировать микроконтроллеры — это сложно, долго или дорого. Поверьте, начать намного проще, чем может показаться. Если есть интерес и желание — пробуйте, не пожалете!

Удачного всем программирования!

P.S. Ну и напоследок, небольшая видео-демонстрация прототипа:

Источник: habr.com

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru