Ввод информации в мк. подключение кнопки к мк bascom-avr

Урок 8. Ввод информации в МК. Подключение кнопки к МК BASCOM-AVR

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

Кнопки бывают двух видов: тактовые и фиксирующие. Тактовые кнопки работают по такому принципу: нажал – контакты замкнулись, отпустил – контакты разомкнулись. Следует учесть, что существуют тактовые кнопки, которые изначально замкнуты, а при нажатии размыкаются.

Фиксирующие кнопки (их иногда называют: тумблеры, выключатели, переключатели) в отличии от тактовых фиксируют своё положение при нажатии, то есть: нажал – контакты замкнулись, еще раз нажал – контакты разомкнулись.

В общем, с кнопками разобрались, теперь будем разбираться, как подключить эти кнопки к микроконтроллеру. А подключить на самом деле очень даже просто! Смотрим схему:

Возможно, вы спросите: Зачем резистор R1? А затем, что без резистора R1, когда кнопка S1 будет разомкнута, микроконтроллер на порте, к которому всё это подключено, будет видеть то логическую 1, то логический 0 тем самым будут производиться ложные срабатывания кнопки.

Чтобы этого не происходило необходимо этот порт “подтягивать” сопротивлением к плюсу питания. Сопротивление резистора R1 может быть в интервале от 4,7кОм до 10кОм.

С резистором получается такая картина: кнопка S1 нажата – на порте МК возникает логический 0, кнопка S1 не нажата – на порте МК возникает логическая 1 за счёт сопротивления R1.

Конечно, нужно знать, что в некоторых AVR микроконтроллерах есть встроенные подтягивающие резисторы сопротивление порядка 50кОм, по умолчанию они отключены. В BASCOM-AVR эти резисторы можно включить, записав в необходимый порт логическую 1.

Но я крайне не рекомендую использовать эти встроенные, гораздо надёжнее использовать внешние, как показано на схеме выше. Ну что, со схематическим решением разобрались, теперь будем разбираться программно. Для работы с кнопкой сначала нужно сконфигурировать порт микроконтроллера на вход, в BASCOM-AVR это делается вот так:
Config (порт микроконтроллера) = input Пример:

Config PINB.3 = input

Обратите внимание, что для работы порта на вход, имя порта должно начинаться с PIN, а не с PORT как для конфигурации порта на выход!

После конфигурации порта на вход мы можем считать с него значение 1 или 0, в нашем случае 0 – кнопка нажата, 1 – кнопка не нажата. А проверить, что кнопка нажата, мы можем так:
If (порт микроконтроллера) = 0 then (если кнопка нажата, то выполняем, действия описанные здесь)

End if

Можно и наоборот, проверить, не нажата ли кнопка:

If (порт микроконтроллера) = 1 then

(если кнопка не нажата, то выполняем, действия описанные здесь)

End if

Пример:

If PINB.3 = 0 then

PORTB.2 = 1 “если кнопка нажата, то включаем светодиод подключенный к PB.2
End if

Просто, не правда ли? Итак, теперь попробуем реализовать подключение кнопки к микроконтроллеру в “железе”. За основу возьмём микроконтроллер Attiny13 и отладочную плату для него сделанную немного ранее. Для того кто не делал отладочную плату, вот схема:

Алгоритм работы программы такой: кнопка S1 нажата – светодиод не горит, кнопка S1 не нажата – светодиод горит. А вот и сама программа на BASCOM-AVR:

$regfile = “attiny13.dat”
$crystal = 8000000 Config Pinb.3 = Input
Config Portb.2 = Output Do
If Pinb.3 = 0 Then Portb.2 = 0
If Pinb.3 = 1 Then Portb.2 = 1
Loop End

Вот такая простая программа. Скомпилированная прошивка находится в архиве ниже. Фьюз биты можно не выставлять, так как в такой простой программе тактовая частота не особо важна. Для ленивых собирать в железе есть проект в нашем любимом симуляторе Proteus, скачать можно в архиве ниже. Работа в схемы в симуляторе Proteus:

Скачать файлы для урока (проект в Proteus, исходник, прошивка) вы можете ниже

Урок 9. Работа с АЦП на примере ATtiny13 в BASCOM-AVR

Скачать список элементов (PDF)

Прикрепленные файлы:

Источник: http://cxem.net/mc/mc127.php

Подключение кнопки к AVR

Подключение кнопки к AVR не должно у вас вызывать никаких трудностей.

В предыдущей статье мы провели эмуляцию схемы в программе Proteus, помигали светодиодом и научились прошивать наш виртуальный микроконтроллер. Наверняка многим из читателей пришла в голову мысль: «А можно ли помигать светодиодом, использую кнопку, подключенную к МК?

Да, разумеется, это возможно. Реализуется довольно легко. Причем можно сэмулировать кнопку как с фиксацией так и без фиксации.

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

Давайте разберем подробнее, как это реализовать с помощью микроконтроллера, и проведем эмуляцию в программе Proteus.

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

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

До тех пор, пока эффект не закончит свою работу, программа не реагирует на нажатие или отжатие кнопки.

Итак к делу. Так выглядит у нас наша схема в программе Proteus (кликните для увеличения):

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

Как мы уже разобрали, питание и землю мы берем во вкладке «Терминал». Обозначаются они у нас соответственно Power и Ground.

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

Перед использованием нам нужно выбрать кнопку в библиотеке аналогично остальным деталям. Для этого нужно набрать в поле «Маска» слово «but».  Затем в поле «Результаты» слово «BUTTON»:

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

Какие порты у нас используются в проекте. Ниже на рисунке мы видим отходящие линии от портов РA0, РВ0, РВ1, РВ2 и РВ3. К порту В у нас подключены светодиоды, а к порту А —  кнопка.

Итак, при нажатии, мы замыкаем цепь соединяющую +5 вольт с портом РА0 и верхним выводом резистора. Для чего у нас здесь вообще установлен резистор? Дело в том, что цепь кнопки должна быть замкнутой. После того как мы установили резистор, ток у нас течет от плюса питания через кнопку, резистор и дальше на землю.

Номинал резистора достаточно взять равным 200 Ом. Итак, когда мы нажимаем кнопку, мы соединяем порт РА0 с +5 вольт питания, и если мы опросим ножку РА0 на наличие напряжения или его отсутствие, мы сможем влиять на выполнение нашей программы.

Скрины с текстом нашей программы я привел ниже:

Итак отличия от прошлого проекта заключаются в том, что все 8 выводов порта РА мы конфигурируем на вход, выводы порта РВ0 — РВ3 мы конфигурируем на выход, а РВ4 — РВ7 на вход.

Затем мы используем в нашей программе проверку условия «if»

Итак, мы видим в строчке после «if», в скобках, условие выполнения. Код ниже выполняется, если на порту PA0 у нас присутствует логический ноль, или ноль вольт. Этот текст в скобках —  сдвиг бита порта.

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

Если условие не верно, программа продолжает выполняться дальше, пропустив текст в фигурных скобках.

