Оглавление:
- Шаг 1: очистите клавиатуру 1
- Шаг 2: очистите клавиатуру 2
- Шаг 3: очистите клавиатуру 3
- Шаг 4: Подключите клавиатуру
- Шаг 5: Подключите клавиатуру к анализатору
- Шаг 6: Какие тумблеры мы должны установить?
- Шаг 7: напишите обработчик прерывания
- Шаг 8: Составьте карту значений нажатия клавиш
- Шаг 9: Код и видео для версии 1
- Шаг 10: Код для версии 2
- Шаг 11: Как избавиться от кнопки? Версия 3
- Шаг 12: Код и видео для рабочей версии
Видео: Учебник по ассемблеру AVR 7:12 шагов
2024 Автор: John Day | [email protected]. Последнее изменение: 2024-01-30 11:47
Добро пожаловать в Урок 7!
Сегодня мы собираемся сначала показать, как очистить клавиатуру, а затем показать, как использовать порты аналогового ввода для связи с клавиатурой. Мы сделаем это, используя прерывания и один провод в качестве ввода. Мы подключим клавиатуру так, чтобы каждое нажатие клавиши посылало на аналоговый вход уникальное напряжение, что позволит нам различать по напряжению, какая клавиша была нажата. Затем мы выведем число, нажатое на наш анализатор регистров, чтобы показать, что все происходит так, как должно. Существует ряд подводных камней, с которыми вы можете столкнуться при использовании аналого-цифрового преобразователя (АЦП) в ATmega328p, и поэтому мы разбейте все на несколько этапов, чтобы попытаться понять, как их избежать. Мы также увидим, почему использование аналого-цифрового преобразователя - не лучший способ управления клавиатурой, даже если он использует меньше портов на вашем микроконтроллере. В этом руководстве вам понадобятся:
- клавиатура. Вы можете купить один или сделать то же, что и я, и собрать его.
- 2 женских разъема для клавиатуры (если вы убираете одну)
- соединительные провода
- макет
- 4 резистора 1 кОм
- 1 резистор 15 кОм
- 1 резистор 3,3 кОм
- 1 резистор 180 Ом
- Резистор 1680 Ом
- цифровой мультиметр
- ваш анализатор из Урок 5
Вы можете пропустить первые несколько шагов, если у вас уже есть клавиатура и вам не нужно ее очищать.
Вот ссылка на полную коллекцию моих руководств по ассемблеру AVR:
Шаг 1: очистите клавиатуру 1
Давным-давно, когда даже ваши бабушка и дедушка были еще детьми, люди использовали эти странно выглядящие устройства, которые имели длинные кабели, подключенные к стене, для связи друг с другом. Их называли «телефонами» и обычно представляли собой дешевые пластиковые штуки, которые издавали раздражающий звук, когда кто-то звонил вам (не то чтобы сегодняшние рингтоны «Джастин Бибер» не так раздражали). В любом случае, на этих устройствах были клавиатуры, которые были очень просто подключены, и поэтому их легко было очистить, и на них есть 2 дополнительные клавиши («повторный набор» и «мигание») от клавиатур, которые вы можете купить, которые вы, возможно, захотите перепрофилировать. как «клавиши со стрелками», «клавиши меню» или что-то еще. Итак, мы собираемся начать с очистки клавиатуры от старого телефона. Сначала возьмите телефон (я использую телефон GE, как показано на рисунках) и подденьте его, чтобы открыть проводку. Затем возьмите стамеску, отломите маленькие пластиковые ручки, которые удерживают клавиатуру, и снимите клавиатуру.
Шаг 2: очистите клавиатуру 2
Теперь возьмите пилу для ПВХ и вырежьте пластик вокруг замочных отверстий, а затем обрежьте края, чтобы получить нужную глубину, оставив тонкую клавиатуру.
Затем снова установите клавиатуру, используя маленькие штифты, которые остались после того, как вы отрезали от них верхнюю часть на последнем шаге, и используйте паяльник, чтобы просто воткнуть горячий утюг в каждое отверстие для штифта, которое расплавит пластик и распределит его по поверхности. нижняя часть клавиатуры образует новые «ручки», которые, как и раньше, будут удерживать клавиатуру на месте.
Мне нравится убирать три динамика и, возможно, другие вещи, такие как переключатели и тому подобное, что есть на плате. Однако на этот раз я не собираюсь убирать переключатели и прочее, потому что на данный момент у нас другие цели. Также там есть линейная микросхема TA31002, которая является телефонным звонком. Техническое описание легко найти и загрузить в Интернете с указанием распиновки и функций. Так что я пока оставлю его припаянным к плате, а потом поиграю с ним. Я хотел бы подключить его к осциллографу и посмотреть, какие крутые сигналы я могу получить от него. Может, даже сделать из него дверной звонок. Кто знает.
В любом случае, как только вы закончите уничтожать телефон и собирать детали, мы закончим создание нашей клавиатуры.
Шаг 3: очистите клавиатуру 3
Используйте приспособление для удаления припоя и снимите ленточные кабели с нижней части клавиатуры, убедившись, что отверстия в печатной плате чистые, а затем прикрепите два гнездовых разъема к плате там, где есть отверстия. Вам, вероятно, придется обрезать свои заголовки, чтобы они были 4-контактными.
Теперь, когда разъемы подключены, вы можете подключить его к макетной плате, взять мультиметр и проверить ключи, вставив мультиметр в случайные контакты и измерив сопротивление. Это позволит вам обозначить ключи. Трудно увидеть, как клавиши подключены к выходам, глядя на схему, но если вы используете мультиметр, вы можете подключить его к любым двум контактам, а затем нажимать кнопки, пока не увидите цифру на экране вместо разомкнутой цепи.. Это будет распиновка для этого ключа.
Таким образом сопоставьте все ключи с выводами.
Шаг 4: Подключите клавиатуру
Теперь, следуя схеме подключения, подключите клавиатуру к макетной плате.
Как это будет работать, мы подадим 5 В на левую сторону, а правая - на GND. Первый вывод справа на схеме входит в первый из наших аналоговых выводов на микроконтроллере Atmega328p. Когда не нажимаются никакие кнопки, сигнал будет 0 В, а когда каждая из различных кнопок нажата, вход аналогового порта будет находиться в диапазоне от 0 В до 5 В с разной величиной в зависимости от того, какая клавиша была нажата. Мы выбрали номиналы резисторов так, чтобы каждый путь содержал сопротивление, отличное от остальных. Аналоговый порт микроконтроллера принимает аналоговый сигнал и разделяет его на 1024 различных канала от 0 до 5 В. Это означает, что каждый канал имеет ширину 5 В / 1024 = 0,005 В / канал = 5 мВ / канал. Таким образом, аналоговый порт может различать входные напряжения, если они отличаются более чем на 5 мВ. В нашем случае мы выбрали значения резисторов, так что любые два нажатия клавиш будут посылать сигнал напряжения, который отличается больше, чем это, поэтому микроконтроллер должен легко решить, какая клавиша была нажата. Большая проблема заключается в том, что вся система очень шумная, поэтому нам нужно будет выбрать диапазон напряжений для сопоставления с каждым нажатием кнопки - но мы вернемся к этому чуть позже.
Обратите внимание, что мы можем управлять 14-кнопочной клавиатурой, используя только одну линию ввода для контроллера. Это один из полезных аспектов аналоговых входов.
Теперь наша первая попытка управления клавиатурой будет заключаться в том, чтобы нажатие клавиши приводило к прерыванию, подпрограмма прерывания считывает аналоговый входной порт и решает, какая клавиша была нажата, а затем выводит это число в нашу подпрограмму анализатора регистров, которая будет отображать ключевое значение в двоичном формате на наших 8 светодиодах, которые мы установили в Уроке 5.
Шаг 5: Подключите клавиатуру к анализатору
На рисунках показано, как мы хотим подключить клавиатуру к микроконтроллеру, чтобы мы могли видеть результат на дисплее нашего анализатора. По сути, мы просто подключаем выход клавиатуры к контакту 0 PortC, который также называется ADC0 на ATmega328P.
Однако есть еще пара вещей. Мы также собираемся подключить кнопку к PD2. Т.е. возьмите провод от вашей шины 5V к кнопке и с другой стороны кнопки к PD2, и, наконец, мы хотим отключить контакт AREF от нашей шины 5V и вместо этого оставить его отключенным. При желании мы могли бы вставить развязывающий конденсатор 0,1 мкФ. Это керамический конденсатор с надписью 104. Первые две цифры - это число, а последняя цифра - это степень 10, на которую мы умножаем ее, чтобы получить ответ в пикофарадах (пико означает 10 ^ -12). Итак, 104 означает 10 x 10 ^ 4 пикофарад, что совпадает с 100 нанофарад (нано означает 10 ^ -9), что равно 0,1 мкФ (микро означает 10 ^ -6). В любом случае, все это стабилизирует вывод AREF, когда мы можем использовать его в качестве опорного вывода.
Нам также нужен резистор 1 МОм между PD2 и землей. Мы собираемся установить PD2 в качестве выходного контакта на 0 В, и мы будем запускать по положительному фронту на этом контакте. Мы хотим, чтобы край исчез сразу, когда мы отпускаем кнопку, поэтому мы вставим этот «понижающий» резистор.
Причина, по которой нам нужна кнопка, заключается в том, что мы хотим, чтобы наш аналого-цифровой преобразователь отключил вывод INT0 на микросхеме, который также является PD2. В конце концов, мы хотели бы, чтобы нажатие клавиши запускало АЦП, а также обеспечивало преобразование входных данных без отдельной кнопки, но из-за того, как работает синхронизация, мы начнем с отдельной кнопки для запуска АЦП, и как только мы прогладим все устранены ошибки и уверены, что все работает правильно, тогда мы будем решать проблемы с шумом и синхронизацией, которые возникают при срабатывании от того же нажатия кнопки, которое мы хотим прочитать.
Итак, на данный момент это работает следующим образом: мы удерживаем клавишу, затем нажимаем кнопку, чтобы запустить АЦП, а затем отпускать, и, надеюсь, двоичное значение нажатой кнопки отобразится на анализаторе.
Итак, давайте напишем код, который выполнит это.
Шаг 6: Какие тумблеры мы должны установить?
Давайте сначала подумаем о том, как мы собираемся закодировать это, чтобы контроллер мог считывать ввод с клавиатуры и преобразовывать его в числовое значение, соответствующее нажатой кнопке. Мы собираемся использовать аналого-цифровой преобразователь (АЦП). который встроен в Atmega328p. Мы будем использовать AREF в качестве опорного напряжения, а выход нашей клавиатуры будет подключен к PortC0 или PC0. Обратите внимание, что этот вывод также называется ADC0 для аналого-цифрового преобразователя 0. Возможно, вам стоит прочитать раздел 12.4 о прерываниях для ATmega328P, а также главу 24 об аналого-цифровом преобразователе, прежде чем мы получим Чтобы настроить микроконтроллер так, чтобы он знал, что делать с аналоговым входным сигналом и как взаимодействовать с нашей программой, мы сначала должны настроить несколько различных АЦП. связанные биты регистра. По сути, они эквивалентны старым тумблерам на первых компьютерах. Вы либо включаете или выключаете переключатель, либо еще дальше вставляете кабели между одной розеткой и другой, так что электроны, достигающие этой развилки дороги, обнаруживают, что одни ворота закрыты, а другие открыты, заставляя их двигаться по другому пути в лабиринте схемотехника и, таким образом, выполняет другую логическую задачу. При кодировании на языке ассемблера у нас есть близкий доступ к этим функциям микроконтроллера, что в первую очередь является одним из привлекательных моментов в этом. Это больше похоже на «руки» и гораздо меньше «за кулисами». Так что не думайте о настройке этих регистров как о утомительной задаче. Вот что делает язык ассемблера интересным! Мы устанавливаем очень личное отношение к внутренней работе и логике чипа и заставляем его делать именно то, что мы хотим - ни больше, ни меньше. Никаких потерь тактовых циклов. Итак, вот список переключателей, которые нам нужно установить:
- Отключите бит АЦП снижения мощности, PRADC, который является битом 0 регистра PRR, поскольку, если этот бит установлен, он отключит АЦП. Регистр снижения мощности - это, по сути, способ отключить различные устройства, которые потребляют энергию, когда они вам не нужны. Поскольку мы используем АЦП, мы хотим убедиться, что он не отключен таким образом. (См. PRADC на странице 46)
- Выберите аналоговый входной канал как ADC0, отключив MUX3… 0 в регистре выбора мультиплексора АЦП (ADMUX) (см. Таблицу 24-4 на стр. 249), они уже отключены по умолчанию, поэтому нам действительно не нужно этого делать. Тем не менее, я включаю его, поскольку, если вы когда-нибудь будете использовать порт, отличный от ADC0, вам нужно будет соответствующим образом переключить эти переключатели. Различные комбинации MUX3, MUX2, MUX1, MUX0 позволяют вам использовать любой из аналоговых портов в качестве входа, и вы также можете изменить их на лету, если хотите просмотреть сразу несколько разных аналоговых сигналов.
- Отключите биты REFS0 и REFS1 в регистре ADMUX, чтобы мы использовали AREF в качестве опорного напряжения, а не внутреннего опорного напряжения (см. Стр. 248).
- Включите бит ADLAR в ADMUX, чтобы результат был «отрегулирован влево», мы обсудим этот выбор на следующем шаге.
- Установите бит ADC0D в регистре отключения цифрового входа (DIDR0), чтобы отключить цифровой вход на PC0. Мы используем этот порт для аналогового входа, поэтому мы можем также отключить для него цифровой вход.
- Установите ISC0 и ISC1 в регистре управления внешним прерыванием A (EICRA), чтобы указать, что мы хотим запускать по нарастающему фронту сигнала напряжения на выводе INT0 (PD2), см. Стр. 71.
- Очистите биты INT0 и INT1 в регистре маски внешнего прерывания (EIMSK), чтобы указать, что мы не используем прерывания на этом выводе. Если бы мы разрешили прерывания на этом выводе, нам бы потребовался обработчик прерывания по адресу 0x0002, но вместо этого мы настраиваем его так, чтобы сигнал на этом выводе запускал преобразование АЦП, завершение которого обрабатывается прерыванием завершения преобразования АЦП на адрес 0x002A. См. Страницу 72.
- Установите бит включения АЦП (ADEN) (бит 7) в регистре управления и состояния АЦП A (ADCSRA), чтобы включить АЦП. См. Страницу 249.
- Мы могли бы начать единичное преобразование, устанавливая бит начала преобразования АЦП (ADSC) каждый раз, когда мы хотим прочитать аналоговый сигнал, однако сейчас мы бы предпочли, чтобы он считывался автоматически всякий раз, когда кто-то нажимает кнопку, поэтому вместо этого мы включим АЦП. Бит включения автоматического запуска (ADATE) в регистре ADCSRA, поэтому запуск выполняется автоматически.
- Мы также устанавливаем биты ADPS2..0 (биты AD Prescalar) на 111, так что тактовая частота АЦП равна тактовой частоте процессора, разделенной на коэффициент 128.
- В качестве источника срабатывания АЦП выберем PD2, который также называется INT0 (External Interrupt Request 0). Мы делаем это путем переключения различных битов в регистре ADCSRB (см. Таблицу 24-6 на странице 251). По таблице мы видим, что нам нужно выключить ADTS0, включить ADTS1 и выключить ADTS2, чтобы АЦП запускал этот вывод. Обратите внимание: если бы мы хотели непрерывно выполнять выборку аналогового порта, например, если бы мы читали некоторый непрерывный аналоговый сигнал (например, выборка звука или что-то в этом роде), мы бы установили для него режим Free Running. Используемый нами метод настройки запуска на PD2 запускает чтение АЦП аналогового порта PC0, не вызывая прерывания. Прерывание произойдет, когда преобразование будет завершено.
- Включите бит разрешения прерывания от АЦП (ADIE) в регистре ADCSRA, чтобы по завершении аналого-цифрового преобразования он генерировал прерывание, для которого мы могли бы написать обработчик прерывания и поместить его в.org 0x002A.
- Установите бит I в SREG, чтобы разрешить прерывания.
Упражнение 1. Убедитесь, что вы прочитали соответствующие разделы таблицы для каждой из вышеперечисленных настроек, чтобы вы понимали, что происходит и что произойдет, если мы изменим их на альтернативные настройки.
Шаг 7: напишите обработчик прерывания
На последнем этапе мы увидели, что настроили его так, что нарастающий фронт, обнаруженный на PD2, будет запускать аналого-цифровое преобразование на PC0, и когда это преобразование будет завершено, оно вызовет прерывание завершения преобразования АЦП. Теперь мы хотим что-то сделать с этим прерыванием. Если вы изучите Таблицу 12-6 на странице 65, вы увидите список возможных прерываний. Мы уже видели прерывание RESET по адресу 0x0000 и прерывание Timer / Counter0 Overflow по адресу 0x0020 в предыдущих руководствах. Теперь мы хотим взглянуть на прерывание АЦП, которое мы видим в таблице по адресу 0x002A. Итак, в начале нашего кода на языке ассемблера нам понадобится строка, которая гласит:
.org 0x002Arjmp ADC_int
который перейдет к нашему обработчику прерывания, помеченному ADC_int, всякий раз, когда АЦП завершит преобразование. Итак, как нам написать обработчик прерывания? АЦП работает следующим образом:
АЦП = Vin x 1024 / Vref
Итак, давайте посмотрим, что произойдет, если я нажму кнопку «повторный набор» на клавиатуре. В этом случае напряжение на PC0 изменится до некоторого значения, скажем, 1,52 В, и поскольку Vref составляет 5 В, мы будем иметь:
АЦП = (1,52 В) x 1024/5 В = 311,296
и поэтому он будет отображаться как 311. Если бы мы хотели преобразовать это обратно в напряжение, мы бы просто отменили вычисление. Однако нам не нужно этого делать, поскольку нас не интересуют фактические напряжения, просто чтобы различать их. Когда преобразование завершено, результат сохраняется в 10-битном числе, помещенном в регистры ADCH и ADCL, и мы заставили его "отрегулировать влево", что означает, что 10-битное число начинается с 7-го бита ADCH и опускается до бит 6 ADCL (всего в этих двух регистрах 16 бит, и мы используем только 10 из них, то есть 1024 канала). Мы могли бы получить результат «с корректировкой вправо», если бы захотели, очистив бит ADLAR в регистре ADMUX. Причина, по которой мы выбираем корректировку влево, заключается в том, что наши сигналы достаточно далеко друг от друга, поэтому последние две цифры номера канала не имеют значения и Вероятно, это просто шум, поэтому мы будем различать нажатия клавиш, используя только старшие 8 цифр, другими словами, нам нужно будет только посмотреть на ADCH, чтобы выяснить, какая кнопка была нажата. Таким образом, наш обработчик прерывания должен просто прочитать номер из ADCH register, преобразуйте это число в значение клавиатуры, а затем отправьте это значение на светодиоды нашего анализатора регистров, чтобы мы могли убедиться, что нажатие, скажем, «9» вызовет загорание светодиода, соответствующего «00001001». Однако нам нужно сначала увидеть, что появляется в ADCH, когда мы нажимаем различные кнопки. Итак, давайте просто напишем простой обработчик прерывания, который просто отправляет содержимое ADCH на дисплей анализатора. Итак, вот что нам нужно:
ADC_int: lds analyzer, ADCH; загрузить значение ADCH в наши анализаторы bi EIFR, 0; сбросить флаг внешнего прерывания, чтобы он был готов к работе снова.
К настоящему моменту вы должны быть в состоянии просто скопировать код из нашего анализатора из учебника 5, добавить это прерывание и параметры переключения и запустить его. Упражнение 2: напишите код и запустите его. Убедитесь, что на дисплее анализатора отображается ADCH. Попробуйте нажать одну и ту же клавишу несколько раз. Всегда ли вы получаете одно и то же значение в ADCH?
Шаг 8: Составьте карту значений нажатия клавиш
Теперь нам нужно преобразовать значения в ADCH в числа, соответствующие нажатой клавише. Мы делаем это, записывая содержимое ADCH для каждого нажатия клавиши, а затем конвертируя его в десятичное число, как я сделал на картинке. В нашей подпрограмме обработки прерывания мы будем рассматривать целый диапазон значений как соответствующий каждому нажатию клавиши, так что ADC будет отображать что-либо в этом диапазоне на данное нажатие клавиши.
Упражнение 3. Выполните это сопоставление, а затем перепишите процедуру обработки прерывания АЦП.
Вот что я получил для своего (ваш, скорее всего, будет другим). Обратите внимание, что я установил диапазон значений для каждого нажатия клавиши.
ADC_int:; Внешний обработчик прерыванийclr анализатор; подготовить новые номера buttonH, ADCH; АЦП обновляется при чтении ADCH clccpi buttonH, 240brlo PC + 3; если ADCH больше, то это анализатор 1ldi, 1; итак загрузите анализатор с возвратом 1rjmp; и кнопка возврата clccpi H, 230; если ADCH больше, то 2brlo PC + 3ldi analyzer, 2rjmp return clccpi buttonH, 217brlo PC + 3ldi analyzer, 3rjmp return clccpi buttonH, 203brlo PC + 3ldi analyzer, 4rjmp return clccpi buttonH, 187brlo PC + 3ldi analyzer, 5rjmp return clccpi button, 5rjmp return clccpi button 155brlo ПК + анализатор 3ldi, 6rjmp return clccpi buttonH, 127brlo ПК + анализатор 3ldi, 255; мы установим flash как все onrjmp return clccpi buttonH, 115brlo PC + 3ldi analyzer, 7rjmp return clccpi buttonH, 94brlo PC + 3ldi analyzer, 8rjmp return clccpi buttonH, 62brlo PC + 3ldi analyzer, 9rjmp return clccpi buttonH, 37brlo PC + 3ldi analyzer, 0b11110000; звездочка - это верхняя половина кнопки возврата rjmp clccpiH, 28brlo PC + анализатор 3ldi, 0rjmp return clccpi buttonH, 17brlo PC + анализатор 3ldi, 0b00001111; знак решетки - нижняя половина на rjmp return clccpi buttonH, 5brlo PC + 3ldi analyzer, 0b11000011; redial is top 2 bottom 2rjmp return ldi analyzer, 0b11011011; в противном случае произошла ошибка return: reti
Шаг 9: Код и видео для версии 1
Я приложил свой код для этой первой версии драйвера клавиатуры. В этом вам нужно нажать кнопку, а затем кнопку, чтобы АЦП считал ввод с клавиатуры. Мы бы предпочли не иметь кнопки, а вместо этого сигнал на преобразование исходит от самого нажатия клавиши. Упражнение 3: Соберите, загрузите этот код и попробуйте его. Возможно, вам придется изменить различные пороги преобразования, чтобы они соответствовали вашим напряжениям нажатия клавиш, поскольку они, вероятно, отличаются от моих. Что произойдет, если вы попытаетесь использовать ввод с клавиатуры как для ADC0, так и для внешнего вывода прерывания вместо кнопки? Я также приложу видео о работе этой первой версии нашего драйвера нажатия клавиш. Вы заметите, что это в моем коде есть раздел, инициализирующий указатель стека. Существуют различные регистры, которые мы можем захотеть вытолкнуть и вытащить из стека, когда мы манипулируем переменными и чем-то еще, а также есть регистры, которые мы, возможно, захотим сохранить и восстановить позже. Например, SREG - это регистр, который не сохраняется при прерываниях, поэтому различные флаги, которые устанавливаются и сбрасываются в результате операций, могут быть изменены, если прерывание происходит в середине чего-либо. Поэтому лучше всего, если вы поместите SREG в стек в начале обработчика прерывания, а затем снова вытащите его в конце обработчика прерывания. Я поместил его в код, чтобы показать, как он инициализируется, и предвидеть, как он нам понадобится позже, но, поскольку нам все равно, что происходит с SREG во время прерываний в нашем коде, я не использовал для этого стек. что я использовал операцию сдвига для установки различных битов в регистрах при инициализации. Например в строке:
ldi темп, (1 <
Команда «<<» в первой строке кода выше - это операция сдвига. По сути, он берет двоичное число 1, равное 0b00000001, и сдвигает его влево на величину ISC01. Это позиция бита ISC01 в регистре EICRA. Поскольку ISC01 - это бит 1, число 1 сдвигается влево на 1 позицию и становится 0b00000010. Точно так же второй, ISC00, является битом 0 EICRA, поэтому сдвиг числа 1 - это нулевые позиции влево. Если вы посмотрите еще раз на файл m328Pdef.inc, который вы загрузили в первом руководстве и с тех пор используете evrr, вы увидите, что это просто длинный список операторов «.equ». Вы обнаружите, что ISC01 равно 1. Ассемблер заменяет каждый его экземпляр на 1, прежде чем даже начать что-либо собирать. Это просто имена битов регистров, которые помогают нам, людям, читать и писать код. Теперь вертикальная линия между двумя операциями сдвига, описанными выше, является логической операцией «или». Вот уравнение:
0b00000010 | 0b00000001 = 0b00000011
и это то, что мы загружаем (используя "ldi") в temp. Причина, по которой люди используют этот метод для загрузки значений в регистр, заключается в том, что он позволяет использовать имя бита, а не просто число, и это значительно упрощает чтение кода. Мы также использовали два других метода. Мы используем инструкции «ори» и «анди». Это позволяет нам устанавливать и очищать биты соответственно без изменения каких-либо других битов в регистре. Например, когда я использовал
ori temp, (1
this "or" s temp с 0b00000001, который помещает 1 в нулевой бит и оставляет все остальное без изменений. Также, когда мы написали
Энди темп, 0b11111110
это изменяет нулевой бит температуры на 0 и оставляет все остальное без изменений.
Упражнение 4: Вы должны просмотреть код и убедиться, что понимаете каждую строку. Возможно, вам будет интересно найти более эффективные методы работы и написать лучшую программу. Есть сотня способов кодировать вещи, и я почти уверен, что вы найдете гораздо лучший способ, чем мой. Вы также можете найти (не дай бог!) Ошибки и упущения. В таком случае я бы хотел услышать о них, чтобы их можно было исправить.
Хорошо, теперь давайте посмотрим, сможем ли мы избавиться от этой лишней кнопки…
Шаг 10: Код для версии 2
Самый простой способ избавиться от кнопки - просто удалить ее полностью, забыть о входе PB2 и просто переключить АЦП в «Free Running Mode».
Другими словами, просто измените регистр ADCSRB так, чтобы все ADTS2, ADTS1 и ADTS0 были нулевыми.
Затем установите бит ADSC в ADCSRA в 1, что запустит первое преобразование.
Теперь загрузите его в свой микроконтроллер, и вы обнаружите, что правильный номер появляется на дисплее, когда вы нажимаете кнопку, и только когда вы нажимаете кнопку. Это связано с тем, что АЦП непрерывно выполняет выборку порта ADC0 и отображает значение. Когда вы убираете палец с кнопки, «дребезг кнопки» вызывает очень быстрое появление нескольких случайных значений, а затем возвращается к входному 0 В. В нашем коде это 0V отображается как 0b11011011 (поскольку нажатие клавиши `0 'уже использует отображаемое значение 0b00000000)
Это не то решение, которое нам нужно по двум причинам. Во-первых, нам не нужно удерживать кнопку. Мы хотим нажать ее один раз, и число будет отображаться (или использоваться в каком-либо новом коде в более позднем руководстве). Во-вторых, мы не хотим постоянно проверять ADC0. Мы хотим, чтобы он выполнял однократное чтение, преобразовывал его, а затем засыпал, пока новое нажатие клавиши не вызовет новое преобразование. Режим автономной работы лучше всего подходит, если единственное, что вы хотите, чтобы микроконтроллер делал, это постоянно считывать какой-либо аналоговый ввод - например, если вы хотите отображать температуру в реальном времени или что-то в этом роде.
Итак, давайте найдем еще одно решение …
Шаг 11: Как избавиться от кнопки? Версия 3
Есть много способов продолжить. Сначала мы могли бы добавить оборудование, чтобы избавиться от кнопки. Например, мы можем попробовать вставить транзистор в схему на выходной линии нажатия клавиш, чтобы он принимал небольшую струйку тока с выхода и отправлял импульс 5 В на вывод прерывания PD2.
Однако это, вероятно, было бы как минимум слишком шумным, а в худшем случае не дало бы достаточно времени для точного считывания нажатия клавиш, поскольку выходное напряжение клавиатуры не успеет стабилизироваться до того, как будет зафиксировано показание АЦП.
Так что лучше придумать программное решение. Что мы хотели бы сделать, так это добавить прерывание на вывод PD2 и написать для него обработчик прерывания, который вызывает однократное чтение вывода клавиатуры. Другими словами, мы избавляемся от прерывания автозапуска от АЦП и добавляем внешнее прерывание, которое вызывает внутри него АЦП. Таким образом, сигнал для чтения АЦП поступает после того, как сигнал PD2 уже возник, и это может дать достаточно времени для стабилизации точного напряжения до того, как вывод PC0 будет считан и преобразован. У нас все еще будет прерывание завершения АЦП, которое выводит результат на дисплей анализатора в конце.
Есть смысл? Ну что ж, сделаем это …
Взгляните на прикрепленный новый код.
Вы видите следующие изменения:
- Мы добавили rjmp по адресу.org 0x0002 для обработки внешнего прерывания INT0.
- Мы изменили регистр EIMSK, чтобы указать, что мы хотим прерывание на выводе INT0.
- Мы изменили вывод ADATE в регистре ADCSRA, чтобы отключить автозапуск.
- Мы избавились от настроек ADCSRB, поскольку они не имеют значения, когда ADATE выключен.
- Нам больше не нужно сбрасывать флаг внешнего триггера, поскольку процедура прерывания INT0 делает это автоматически после завершения - раньше у нас не было процедуры прерывания, мы просто запускали АЦП по сигналу на этом выводе, поэтому нам пришлось снимите этот флаг вручную.
Теперь в обработчике прерывания мы просто вызываем единичное преобразование из АЦП.
Упражнение 5. Запустите эту версию и посмотрите, что произойдет.
Шаг 12: Код и видео для рабочей версии
Как мы видели в последней версии, прерывание от кнопки работает не очень хорошо, потому что прерывание запускается по нарастающему фронту на вывод PD2, а затем обработчик прерывания вызывает преобразование АЦП. Однако затем АЦП получает значение напряжения до того, как оно стабилизируется, и поэтому он считывает ерунду.
Нам нужно ввести задержку между прерыванием на PD2 и чтением АЦП на PC0. Мы сделаем это, добавив таймер / счетчик, прерывание переполнения счетчика и процедуру задержки. К счастью, мы уже знаем, как это сделать из Урока 3! Поэтому мы просто скопируем и вставим оттуда соответствующий код.
Я привел полученный код и видео, демонстрирующее его работу.
Вы заметите, что показания не так точны, как можно было бы надеяться. Вероятно, это связано с рядом источников:
- мы подключаемся к выходу напряжения клавиатуры для запуска PD2, что влияет на показания в PC0.
- мы действительно не знаем, сколько времени нужно отложить после срабатывания триггера, чтобы получить наилучшее показание.
- Для завершения преобразования АЦП требуется несколько циклов, что означает, что мы не можем быстро запускать клавиатуру.
- возможно шум в самой клавиатуре.
- так далее…
Итак, хотя нам удалось заставить работать клавиатуру, и теперь мы можем использовать ее в приложениях, используя значения нажатия клавиш каким-либо другим способом, вместо того, чтобы просто выводить их на дисплей анализатора, это не очень точно и очень раздражает. Вот почему я думаю, что лучший способ подключить клавиатуру - просто вставить каждый выход клавиатуры в другой порт и решить, какая клавиша нажата, какие порты видят напряжение. Это легко, очень быстро и очень точно.
На самом деле, есть только две причины, по которым кто-то захочет управлять клавиатурой так, как мы здесь:
- Он использует только 2 контакта на нашем микроконтроллере вместо 8.
- Это отличный проект, чтобы показать различные аспекты АЦП на микроконтроллере, которые отличаются от стандартных вещей, которые вы можете там найти, таких как показания температуры, поворотные потенциометры и т.д. а не просто режим бесплатного использования ЦП.
В любом случае, вот вам пара заключительных упражнений:
Упражнение 6: Перепишите обработчик прерывания завершения преобразования АЦП для использования справочной таблицы. Т.е. Таким образом, он проверяет аналоговое значение с первым элементом в таблице, и если оно больше, оно возвращается из прерывания, если это не так, он увеличивает Z до следующего элемента в таблице и снова переходит к тесту. Это сократит код, очистит процедуру прерывания и сделает ее лучше. (Я дам возможное решение в качестве следующего шага) Упражнение 7: Подключите клавиатуру к 8 контактам микроконтроллера, напишите для него простой драйвер и убедитесь, насколько он лучше. Можете ли вы придумать несколько способов улучшить работу нашего метода?
Это все для этого урока. Я прикрепил окончательную версию с указателями. По мере того, как мы приближаемся к нашей конечной цели, мы еще раз будем использовать клавиатуру в Уроке 9, чтобы показать, как с ее помощью управлять семисегментными дисплеями (и создать что-то интересное, использующее дополнительные клавиши на клавиатуре телефона), а затем мы будем вместо этого переключитесь на управление с помощью нажатия кнопок (поскольку этот метод лучше подходит для конечного продукта, к которому мы стремимся с помощью этих руководств), и мы просто отложим клавиатуру.
Увидимся в следующий раз!
Рекомендуемые:
Учебник по ассемблеру AVR 2: 4 шага
Учебник 2 по ассемблеру AVR: Это руководство является продолжением «Учебного пособия 1 по ассемблеру AVR»; Если вы еще не прошли Урок 1, вам следует остановиться сейчас и сделать это в первую очередь. В этом уроке мы продолжим изучение программирования на языке ассемблера atmega328p u
Учебник по ассемблеру AVR, 1: 5 шагов
AVR Assembler Tutorial 1: Я решил написать серию руководств о том, как писать программы на языке ассемблера для Atmega328p, который является микроконтроллером, используемым в Arduino. Если люди останутся заинтересованными, я буду продолжать выпускать по одному в неделю или около того, пока у меня не закончатся
Учебник по ассемблеру AVR 9: 7 шагов
AVR Assembler Tutorial 9: Добро пожаловать в Урок 9. Сегодня мы покажем, как управлять как 7-сегментным, так и 4-значным дисплеем, используя наш код языка ассемблера ATmega328P и AVR. В ходе этого нам придется отвлечься от того, как использовать стек
Учебник по ассемблеру AVR 11: 5 шагов
AVR Assembler Tutorial 11: Добро пожаловать в Tutorial 11! В этом коротком руководстве мы, наконец, собираемся построить первую часть нашего финального проекта. Первое, что вам нужно сделать, это перейти к самому последнему шагу этого руководства и посмотреть видео. Тогда вернись сюда. [пауза, пока вы
Учебник по ассемблеру AVR 3: 9 шагов
Учебник 3 по AVR Assembler: Добро пожаловать в учебник №3! Прежде чем мы начнем, я хочу высказать несколько философских соображений. Не бойтесь экспериментировать со схемами и кодом, которые мы создаем в этих уроках. Поменяйте провода, добавьте новые компоненты, возьмите компонент