Аналогично, с помощью условия «if» мы опрашиваем кнопку на нажатие. Обратите внимание, текст у нас в скобках изменился. Это означает что если на ножке РА0 у нас логическая единица, мы выполняем условие, то есть текст в фигурных скобках.

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

Таким образом, мы можем влиять на выполнение программы, с помощью нажатия кнопки, опрашивая наличие на ней логического нуля, или логической единицы

Также прикрепляю архив, в котором находятся файл «сишник», HEX и файл Протеуса.

А вот и видео

Источник: https://www.ruselectronic.com/podklyuchenie-knopki-k-mk-avr/

Работа с кнопками программа обработки нажатия для микроконтроллера ATmega8

В этой заметке пойдет речь о считывании информации с помощью клавиш. Выводить введенную информацию будем на алфавитно-символьный ЖКИ. Предлагаю начать с самого простого. Подсоединим одну клавишу, без фиксатора, нормально разомкнутую и рассмотрим некоторые тонкости работы.

В этой заметке пойдет речь о считывании информации с помощью клавиш. Выводить введенную информацию будем на алфавитно-символьный ЖКИ. Предлагаю начать с самого простого. Подсоединим одну клавишу, без фиксатора, нормально разомкнутую и рассмотрим некоторые тонкости работы.

Испытуемая клавиша А2 при нажатии закорачивает вывод PB0 на «землю». Вся остальная обвязка стандартна.

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

Второй тонкостью является вопрос:

При появлении логического нуля на выводе порта микроконтроллера на протяжении 1мс? Но при залипании клавиши может возникнуть неприятная ситуация.
Третьим будет вопрос,

«с какой периодичностью проверять клавиши?»

Так как реакция человека на внешние раздражители редко когда превышает 0,03с. То условимся считывать состояние клавиатуры 100 раз в секунду.

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

В связи с этими рассуждениями напишем программу, которая будет обрабатывать нажатие одной клавиши, имитируя включение чего-то, на ЖКИ соответственно будем писать «On», «Off».

  1. #include //Библиотека ввода/вывода

  2. #include //Библиотека прерываний

  3. #define RS 2 //Вывод ЖКИ RS подключаем на вывод PD2 МК

  4. #define E 3 //Вывод ЖКИ E подключаем на вывод PD3 МК

  5. #define TIME<\p>

  6. //Временная константа для ЖКИ

  7. //Тактовая частота 4Mhz

  8. unsigned char status=0;

  9. //Переменная статуса

  10. //Программа задержки

  11. void pause (unsigned int a)<\p>

  12. {<\p>

  13. unsigned int i; //декларация переменной для программы задержки

  14. for (i=a;i>0;i–); //Основной цикл программы задержки

  15. }

  16. //Передача команды в ЖКИ<\p>

  17. void lcd_com (unsigned char lcd) //Программа записи команд в ЖКИ<\p>

  18. {<\p>

  19. unsigned char temp;

  20. temp=(lcd&~(1

Источник: https://avrlab.com/node/83

Как подключить к микроконтроллеру кнопки

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

Думаю, что материал будет полезен начинающим.Чтобы не сбивать вас с толку, на приведенных ниже рисунках не показаны схемы питания, сброса и тактирования микроконтроллеров.

                             рис1а                                                                            рис1б

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

   Когда кнопка отпущена – вывод мк через резистор соединен с “плюсом” питания (рис. 1а). Когда кнопка нажата – вывод мк соединен с землей. Подтягивающий резистор R1  ограничивает силу тока в цепи переключателя. Если бы его не было, то при нажатии кнопки мы бы просто закоротили наш источник питания.

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

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

Если на выводе “логический  ноль” – ничего страшного не случиться, потому что – в первом случае (рис1а) величина втекающего тока ограничена резистором R1, а во втором случае (рис1б)  никакой ток вообще не потечет.

При нажатии кнопки тоже ничего не случиться, поскольку разность потенциалов между выводом и “землей” в этом случае будет равна нулю.

   Если же на выводе будет ”логическая единица” и кнопка окажется нажатой, то через вывод микроконтроллера на землю потечет ток величиной в несколько десятков миллиампер и вывод порта может “погореть”. Предельно допустимый ток для вывода микроконтролера AVR согласно документации равен 40 мА.

Поэтому иногда нелишним бывает поставить между выводом мк и кнопкой резистор номиналом в несколько сотен ом, например 330 (рис 1с). Так, например, подключены кнопки на отладочной плате STK500.

Это сделано для подстраховки, чтобы пользователь нечаянно не спалил микроконтроллер в ходе своих эксперементов.

   Для своих макетов впрочем можно обойтись и без этого резистора. 

 Рис 1с

Рис. 2а

Рис. 2б

     Используется когда кнопок больше двух, а выводы мк хочется сэкономить. Каждой кнопке в данном случае соответствует свой цифровой код, а  количество кнопок, которые можно таким способом повесить на N выводов мк =  2N  – 1. То есть на три вывода можно повесить 7 кнопок, на четыре – 15 и так далее.

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

   Кстати, через диоды еще можно завести сигналы от кнопок на вывод внешнего прерывания контроллера (рис. 3).

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

Таким образом контроллеру не нужно будет постоянно опрашивать кнопки, эта процедура будет запускаться только по событию внешнего прерывания. 

                                                                             Рис. 3

   Данная схема актуальна не для всех микроконтроллеров AVR, потому что в некоторых моделях микроконтроллеров внешнее прерывание может возникать по любому изменению на любом выводе. (например в ATmega164P)

Рис. 4

   Такой вариант подключения обычно используется для блоков из нескольких кнопок, которые объединены конструктивно и соединены электрически по матричной схеме. Но никто не запрещает использовать эту схему и для включения  обычных кнопок, однако реальную экономию она дает при количестве кнопок ? 9.

   Выводы PС0, PС1, PС2, PC3  – это строки матрицы, выводы PB0, PB1, PB2 – это столбцы матрицы. Кнопки можно опрашивать либо по строкам, либо по столбцам. Допустим, мы опрашиваем их по столбцам. Процедура опроса будет выглядеть следующим образом.

Начальное состояние всех выводов – вход с включенным подтягивающим резистором. Устанавливаем вывод PB0 в режим выхода и выставляем ноль. Теперь нажатие кнопок S1, S2, S3, S4 будет замыкать выводы PС0, PС1, PС2, PC3 на 0 питания.

Опрашиваем эти выводы и определям нажата ли какая-нибудь кнопка в данный момент. Устанавливаем вывод PB0 в режим выхода и включаем подтягивающий резистор. Устанавливаем вывод PB1 в режим выхода и выставляем ноль. Снова опрашиваем выводы PС0, PС1, PС2, PC3.

Теперь нажатие кнопок S5, S6, S7, S8 будет замыкать выводы PС0, PС1, PС2, PC3. Последний столбец кнопок опрашиваем аналогично. 
 

   Строки матрицы можно завести через диоды на вывод внещнего прерывания. Тогда логику программы можно было бы построить так. Если клавиатура не используется в течении нескольких минут, микроконтроллер переходит в режим пониженного энергопотребления. При этом выводы PB0, PB1, PB2 – конфигурируются как выходы с нулевым логическим уровнем.

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

Как только он переполняется, микроконтроллер опять переходит в режим пониженного энергопотребления. 

   Это, пожалуй, пограничный случай экономии выводов при подключении кнопок, поскольку задействован только один вывод микроконтроллера – вывод АЦП. Суть способа понятна из рисунка.

У нас есть резистивный делитель  с известными уровнями напряжений на резисторах, с помощью кнопок эти напряжения мы коммутируем на вход АЦП.

Контроллер оцифровывает напряжение на этом выводе  и, исходя из того, в какой диапазон попадает считанное напряжение, определяет номер нажатой кнопки.

  Когда ни одна кнопка не нажата, вход АЦП притянут к земле резистором R2. Оставлять вход АЦП плавающим нельзя, а то он будет ловить помехи. При замыкании кнопок резистор R2 оказывается включенным параллельно с резисторами делителя.

Чтобы он не влиял на уровень напряжения на входе АЦП, его значение выбирают довольно большим.

Резистор R1 предназначен для ограничения величины входного тока в случае если вывод контроллера окажется в режиме цифрового входа и будет нажата кнопка S5.

Рис. 5

  Есть еще один вариант подобной схемы приведен на рис. 6. Здесь с помощью кнопок определенные резисторы делителя напряжения коммутируются на землю.

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

Рис. 6

Продолжение следует…

Источник: http://chipenable.ru/index.php/item/13

Подключаем кнопки к AVR. Шаг №12

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

Материала в интернете куча, но каждый индивидуальный взгляд на решение вопроса увеличивает скорость понимания данного направления. Поэтому я и решил написать. Ну что ж перейдем к кнопкам. Зачем нужны кнопки? К примеру вы создаете тот же барьер — реле напряжения, но для гибкости устройства необходимо менять граничные уровни напряжения, т.к.

сеть у каждого очень индивидуальна, к сожалению. Вот тут и приходят на помощь кнопки.

Кнопка —это механическое устройство для передачи сигнала/ввода информации путём замыкания или размыкания двух или более контактов. По сути своей является датчиком внешнего физического воздействия.

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

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

В данном случае, просто подсоединяем один конец к ножке МК, а второй вывод к земле либо к питанию. Не забываем задействовать внутренний подтягивающий резистор для исключения помех от наводок, даже тем же пальцем. Принцип следующий настраиваем порт как вход т.е.

регистр DDRx выставляем в 0, далее подтягиваем внутренние резисторы, т.е. выставляет регистр PORTx в1.

А далее алгоритм опроса, вот здесь он может быть очень индивидуален, ну во первых если нам необходимо  просто ввести данные вначале программы и далее кнопки недолжны реагировать, то тут можно поместить опрос в циклическое условие, например ниже представлен кусочек кода моей программы на СИ для двух кнопок. 

while ((e == 0)&&(e1 == 0)) //  Начало цикла, берем любые переменные, к примеру равные нулю

        // Далее начинается обработка кода, пока не поменяется, хотя бы одно значение переменной на истинно

         {

   if ((PIND & 0×20) == 0) // здесь мы нажали на кнопку, и в данном случае на пине 5 порта установился 0. Ниже небольшой код по обработке дребезга контактов, о нем написал чуть ниже

   {

                   _delay_ms (50);         // Устранение дребезга клавиш

                   if ((PIND & 0×20) == 0) // Опять проверяем нажатие

                      e++;             //Увеличиваем на 1

                      ……     ;          // Здесь выполняется необходимая нам команда

                   while ((PIND & 0×20) == 0) //Все ждем отпускание кнопки

                          {}

}  // Выходим из условия

  else {}; //можно и неиспользовать, пустая комманда, даже занимающая сокото там тактов

              if ((PIND & 0×40) == 0) // а здесь мы нажал на кнопку с2, ну и т.д.

               {

                      _delay_ms (50);

                       if ((PIND & 0×40) == 0)

                      e1++;

                      ……;

                      while ((PIND & 0×40) == 0)

                      {}

               }

               else {};

             ……;

 }; // выходим из циклического условия если мы нажали хотя бы одну кнопку

Данный код представляет примерный подход опроса двух кнопок. Алгоритм может меняться как пожелает фантазия. Но самое главное что в коде опроса должен присутствовать антидребезговый код.

Что это? Дребезг это явление возникает в переключателях, которое представляет собой в момент переключения случайные многократные неконтролируемые замыкания и размыкания контактов и длятся они от десятков до сотен миллисекунд. На рисунке ниже у нас пример дребезга. Т.к.

в протеусе все идеально, то пришлось дорисовать реальность – дребезг красным. Что у нас получается, МК посчитает, перед переходом на другую команду в момент переключения кнопки любое состояние из полосы неопределенности 0 или 1 которая возникает при  колебаниях за счет дребезга контактов. Т.е.

выходит угадал не угадал… Техника требует точности. Борются двумя методами, первый для компенсации дребезга применяют переключатели с обратной связью, с характеристикой в виде прямоугольной петли гистерезиса и т. д., второй программный метод. Этот метод мы  и рассмотрим . В коде выше есть комментарий //Устранение дребезга клавиш.

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

Давайте рассмотрим случай когда кнопка должна использоваться на протяжении всего времени  работы устройства. Здесь нам на помощь приходят прерывания, например их можно использовать внешнее прерывание. К примеру подключаем кнопку к выводу INT0, другой вывод  к земле, здесь зависит от определения условий генераций внешних прерывания и от типа МК.

Читайте даташит. Порт также настраиваем на вход, подтягиваем резистор. В нормальном состоянии, когда кнопка разомкнута на выводе присутствует 1. В момент замыкания на вывод приходит 0, где по спадающему фронту (настройка) запускается обработчик прерываний. Для запуска внешнего прерывания необходимо флаг I регистра SREG установить в 1.

При возникновения прерывания этот флаг аппаратно сбрасывается. Если мы хотим вызывать вложенные прерывания то необходимо программно установить этот флаг. При выходе из обработчика необходимо выполнить комманду reti; , которая установит этот флаг в 1.

Например в программе считывания кнопок на АЦП был описан способ считывания кнопок в прерывании, только уже используя АЦП.

Ниже приведен код для работы с внешним прерыванием.

GICR =0×40; //Управляющий регистр для разрешения/запрещения  прерываний. Разрешаем внешние прерывание INT0.
MCUCR = 0×02; //Конфигурационный регистр для выбора условий генераций внешнего прерывания. По спадающему фронту.
sei (); //установка флага I регистра SREG в 1. Разрешение общего прерывания.

Должен быть обязательно установлен.
SIGNAL (SIG_INTERRUPT0)//Обработчик прерывания по вектору внешнего прерывания. Данные векторы хорошо описаны в Шпаке для среды WinAVR.

{  //Здесь  пишем необходимый нам код при нажатии на кнопку   }
//Далее обработчик прерывания заканчивает свою работу, и программа возвращается в основной цикл.

Также наверное стоит упомянуть о регистре GIFR, флаги которого используются для индикации прерываний. Кому необходимо читаем даташит.Способов использования прерываний для кнопок куча, поэтому читаем, подбираем… На этом все. В следующей статье поговорим об использовании памяти EEPROM. Всем пока.

Просмотрено 30778 раз.

Источник: http://www.ap-impulse.ru/podklyuchaem-knopki-k-avr-shag-12/

Устройство и работа портов ввода-вывода микроконтроллеров AVR. Часть 4

Подключение кнопки к линии порта ввода/вывода Изучив данный материал, в котором все очень детально и подробно описано с большим количеством примеров, вы сможете легко овладеть и программировать порты ввода/вывода микроконтроллеров AVR.
Пример будем рассматривать на микроконтроллере ATMega8.

Программу писать будем в Atmel Studio 6.0.

Эмулировать схему будем в Proteus 7 Professional.

Самой распространенной задачей при создании проектов для микроконтроллеров является подключение кнопок. Несмотря на простоту, эта задача имеет существенные, возможно и неочевидные особенности. Если подключить один из контактов кнопки, например, к общему проводу («земле»), а второй к выбранной линии порта ввода/вывода микроконтроллера, который переключен в режим «Вход», то выяснится, что такой метод не работает. При нажатии кнопки линия порта микроконтроллера соединяется с землей, и программа будет считывать лог.«0» с этой линии порта ввода/вывода, но при отпущенной кнопке вывод микроконтроллера не будет соединен ни с чем, что часто и называют «висит в воздухе». В таком случае программа будет считать с вывода и лог.«0» и лог.«1» случайным образом, так как на не к чему не присоединённую линию порта ввода/вывода будут наводится наводки. Правильное подключение предполагает, что в разомкнутом состоянии вывод микроконтроллера должен быть соединен через резистор, например с шиной питания, а в замкнутом — с землей, либо наоборот. Сопротивление резистора не должно быть слишком маленьким, чтобы ток, текущий через него при замкнутых контактах кнопки не был слишком большим. Обычно используют значения порядка 10-100 кОм.Рис: Подключения кнопки с подтянутой шиной питания. При таком подключении состояние линии порта ввода вывода будет: — при отжатой кнопке равно лог.«1»; — при нажатой кнопке равно лог.«0»;Рис: Подключения кнопки с подтянутой землей. При таком подключении состояние линии порта ввода вывода будет: — при отжатой кнопке равно лог.«0»; — при нажатой кнопке равно лог.«1»;

— подключения к линии порта ввода/вывода кнопки с подтянутой шиной питания:

// Подключаем внешние библиотеки
#include #include // Основная программа
int main(void) { // Настраиваем порты ввода/вывода DDRB = 0b11111111; //Настраиваем все разряды порта B на режим “Выход” PORTB = 0b00000000; //Устанавливаем все разряды порта B в лог.«0» (На выходе порта напряжение равное GND) DDRD = 0b00000000; //Настраиваем все разряды порта D на режим “Вход” PORTD = 0b11111111; //Устанавливаем все разряды порта D в лог.«1» (На выходе порта напряжение равное Vcc) // Вечный цикл while (1) { //Проверяем: если состояние PD0 лог.«0» то кнопка нажата if ((PIND&(1

Источник: https://habr.com/post/256269/

Урок 2. Управление кнопками в AVR

На первом уроке мы научились подавать напряжение ножкой микроконтроллера. Теперь нужно научиться управлять микроконтроллером без перепрошивки.

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

https://www.youtube.com/watch?v=HQ3ixolWKb8

Помните в первом уроке мы настраивали ножку как выход, т.е. мы могли ей подавать напряжение. Так вот, ножку можно настроить как вход. В таком режиме можно проверить есть ли на ней напряжение или нет.

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

После создания проекта приведем код к такому виду:

#include
#include
 
void main(void)
{
 
PORTB=0x02;
DDRB=0x01;
 
while (1)
{
 
if(PINB.1==0)
{
PORTB.0=1;
delay_ms(100);
PORTB.0=0;
delay_ms(100);
}
 
};
}

#include #include void main(void) { PORTB=0x02; DDRB=0x01; while (1) { if(PINB.1==0) { PORTB.0=1; delay_ms(100); PORTB.0=0; delay_ms(100); } }; }

Как мы видим, по сравнению с первым уроком изменилась настройка порта

PORTB=0x02; DDRB=0x01;

Подробнее о том что значат данные строки можно почитать тут

Также появилась новая строчка

if(PINB.1==0) {}

данную строчку нужно читать так — если на ножке 1 порта В подключили землю (0 потенциал), то выполнить код в фигурных скобках. В нашем примере это код из первого урока. Если кнопка не замкнута, то ничего не делать. Промоделировать можно в Proteuse.

Вместо кнопки можно поставить датчик, реле и т.п., вместо светодиода — пищалку, получится сигнализация.

Архив с прошивкой и файлом протеуса доступен тут

Update1: Зачем нужна подтяжка порта?
У входа мк большое сопротивление, если будут течь даже микротоки вызванные помехами, то по закону Ома U=R*I это может привести к тому, что на входе появится лог 1.

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

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

Почему подключение через резистор? Допустим мы подключили вход к плюсу напрямую без резистора. Когда кнопка сработает, она притянет вход к земле, поэтому на входе будет короткое замыкание между + и землей.

Если же стоит резистор, то при замыкании кнопки с одной стороны он так и останется подключен к +, а со второй стороны на нем появится земля от кнопки.

Через резистор потечет ток, но его величина будет не такой большой.

Update2: Добавлен тест, в котором вы можете проверить на сколько хорошо вы усвоили материал урока

This movie requires Flash Player 9

Источник: http://avr-start.ru/?p=197

Подключение кнопки

Источник: http://robotsspace.ucoz.ru/publ/podkljuchenie_knopki/9-1-0-62

Как подружить BASCOM AVR с USB? (AN #178

Источник: http://bascom.at.ua/publ/kak_podruzhit_bascom_avr_s_usb_russkij_variant_an_178_software_implementation_of_usb_in_avr/1-1-0-34

Ссылка на основную публикацию
Adblock
detector
",css:{backgroundColor:"#000",opacity:.6}},container:{block:void 0,tpl:"
"},wrap:void 0,body:void 0,errors:{tpl:"
",autoclose_delay:2e3,ajax_unsuccessful_load:"Error"},openEffect:{type:"fade",speed:400},closeEffect:{type:"fade",speed:400},beforeOpen:n.noop,afterOpen:n.noop,beforeClose:n.noop,afterClose:n.noop,afterLoading:n.noop,afterLoadingOnShow:n.noop,errorLoading:n.noop},o=0,p=n([]),h={isEventOut:function(a,b){var c=!0;return n(a).each(function(){n(b.target).get(0)==n(this).get(0)&&(c=!1),0==n(b.target).closest("HTML",n(this).get(0)).length&&(c=!1)}),c}},q={getParentEl:function(a){var b=n(a);return b.data("arcticmodal")?b:(b=n(a).closest(".arcticmodal-container").data("arcticmodalParentEl"),!!b&&b)},transition:function(a,b,c,d){switch(d=null==d?n.noop:d,c.type){case"fade":"show"==b?a.fadeIn(c.speed,d):a.fadeOut(c.speed,d);break;case"none":"show"==b?a.show():a.hide(),d();}},prepare_body:function(a,b){n(".arcticmodal-close",a.body).unbind("click.arcticmodal").bind("click.arcticmodal",function(){return b.arcticmodal("close"),!1})},init_el:function(d,a){var b=d.data("arcticmodal");if(!b){if(b=a,o++,b.modalID=o,b.overlay.block=n(b.overlay.tpl),b.overlay.block.css(b.overlay.css),b.container.block=n(b.container.tpl),b.body=n(".arcticmodal-container_i2",b.container.block),a.clone?b.body.html(d.clone(!0)):(d.before("
"),b.body.html(d)),q.prepare_body(b,d),b.closeOnOverlayClick&&b.overlay.block.add(b.container.block).click(function(a){h.isEventOut(n(">*",b.body),a)&&d.arcticmodal("close")}),b.container.block.data("arcticmodalParentEl",d),d.data("arcticmodal",b),p=n.merge(p,d),n.proxy(e.show,d)(),"html"==b.type)return d;if(null!=b.ajax.beforeSend){var c=b.ajax.beforeSend;delete b.ajax.beforeSend}if(null!=b.ajax.success){var f=b.ajax.success;delete b.ajax.success}if(null!=b.ajax.error){var g=b.ajax.error;delete b.ajax.error}var j=n.extend(!0,{url:b.url,beforeSend:function(){null==c?b.body.html("
"):c(b,d)},success:function(c){d.trigger("afterLoading"),b.afterLoading(b,d,c),null==f?b.body.html(c):f(b,d,c),q.prepare_body(b,d),d.trigger("afterLoadingOnShow"),b.afterLoadingOnShow(b,d,c)},error:function(){d.trigger("errorLoading"),b.errorLoading(b,d),null==g?(b.body.html(b.errors.tpl),n(".arcticmodal-error",b.body).html(b.errors.ajax_unsuccessful_load),n(".arcticmodal-close",b.body).click(function(){return d.arcticmodal("close"),!1}),b.errors.autoclose_delay&&setTimeout(function(){d.arcticmodal("close")},b.errors.autoclose_delay)):g(b,d)}},b.ajax);b.ajax_request=n.ajax(j),d.data("arcticmodal",b)}},init:function(b){if(b=n.extend(!0,{},a,b),!n.isFunction(this))return this.each(function(){q.init_el(n(this),n.extend(!0,{},b))});if(null==b)return void n.error("jquery.arcticmodal: Uncorrect parameters");if(""==b.type)return void n.error("jquery.arcticmodal: Don't set parameter \"type\"");switch(b.type){case"html":if(""==b.content)return void n.error("jquery.arcticmodal: Don't set parameter \"content\"");var e=b.content;return b.content="",q.init_el(n(e),b);case"ajax":return""==b.url?void n.error("jquery.arcticmodal: Don't set parameter \"url\""):q.init_el(n("
"),b);}}},e={show:function(){var a=q.getParentEl(this);if(!1===a)return void n.error("jquery.arcticmodal: Uncorrect call");var b=a.data("arcticmodal");if(b.overlay.block.hide(),b.container.block.hide(),n("BODY").append(b.overlay.block),n("BODY").append(b.container.block),b.beforeOpen(b,a),a.trigger("beforeOpen"),"hidden"!=b.wrap.css("overflow")){b.wrap.data("arcticmodalOverflow",b.wrap.css("overflow"));var c=b.wrap.outerWidth(!0);b.wrap.css("overflow","hidden");var d=b.wrap.outerWidth(!0);d!=c&&b.wrap.css("marginRight",d-c+"px")}return p.not(a).each(function(){var a=n(this).data("arcticmodal");a.overlay.block.hide()}),q.transition(b.overlay.block,"show",1*")),b.overlay.block.remove(),b.container.block.remove(),a.data("arcticmodal",null),n(".arcticmodal-container").length||(b.wrap.data("arcticmodalOverflow")&&b.wrap.css("overflow",b.wrap.data("arcticmodalOverflow")),b.wrap.css("marginRight",0))}),"ajax"==b.type&&b.ajax_request.abort(),p=p.not(a))})},setDefault:function(b){n.extend(!0,a,b)}};n(function(){a.wrap=n(document.all&&!document.querySelector?"html":"body")}),n(document).bind("keyup.arcticmodal",function(d){var a=p.last();if(a.length){var b=a.data("arcticmodal");b.closeOnEsc&&27===d.keyCode&&a.arcticmodal("close")}}),n.arcticmodal=n.fn.arcticmodal=function(a){return e[a]?e[a].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof a&&a?void n.error("jquery.arcticmodal: Method "+a+" does not exist"):q.init.apply(this,arguments)}}(jQuery)}var debugMode="undefined"!=typeof debugFlatPM&&debugFlatPM,duplicateMode="undefined"!=typeof duplicateFlatPM&&duplicateFlatPM,countMode="undefined"!=typeof countFlatPM&&countFlatPM;document["wri"+"te"]=function(a){let b=document.createElement("div");jQuery(document.currentScript).after(b),flatPM_setHTML(b,a),jQuery(b).contents().unwrap()};function flatPM_sticky(c,d,e=0){function f(){if(null==a){let b=getComputedStyle(g,""),c="";for(let a=0;a=b.top-h?b.top-h{const d=c.split("=");return d[0]===a?decodeURIComponent(d[1]):b},""),c=""==b?void 0:b;return c}function flatPM_testCookie(){let a="test_56445";try{return localStorage.setItem(a,a),localStorage.removeItem(a),!0}catch(a){return!1}}function flatPM_grep(a,b,c){return jQuery.grep(a,(a,d)=>c?d==b:0==(d+1)%b)}function flatPM_random(a,b){return Math.floor(Math.random()*(b-a+1))+a}
");let k=document.querySelector(".flat_pm_modal[data-id-modal=\""+a.ID+"\"]");if(-1===d.indexOf("go"+"oglesyndication")?flatPM_setHTML(k,d):jQuery(k).html(b+d),"px"==a.how.popup.px_s)e.bind(h,()=>{e.scrollTop()>a.how.popup.after&&(e.unbind(h),f.unbind(i),j())}),void 0!==a.how.popup.close_window&&"true"==a.how.popup.close_window&&f.bind(i,()=>{e.unbind(h),f.unbind(i),j()});else{let b=setTimeout(()=>{f.unbind(i),j()},1e3*a.how.popup.after);void 0!==a.how.popup.close_window&&"true"==a.how.popup.close_window&&f.bind(i,()=>{clearTimeout(b),f.unbind(i),j()})}f.on("click",".flat_pm_modal .flat_pm_crs",()=>{jQuery.arcticmodal("close")})}if(void 0!==a.how.outgoing){let b,c="0"==a.how.outgoing.indent?"":" style=\"bottom:"+a.how.outgoing.indent+"px\"",e="true"==a.how.outgoing.cross?"":"",f=jQuery(window),g="scroll.out"+a.ID,h=void 0===flatPM_getCookie("flat_out_"+a.ID+"_mb")||"false"!=flatPM_getCookie("flat_out_"+a.ID+"_mb"),i=document.createElement("div"),j=jQuery("body"),k=()=>{void 0!==a.how.outgoing.cookie&&"false"==a.how.outgoing.cookie&&h&&(jQuery(".flat_pm_out[data-id-out=\""+a.ID+"\"]").addClass("show"),j.on("click",".flat_pm_out[data-id-out=\""+a.ID+"\"] .flat_pm_crs",function(){flatPM_setCookie("flat_out_"+a.ID+"_mb",!1)})),(void 0===a.how.outgoing.cookie||"false"!=a.how.outgoing.cookie)&&jQuery(".flat_pm_out[data-id-out=\""+a.ID+"\"]").addClass("show")};switch(a.how.outgoing.whence){case"1":b="top";break;case"2":b="bottom";break;case"3":b="left";break;case"4":b="right";}jQuery("body > *").eq(0).before("
"+e+"
");let m=document.querySelector(".flat_pm_out[data-id-out=\""+a.ID+"\"]");-1===d.indexOf("go"+"oglesyndication")?flatPM_setHTML(m,d):jQuery(m).html(e+d),"px"==a.how.outgoing.px_s?f.bind(g,()=>{f.scrollTop()>a.how.outgoing.after&&(f.unbind(g),k())}):setTimeout(()=>{k()},1e3*a.how.outgoing.after),j.on("click",".flat_pm_out .flat_pm_crs",function(){jQuery(this).parent().removeClass("show").addClass("closed")})}countMode&&(flat_count["block_"+a.ID]={},flat_count["block_"+a.ID].count=1,flat_count["block_"+a.ID].click=0,flat_count["block_"+a.ID].id=a.ID)}catch(a){console.warn(a)}}function flatPM_start(){let a=flat_pm_arr.length;if(0==a)return flat_pm_arr=[],void jQuery(".flat_pm_start, .flat_pm_end").remove();flat_body=flat_body||jQuery("body"),!flat_counter&&countMode&&(flat_counter=!0,flat_body.on("click","[data-flat-id]",function(){let a=jQuery(this),b=a.attr("data-flat-id");flat_count["block_"+b].click++}),flat_body.on("mouseenter","[data-flat-id] iframe",function(){let a=jQuery(this),b=a.closest("[data-flat-id]").attr("data-flat-id");flat_iframe=b}).on("mouseleave","[data-flat-id] iframe",function(){flat_iframe=-1}),jQuery(window).on("beforeunload",()=>{jQuery.isEmptyObject(flat_count)||jQuery.ajax({async:!1,type:"POST",url:ajaxUrlFlatPM,dataType:"json",data:{action:"flat_pm_ajax",data_me:{method:"flat_pm_block_counter",arr:flat_count}}})}).on("blur",()=>{-1!=flat_iframe&&flat_count["block_"+flat_iframe].click++})),flat_userVars.init();for(let b=0;bflat_userVars.textlen||void 0!==a.chapter_sub&&a.chapter_subflat_userVars.titlelen||void 0!==a.title_sub&&a.title_subc&&cc&&c>d&&(b=flatPM_addDays(b,-1)),b>e||cd||c-1!=flat_userVars.referer.indexOf(a))||void 0!==a.referer.referer_disabled&&-1!=a.referer.referer_disabled.findIndex(a=>-1!=flat_userVars.referer.indexOf(a)))&&(c=!0),c||void 0===a.browser||(void 0===a.browser.browser_enabled||-1!=a.browser.browser_enabled.indexOf(flat_userVars.browser))&&(void 0===a.browser.browser_disabled||-1==a.browser.browser_disabled.indexOf(flat_userVars.browser)))){if(c&&void 0!==a.browser&&void 0!==a.browser.browser_enabled&&-1!=a.browser.browser_enabled.indexOf(flat_userVars.browser)&&(c=!1),!c&&(void 0!==a.geo||void 0!==a.role)&&(""==flat_userVars.ccode||""==flat_userVars.country||""==flat_userVars.city||""==flat_userVars.role)){flat_pm_then.push(a),flatPM_setWrap(a),flat_body.hasClass("flat_pm_block_geo_role")||(flat_body.addClass("flat_pm_block_geo_role"),flatPM_ajax("flat_pm_block_geo_role")),c=!0}c||(flatPM_setWrap(a),flatPM_next(a))}}}let b=jQuery(".flatPM_sticky");b.each(function(){let a=jQuery(this),b=a.data("height")||350,c=a.data("top");a.wrap("
");let d=a.parent()[0];flatPM_sticky(this,d,c)}),debugMode||countMode||jQuery("[data-flat-id]:not([data-id-out]):not([data-id-modal])").contents().unwrap(),flat_pm_arr=[],jQuery(".flat_pm_start, .flat_pm_end").remove()}

В данной статье описано подключение тактовой кнопки к микроконтроллеру семейства AVR. Приведены алгоритмы обработки событий кнопки и программного антидребезга. В качестве примера приведена программа управления светодиодом, написанная в CodeVisionAVR.

Аппаратная реализация.

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

Но устройство AVR контроллеров позволяет упростить схему за счет внутренних ресурсов чипа. В качестве резистора R* можно задействовать встроенный резистор в МК. Правда, это надо будет программно прописать (не забудьте об этом!!!). В конечном варианте схема будет выглядеть вот так:

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

Для примера нам потребуется светодиод, подключеный через токоограничивающий резистор 220-330 Ом.

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

Программная реализация.

Простейший случай.

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

Тогда при нажатии кнопки (соединении линии порта с землей) линия будет иметь низкий уровень. Это изменение и будет отслеживать наша программа.
Рассмотрим пример, в котором при каждом нажатии на кнопку, светодиод будет менять свое состояние.

Для этого организуем цикл.

Алгоритм получился примерно вот такой:

Пояснение: в бесконечном цикле микроконтроллер проверяет состояние своего входа, и в случае обнаружения на нем низкого уровня (замыкание вывода на землю) производит нужные операции.

Дребезг контактов.

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

То есть, когда вы нажимаете на кнопку, контакты не сразу занимают нужное положение, перед этим они начинают колебаться, приводя к неоднократному срабатыванию кнопки – это явление называется дребезг контактов. На рисунке показан график того, что примерно происходит на входе контроллера при нажатии кнопки.

Для человека такое время колебания незначительно – мы его даже не заметим. Другое дело, микроконтроллер: предположим, проверка кнопки осуществляется в цикле, а контроллер работает на частоте 8 МГц, в таком случае, проверка кнопки будет осуществляться несколько тысяч, если не десятков тысяч раз в секунду.

Может получиться так, (а скорее всего так и получится) что за то время, пока происходит дребезг, программа еще раз проверит кнопку – в таком случае предсказать результат сложно (раз на раз не приходится)

Программный антидребезг

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

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

Алгоритм антидребезга при этом будет выглядеть так:

Важно помнить, что при отпускании кнопки дребезг так же будет происходить!


Ожидание отпускания кнопки.

Предположим, вы нажали кнопку и держите. Программа проверит ее в первый раз – сделает все так, как надо. Обработает антидребезг, выполнит все что нужно. А потом при последующей проверке снова обнаружит, что кнопка нажата – непорядок.

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

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

Алгоритм приобретет такой вид:

В плане теории, в общем-то все) Поздравляю, если вы дочитали до этого места!

Пример применения всего вышеописанного.

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

Алгоритм работы программы следующий:

Реализация данного алгоритма зависит от того, на каком языке вы пишите, и как вы это делаете. В качестве примера привожу реализацию в компиляторе CodeVision AVR

Code

/***************************************************** This program was produced by the CodeWizardAVR V2.04.0a Evaluation Automatic Program Generator © Copyright 1998-2009 Pavel Haiduc, HP InfoTech s.r.l. http://www.hpinfotech.com Project : Test Version : 1.0.0.0.1 Date : 20.09.2009 Author : DeepBlack Company :   Comments:   for robotsspace.ucoz.ru Chip type : ATmega8 Program type : Application AVR Core Clock frequency: 16,000000 MHz Memory model : Small External RAM size : 0 Data Stack size : 256 *****************************************************/ #include #include // Declare your global variables here bit flag = 0; void set(){ // функция смены значения на выходе flag = !flag; PORTD.4 = flag; } void main(void) { // Declare your local variables here // Input/Output Ports initialization // Port B initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In   // State7=T State6=T State5=T State4=T State3=T State2=T State1=P State0=T   PORTB=0x02; DDRB=0x00; // Port C initialization // Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In   // State6=T State5=T State4=T State3=T State2=P State1=T State0=T   PORTC=0x04; DDRC=0x00; // Port D initialization // Func7=In Func6=In Func5=In Func4=Out Func3=In Func2=In Func1=In Func0=In   // State7=T State6=T State5=T State4=0 State3=T State2=T State1=T State0=T   PORTD=0x00; DDRD=0x10; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: Timer 0 Stopped TCCR0=0x00; TCNT0=0x00; // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: Timer 1 Stopped // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge // Timer 1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=0x00; TCCR1B=0x00; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; // Timer/Counter 2 initialization // Clock source: System Clock // Clock value: Timer 2 Stopped // Mode: Normal top=FFh // OC2 output: Disconnected ASSR=0x00; TCCR2=0x00; TCNT2=0x00; OCR2=0x00; // External Interrupt(s) initialization // INT0: Off // INT1: Off MCUCR=0x00;     // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x00; // Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80; SFIOR=0x00; while (1)   {     if (PINC.2==0) { // ждем нажатия   delay_ms(50); // антидребезг   if (PINC.2==0) set(); // если все норм, переключаем     else continue;   }   else continue;       while(PINC.2==0) {}; // ждем отпускания кнопки   delay_ms(50); // антидребезг     }; }    В начале в генераторе кода надо сконфигурировать линии портов. На скриншоте указано, что на линию входа необходимо подключить внутренний нагрузочный резистор (поставить Р вместо Т). Об этом резисторе написано выше. Там, где говорилось о вариантах подключения кнопки к контроллеру.

//_________________________________Удачи!

Источник: http://по материалам книги А.В. Белова “Создаем устройства на микроконтроллерах”

Уважаемый Пётр использовал библиотеку программного обеспечения USB господина Ollopa. Господин Ollopa был так добр, что опубликовал версию LBX своей библиотеки.

Хотя библиотека и работает, она не протестирована на все 100% и пока не поддерживается. Со временем появится коммерческая версия (LIB), которая будет поддерживаться.

Эта библиотека программного обеспечения USB и образцы кода, можно использовать в USB устройствах для большинства AVR чипов –

Спасибо Петр, за этот замечательный материал!

Программная реализация USB в AVR.

USB драйвер (файл swusb.LBX ) нужно скопировать в папку LIB программы BASCOM-AVR. Пример HID джойстика был переделан в демонстрационное устройство и USB термометр.

Demo – device.

Демонстрационное устройство, позволяет производить двухсторонний обмен произвольной информацией с компьютером. Его схема показана на рисунке.

Программа имеет довольно большой размер (почти 1000 строк), поэтому будут рассмотрены лишь фрагменты, отвечающие за конфигурацию USB драйвера и обмен информацией.

В оригинальной программе был заменён HID дескриптор устройства, типа джойстик, на HID дескриптор нестандартного устройства, позволяющий производить обмен произвольной информацией. Также была активирована вторая конечная точка и настроена на приём информации от компьютера.

Именно HID дескриптор определяет тип устройства. От него зависит, будет ли устройство, клавиатурой, мышкой, джойстиком и т. д. В рассматриваемом демонстрационном устройстве, HID дескриптор имеет вид:

Data 33 ' Length = 33 bytes
Data &H06 , &H00 , &HFF ' Usage_page(vendor Defined Page 1)
Data &H09 , &H01 ' Usage(vendor Usage 1)
Data &HA1 , &H02 ' Collection(logical)

Data &H09 , &H01 ' Usage(pointer)

Data &H15 , &H00 ' Logical_minimum(0)
Data &H25 , &HFF ' Logical_maximum(255)
Data &H75 , &H08 ' Report_size(8)
Data &H95 , &H01 ' Report_count(1)
Data &H81 , &H02 ' Input(data , Var , Abs)

Data &H09 , &H01 ' Usage(pointer)

Data &H15 , &H00 ' Logical_minimum(0)
Data &H26 , &HFF , 0 ' Logical_maximum(255)
Data &H75 , &H08 ' Report_size(8)
Data &H95 , &H01 ' Report_count(1)
Data &H91 , &H02 ' Output(data , Var , Abs)

Data &HC0 ' End_collection

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

Параметры Logical_minimum и Logical_maximum определяют допустимый интервал значений, хранящийся в буфере конечной точки. Параметр Report_count определяет число байт, передаваемых или принимаемых за одну посылку. Допустимое значение 1…8.

В демонстрационном устройстве, передаётся и принимается, только по один байт за посылку.

Конфигурация конечных точек производится с помощью этого кода.

' Address of optional endpoints (Must be > 0.

comment-out to not use)
Const _usb_endp2addr = 1
Const _usb_endp3addr = 2
' Valid types are 0 for control or 3 for interrupt
Const _usb_endp2type = 3
Const _usb_endp3type = 3
' Directions are: 0=Out, 1=In.

Ignored by control endpoints
Const _usb_endp2direction = 1
Const _usb_endp3direction = 0
' Polling interval (ms) for interrupt endpoints. Ignored by control endpoints
' (Must be at least 10)
Const _usb_endp2interval = 200
Const _usb_endp3interval = 100

Уникальные идентификаторы устройства – Vendor ID and Product ID, задают в строках:

Const _usb_vid = &HAAAA
Const _usb_pid = &HEF22

Приём и передача данных, выполняются в главном цикле программы.

Do
     Resetcounter = 0
     ' Check for reset here
     While _usb_pin._usb_dminus = 0
          Incr Resetcounter
          If Resetcounter = 1000 Then
               Call Usb_reset()
          End If
     Wend

     ' Check for received data

     If _usb_status._usb_rxc = 1 Then
          If _usb_status._usb_setup = 1 Then
               ' Process a setup packet/Control message
               Call Usb_processsetup(_usb_tx_status)
          Elseif _usb_status._usb_endp1 = 1 Then
               ' Input data endpoints
               Portb = _usb_rx_buffer(2) ' Copy USB data in Portb
          End If

          ' Reset the RXC bit and set the RTR bit (ready to receive a new packet)
          _usb_status._usb_rtr = 1
          _usb_status._usb_rxc = 0
     End If

     Buttons_current = Pinc
     Buttons_current = Buttons_current And 3
     If Buttons_current Buttons_last Then 
     ' Queue data to be sent on endpoint 2 (HID report)
          If _usb_tx_status2.

_usb_txc = 1 Then
               Buttons_last = Buttons_current
               _usb_tx_buffer2(2) = Buttons_current
              Call Usb_send(_usb_tx_status2 , 1) ' Send data in PC
          End If
     End If
Loop

End При поступлении новых данных от компьютера, будет установлен флаг _usb_endp1 в переменной _usb_status. Поступившие данные хранятся в массиве _usb_rx_buffer.

В демонстрационной программе, за одну посылку, принимается только один байт данных, что описано в HID репорте. Этот байт копируется в Portb микроконтроллера. Для передачи данных из микроконтроллера в компьютер, данные записываются в массив _usb_tx_buffer2.

После этого вызывается функция Usb_send. Её второй аргумент – число передаваемых байт. Но перед этим, проверяется готовность USB драйвера к передаче данных, путём проверки флага _usb_txc, переменной _usb_tx_status2.

Для работы с демонстрационным устройством, была разработана компьютерная программа HID_Example_IO.exe

USB thermometer.

USB термометр создан на основе кода демонстрационного устройства. Основные изменения были внесены в главный цикл программы.

Config 1wire = Portc.5

Dim 1wire_array(9) As Byte
Dim W_1wire As Word
Dim Dsid1(8) As Byte
Dim Flaginputtermo As Byte

Dim Resetcounter As Word

Dim Idlemode As Byte

Enable Interrupts

W_1wire = 1wirecount()

Dsid1(1) = 1wsearchfirst()
1wreset ' reset the bus
1wwrite &HCC' skip rom
1wwrite &H44 ' Convert T
Timer1= 0
Flaginputtermo = 0

Do

     Resetcounter = 0

     'Check for reset here

     While _usb_pin._usb_dminus= 0
          Incr Resetcounter
          If Resetcounter = 1000 Then
               Call Usb_reset()
          End If
     Wend

     'Check for received data

     If _usb_status._usb_rxc = 1 Then
          If _usb_status._usb_setup = 1 Then
               'Process a setup packet/Control message
               Call Usb_processsetup(_usb_tx_status)
          Elseif _usb_status._usb_endp1 = 1 Then
               ' Input data endpoints
          End If
          'Reset the RXC bit and set the RTR bit (ready to receive a new packet)
         _usb_status._usb_rtr = 1
         _usb_status._usb_rxc = 0
     End If

     If Flaginputtermo = 1 Then

               Flaginputtermo = 0 
               1wverify Dsid1(1)
               1wwrite &HBE
               1wire_array(1) = 1wread(9)
               1wreset ' reset the bus
               1wwrite &HCC ' skip rom
               1wwrite &H44 ' Convert T
          'Queue data to be sent on endpoint 2 (HID report)
          If _usb_tx_status2._usb_txc = 1 Then
               _usb_tx_buffer2(2) = 1wire_array(1)
               _usb_tx_buffer2(3) = 1wire_Array(2)
              Call Usb_send(_usb_tx_status2 , 2) ' Send data (2 bytes) in PC

Из главного цикла удалён код, принимающий данные от компьютера и добавлен код, опроса датчика DS18B20. Данные из датчика нужно считывать не чаще одного раза за 750 миллисекунд.

Чтобы не задерживать работу главного цикла на такой относительно большой промежуток времени, была использована переменная Flaginputtermo как флаг.

В прерывании от таймера Timer1, происходящем примерно один раз в секунду, в переменную записывается число 1, что служит признаком необходимости чтения данных из датчика.

По окончанию чтения, данные копируются из массива 1wire_array в массив _usb_tx_buffer2 и вызывается функция Usb_send, передающая данные (2 байта) через шину USB в компьютер. В HID репорт было внесено небольшое изменение (выделено зелёным цветом), связанное с необходимостью передачи 2 байт за посылку.

Data 33 ' Length = 33 bytes
Data &H06 , &H00 , &HFF ' Usage_page(vendor Defined Page 1)
Data &H09 , &H01 ' Usage(vendor Usage 1)
Data &HA1 , &H02 ' Collection(logical)

Data &H09 , &H01 ' Usage(pointer)

Data &H15 , &H00 ' Logical_minimum(0)
Data &H25 , &HFF ' Logical_maximum(255)
Data &H75 , &H08 ' Report_size(8)
Data &H95 , &H02 ' Report_count(2)
Data &H81 , &H02 ' Input(data , Var , Abs)

Data &H09 , &H01 ' Usage(pointer)

Data &H15 , &H00 ' Logical_minimum(0)
Data &H26 , &HFF , 0 ' Logical_maximum(255)
Data &H75 , &H08 ' Report_size(8)
Data &H95 , &H01 ' Report_count(1)
Data &H91 , &H02 ' Output(data , Var , Abs)

Data &HC0 ' End_collection

Для отображения температуры на экране компьютера, была разработана программа USB_thermometer.exe

Для их компиляции, нужен PureBasic, версии 4.40 или 4.41.

Или с зеркал http://purebasic.ucoz.ru/PureBasic_4.41_Demo.exehttp://purebasic.programist.ru/PureBasic_4.41_Demo.exe

Для безошибочной компиляции, нужно установить библиотеку HID_Lib (файл “HID_Lib for PureBasic 4.41.exe” в архиве).

Софт со стороны ПК на VB6, VBNET, C#.

Подборка статей по виртуальному USB Oloppa:

  • USB барометр
  • USB термометр на ATmega8 и PIC18F4550
  • USB часы
  • USB джойстик на ATmega8
  • Простое USB HID устройство на ATmega8
  • СТРЕЛОЧНЫЙ ИНДИКАТОР ЗАГРУЗКИ ЦП И ОПЕРАТИВНОЙ ПАМЯТИ ПК
  • ОРГАНИЗУЕМ ПРОГРАММНЫЙ USB В BASCOM-AVR НА ПРИМЕРЕ USB-ВОЛЬТМЕТРА. ЧАСТЬ 1-3
  • AVR-Software-USB mit Bascom     

Удачного вам ЮСБ-ирования!!!