Съдържание:

Урок за асемблер на AVR 7: 12 стъпки
Урок за асемблер на AVR 7: 12 стъпки

Видео: Урок за асемблер на AVR 7: 12 стъпки

Видео: Урок за асемблер на AVR 7: 12 стъпки
Видео: AVR Ассемблер. Урок 7. ШИМ. Управление серво. AVR Assembler. Lesson 7. PWM. Servo control. 2024, Юли
Anonim
Урок за асемблер на AVR 7
Урок за асемблер на AVR 7

Добре дошли в Урок 7!

Днес първо ще покажем как да изчистим клавиатурата, а след това ще покажем как да използваме аналоговите входни портове за комуникация с клавиатурата, Ще направим това, като използваме прекъсвания и един проводник като вход. Ще свържем клавиатурата така, че всяко натискане на клавиш изпраща уникално напрежение към аналоговия вход, което ще ни позволи да различим по напрежението кой клавиш е натиснат. След това ще изведем номера, натиснат към нашия анализатор на регистър, за да покажем, че всичко се случва както трябва. Има редица подводни камъни, до които можете да се обърнете, когато използвате аналогово -цифровия преобразувател (ADC) в ATmega328p и така ще направим вземете нещата на няколко етапа по пътя, за да се опитате да разберете как да ги избегнете. Ще видим и защо използването на аналогово -цифров преобразувател не е най -добрият начин за управление на клавиатурата, въпреки че използва по -малко портове на вашия микроконтролер. В този урок ще ви трябва:

  1. клавиатура. Можете да си купите един или да направите това, което направих аз и да изчистя един.
  2. 2 женски заглавки за клавиатурата (ако изчиствате една)
  3. свързващи проводници
  4. макет
  5. 4 1 Кома резистори
  6. 1 15 резистора Kohm
  7. 1 3.3 Комов резистор
  8. 1 180 ома резистор
  9. Резистор 1 680 ома
  10. цифров мултицет
  11. вашия анализатор от Урок 5

Може да искате да пропуснете първите няколко стъпки, ако вече имате клавиатура и не е необходимо да я изчиствате.

Ето линк към пълната колекция от моите уроци за AVR асемблер:

Стъпка 1: Изчистете клавиатурата 1

Изчистете клавиатурата 1
Изчистете клавиатурата 1
Изчистете клавиатурата 1
Изчистете клавиатурата 1
Изчистете клавиатурата 1
Изчистете клавиатурата 1
Изчистете клавиатурата 1
Изчистете клавиатурата 1

Много отдавна, когато дори вашите баби и дядовци са били просто деца, хората са използвали тези странно изглеждащи устройства, които са имали дълги кабели, включени в стената, за да комуникират помежду си. Наричаха се „телефони“и обикновено бяха евтини пластмасови неща, които издаваха досаден звук, когато някой ви се обади (не че днешните мелодии на „Джъстин Бийбър“не са еднакво досадни). Във всеки случай, тези устройства са имали клавиатури, които са много просто свързани и затова са лесни за изчистване и имат 2 допълнителни клавиша върху тях ("повторно набиране" и "флаш") от клавиатурите, които можете да закупите, които може да искате да пренастроите като "клавиши със стрелки", "клавиши от менюто" или нещо друго. Така че ще започнем с изчистване на клавиатура от стар телефон. Първо вземете телефона (използвам такъв GE, както е показано на снимките) и го отделете, за да разкриете окабеляването.

Стъпка 2: Изчистете клавиатурата 2

Изчистете клавиатурата 2
Изчистете клавиатурата 2
Изчистете клавиатурата 2
Изчистете клавиатурата 2
Изчистете клавиатурата 2
Изчистете клавиатурата 2

Сега вземете PVC трион и изрежете пластмасата около отворите за ключове и след това изрежете около ръба, за да получите дълбочината вдясно, оставяйки тънка клавиатура.

След това поставете отново клавиатурата, като използвате малките колчета, които остават, след като сте отрязали върховете им в последната стъпка, и използвайте поялник, за да прокарате горещото желязо във всеки отвор за колче, което ще разтопи пластмасата и ще я разпръсне върху долната част на клавиатурата, образувайки нови „копчета“, които ще задържат клавиатурата на място както преди.

Обичам да изчиствам трите високоговорителя и може би другите неща като превключватели и какво ли не са на дъската. Този път обаче няма да търся превключвателите и други неща, защото в момента имаме други цели. Също така там има линейна интегрална схема TA31002, която е телефонна звънене. Информационният лист може лесно да бъде намерен и изтеглен онлайн, предоставящ разпечатката и функциите. Затова засега ще го оставя запоен към дъската и по -късно ще си поиграя с него. Бих искал да го свържа към осцилоскоп и да видя какви готини сигнали мога да извлека от него. Може би дори да направите звънец на вратата от него. Кой знае.

Така или иначе, след като приключите с унищожаването на телефона и изчистването на частите, ние ще завършим изработката на нашата клавиатура.

Стъпка 3: Изчистете клавиатурата 3

Изчистете клавиатурата 3
Изчистете клавиатурата 3
Изчистете клавиатурата 3
Изчистете клавиатурата 3
Изчистете клавиатурата 3
Изчистете клавиатурата 3

Използвайте фитил за разпаяване и отстранете лентовите кабели от долната част на клавиатурата, като се уверите, че дупките в платката са чисти и след това прикрепете две женски заглавки към дъската, където са отворите. Вероятно ще трябва да отрежете заглавките си, така че да са 4-пинови заглавки.

Сега, когато заглавките са прикрепени, можете да ги свържете към макет, да вземете мултицет и да тествате клавишите, като залепите мултицета върху произволни щифтове и измервате съпротивлението. Това ще ви позволи да начертаете ключовете. Трудно е да се види как ключовете са свързани към изходите, като се погледне веригата, но ако използвате мултицет, можете да го включите към всеки два пина и след това да натискате бутоните, докато не видите число на екрана вместо отворена верига. Това ще бъде извеждането на този ключ.

Посочете всички ключове за извеждане на пинове по този начин.

Стъпка 4: Свържете клавиатурата

Свържете клавиатурата
Свържете клавиатурата
Свържете клавиатурата
Свържете клавиатурата

Сега следвайте схемата на свързване и свържете клавиатурата към вашата дъска.

Как ще работи това е, че ще поставим 5V в лявата страна, а дясната страна отива към GND. Първият щифт вдясно на диаграмата влиза в първия от нашите аналогови щифтове на микроконтролера Atmega328p. Когато няма натиснати бутони, сигналът ще бъде 0V, а когато се натисне всеки от различните бутони, входът към аналоговия порт ще варира между 0V и 5V с различно количество в зависимост от това кой клавиш е натиснат. Избрахме стойностите на резистора, така че всеки път да съдържа съпротивление, различно от останалите. Аналоговият порт на микроконтролера приема аналогов сигнал и го разделя на 1024 различни канала между 0V и 5V. Това означава, че всеки канал има ширина 5V/1024 = 0.005 V/канал = 5 mV/канал. Така че аналоговият порт може да различава входното напрежение, стига да се различава с повече от 5 mV. В нашия случай сме избрали стойности на резистора, така че всеки два натискания на клавиши да изпращат сигнал за напрежение, който се различава с повече от това, така че микроконтролерът лесно да може да реши кой клавиш е натиснат. Големият проблем е, че цялата система е много шумна, така че ще трябва да изберем диапазон от напрежения, които да се съпоставят с всяко натискане на бутон - но ще влезем в това малко по -късно.

Забележете, че можем да управляваме клавиатура с 14 бутона, използвайки само един входен ред към контролера. Това е един от полезните аспекти на аналоговите входове.

Сега първият ни опит да контролираме клавиатурата ще бъде натискането на клавиш да предизвика прекъсване, подпрограмата за прекъсване ще прочете порта за аналогов вход и ще реши кой клавиш е натиснат и след това ще изведе този номер към нашата подпрограма за анализатор на регистър, която ще покаже ключова стойност в двоичен формат на нашите 8 светодиода, които сме настроили в Урок 5.

Стъпка 5: Свържете клавиатурата към вашия анализатор

Свържете клавиатурата към вашия анализатор
Свържете клавиатурата към вашия анализатор
Свържете клавиатурата към вашия анализатор
Свържете клавиатурата към вашия анализатор

Снимките показват как искаме да свържем клавиатурата към микроконтролера, така че да можем да видим изхода на нашия дисплей на анализатора. По същество ние просто свързваме изхода от клавиатурата към PortC пин 0, който също се нарича ADC0 на ATmega328P.

Има обаче няколко допълнителни неща. Също така ще свържем бутон към PD2. Т.е. вземете проводник от вашата 5V шина към бутон и от другата страна на бутона към PD2 и накрая искаме да изключим щифта AREF от нашата 5V шина и вместо това да го оставим изключен. Бихме могли да поставим 0,1 микрофарад кондензатор за отделяне, ако искаме. Това е керамичен кондензатор с надпис 104. Първите две цифри са числото, а последната цифра е степента на 10, умножаваме я, за да получим отговор в пикофаради (pico означава 10^-12), така че 104 означава 10 x 10^4 picofarads, което е същото като 100 нанофарада (нано означава 10^-9), което е същото като 0,1 микрофарада (микро означава 10^-6). Както и да е, всичко това прави стабилизиране на щифта AREF, когато можем да го използваме като референтен щифт.

Искаме и 1 Mohm резистор между PD2 и земята. Ще настроим PD2 като изходен щифт при 0V и ще задействаме на положителен ръб на този щифт. Искаме ръбът да изчезне веднага, когато освободим бутона, така че ще вмъкнем този "издърпващ" резистор.

Причината, поради която искаме бутона, е, че искаме да задействаме нашия аналогово-цифров преобразувател извън щифт INT0 на чипа, който също е PD2. В крайна сметка бихме искали натискането на клавиш едновременно да задейства ADC и също така да осигури преобразуването на входа, без да има отделен бутон, но поради начина, по който работи времето, ще започнем, като имаме отделен бутон за задействане на ADC и след като изгладим всички отстраняваме грешките и сме уверени, че всичко работи правилно, тогава ще се справим с проблемите с шума и времето, които идват при задействане от същото натискане на бутон, което искаме да прочетем.

Така че засега начинът, по който работи, е, че ще задържим клавиш, след това ще натиснем бутона, за да задействаме ADC, и след това ще го пуснем и да се надяваме, че двоичната стойност на бутона, който натиснахме, ще се покаже на анализатора.

Така че нека напишем код, който ще постигне това.

Стъпка 6: Кои превключватели за превключване трябва да зададем?

Кои превключватели за превключване трябва да настроим?
Кои превключватели за превключване трябва да настроим?

Нека първо помислим как ще кодираме това, така че контролерът да може да прочете входа от клавиатурата и да го превърне в числова стойност, съответстваща на бутона, който е натиснат. Ще използваме аналогово -цифров преобразувател (ADC) който е вграден в Atmega328p. Ще използваме AREF като референтно напрежение, а изходът на клавиатурата ще бъде свързан към PortC0 или PC0. Имайте предвид, че този щифт се нарича още ADC0 за аналогово-цифров преобразувател 0. Може да е добра идея да прочетете раздел 12.4 за прекъсванията за ATmega328P, а също и глава 24 за аналогово-цифровия преобразувател, преди да получим за да настроим микроконтролера, така че да знае какво да прави с аналогов входен сигнал и как да взаимодейства с нашата програма, първо трябва да настроим няколко от различните ADC свързани регистърни битове. По същество те са еквивалентни на старите превключватели на първите компютри. Можете или да включите или изключите превключвател, или дори по -назад да включите кабели между един изход и друг, така че електроните, достигащи до тази разклонение на пътя, да намерят една врата затворена, а друга отворена, което я принуждава по различен път в лабиринта на верига и по този начин изпълнява различна логическа задача. Когато кодираме на асемблерен език, имаме близък достъп до тези функции на микроконтролера, което е едно от атрактивните неща за това да го направите на първо място. Това е повече „на ръце“и много по -малко се случва „зад кулисите“. Така че не мислете да поставяте тези регистри като досадна задача. Това прави асемблерния език интересен! Получаваме много лична връзка с вътрешната работа и логиката на чипа и го караме да прави точно това, което искаме - нито повече, нито по -малко. Няма пропилени цикли на часовника. Ето списък на ключовете, които трябва да настроим:

  1. Изключете ADC бита за намаляване на мощността, PRADC, който е бит 0 от регистъра PRR, тъй като ако този бит е включен, той ще изключи ADC. Регистърът за намаляване на мощността е по същество начин за изключване на различни неща, които използват енергия, когато нямате нужда от тях. Тъй като използваме ADC, искаме да се уверим, че той не е деактивиран по този начин. (Вижте PRADC на страница 46)
  2. Изберете аналоговия входен канал да бъде ADC0, като изключите MUX3… 0 в регистъра за избор на ADC мултиплексор (ADMUX) (вижте таблица 24-4 стр. 249), те вече са изключени по подразбиране, така че не е нужно да правим това. Включвам го обаче, тъй като ако някога използвате порт, различен от ADC0, ще трябва да превключите съответно тези превключватели. Различни комбинации от MUX3, MUX2, MUX1, MUX0 ви позволяват да използвате всеки от аналоговите портове като вход и можете също да ги промените в движение, ако искате да разгледате няколко различни аналогови сигнала наведнъж.
  3. Изключете битовете REFS0 и REFS1 в регистъра ADMUX, така че да използваме AREF като наше референтно напрежение, а не като вътрешна референция (Вижте страница 248).
  4. Включете бита ADLAR в ADMUX, така че резултатът да е "регулиран наляво", ще обсъдим този избор в следващата стъпка.
  5. Задайте бита ADC0D в регистъра за изключване на цифровия вход (DIDR0), за да изключите цифровия вход на PC0. Използваме този порт за аналогов вход, така че можем също да деактивираме цифровия вход за него.
  6. Задайте ISC0 и ISC1 в регистъра за управление на външни прекъсвания A (EICRA), за да покажете, че искаме да задействаме по нарастващия ръб на сигнал за напрежение към извода INT0 (PD2), вижте страница 71.
  7. Изчистете битовете INT0 и INT1 в регистъра на маската за външни прекъсвания (EIMSK), за да покажете, че не използваме прекъсвания на този щифт. Ако трябва да разрешим прекъсвания на този пин, ще се нуждаем от манипулатор на прекъсвания на адрес 0x0002, но вместо това го настройваме така, че сигнал на този пин да задейства преобразуването на ADC, чието завършване се обработва чрез пълно прекъсване на преобразуването на ADC адрес 0x002A. Вижте страница 72.
  8. Задайте бита за активиране на ADC (ADEN) (бит 7) в контрола на ADC и регистъра на състоянието A (ADCSRA), за да активирате ADC. Вижте страница 249.
  9. Бихме могли да започнем единично преобразуване, като задаваме бита за преобразуване на ADC (ADSC) всеки път, когато искаме да прочетем аналоговия сигнал, но засега бихме предпочели той да се чете автоматично всеки път, когато някой натисне бутона, така че вместо това ще активираме ADC Autotrigger Enable (ADATE) бит в регистъра ADCSRA, така че задействането да се извършва автоматично.
  10. Също така зададохме ADPS2..0 бита (AD Prescalar бита) на 111, така че часовникът на ADC да е часовникът на процесора, разделен на фактор 128.
  11. Ще изберем източника на задействане на ADC да бъде PD2, който също се нарича INT0 (Заявка за външно прекъсване 0). Правим това, като превключваме различните битове в регистъра ADCSRB (Вижте Таблица 24-6 на страница 251). По таблицата виждаме, че искаме ADTS0 да е изключен, ADTS1 включен и ADTS2 изключен, така че ADC да задейства този щифт. Обърнете внимание, ако искаме непрекъснато да вземаме проби от аналоговия порт, като ако четем някакъв непрекъснат аналогов сигнал (като звукова проба или нещо подобно), бихме задали това в режим на свободна работа. Използваният от нас метод за настройка на задействане на PD2 задейства ADC отчитане на аналоговия порт PC0, без да причинява прекъсване. Прекъсването ще дойде, когато преобразуването приключи.
  12. Активирайте бита за активиране на ADC прекъсване (ADIE) в регистъра на ADCSRA, така че когато аналогово -цифровото преобразуване приключи, ще генерира прекъсване, за което можем да напишем манипулатор на прекъсвания и да го поставим на.org 0x002A.
  13. Задайте I бита в SREG, за да активирате прекъсванията.

Упражнение 1: Уверете се, че сте прочели съответните раздели в листа с данни за всяка от горните настройки, за да разберете какво се случва и какво би станало, ако ги променим на алтернативни настройки.

Стъпка 7: Напишете манипулатора на прекъсвания

В последната стъпка видяхме, че сме го настроили така, че нарастващ ръб, открит на PD2, да задейства аналогово -цифрово преобразуване на PC0 и когато това преобразуване приключи, ще хвърли прекъсване на ADC Conversion Complete. Сега искаме да направим нещо с това прекъсване. Ако разгледате Таблица 12-6 на страница 65, ще видите списък с възможните прекъсвания. Вече видяхме прекъсването RESET на адрес 0x0000 и прекъсването на таймера/брояча0 Overflow на адрес 0x0020 в предишни уроци. Сега искаме да разгледаме ADC прекъсването, което виждаме от таблицата, е на адрес 0x002A. Така че в началото на нашия код на асемблер ще ни трябва ред, който гласи:

.org 0x002Arjmp ADC_int

който ще премине към нашия манипулатор на прекъсвания, означен с ADC_int, когато ADC е завършил преобразуване. И така, как трябва да напишем нашия манипулатор на прекъсвания? Начинът, по който работи ADC, е чрез извършване на следното изчисление:

ADC = Vin x 1024 / Vref

Така че нека да видим какво ще се случи, ако натисна бутона "повторно набиране" на клавиатурата. В този случай напрежението на PC0 ще се промени до някаква стойност, да речем 1.52V, и тъй като Vref е на 5V ще имаме:

ADC = (1.52V) x 1024 / 5V = 311.296

и така щеше да се покаже като 311. Ако искаме да преобразуваме това обратно във напрежение, просто бихме обърнали изчислението. Няма да се налага да правим това обаче, тъй като не се интересуваме от действителните напрежения, само за да правим разлика между тях. Когато преобразуването приключи, резултатът се съхранява в 10-битово число, поставено в регистрите ADCH и ADCL и ние сме го накарали да бъде "регулиран наляво", което означава, че 10-битовите започват от бит 7 на ADCH и се спускат до бит 6 на ADCL (има общо 16 бита в тези два регистъра и ние използваме само 10 от тях, т.е. 1024 канала). Бихме могли да имаме резултата „дясно коригиран“, ако искаме, като изчистим бита ADLAR в регистъра ADMUX. Причината, поради която избираме коригиране наляво, е, защото нашите сигнали са достатъчно отдалечени, че последните две цифри от номера на канала не са релевантни и вероятно са просто шум, така че ще различаваме натискането на клавиши, използвайки само горните 8 цифри, с други думи, ще трябва само да погледнем ADCH, за да разберем кой бутон е натиснат. Така че нашият прекъсвач трябва просто да прочете номера от ADCH регистрирайте, преобразувайте това число в стойност на клавиатурата и след това изпратете тази стойност към нашите светодиоди за анализатор на регистър, така че да можем да проверим дали натискането на „9“ще доведе до включване на светодиодите, съответстващи на „00001001“. Преди да отидем това макар че първо трябва да видим какво се показва в ADCH, когато натискаме различните бутони. Нека просто напишем прост манипулатор на прекъсвания, който просто изпраща съдържанието на ADCH на дисплея на анализатора. Ето какво ни трябва:

ADC_int: lds анализатор, ADCH; заредете стойността на ADCH в нашия анализаторbi EIFR, 0; изчистете външния флаг за прекъсване, така че да е готов за работа

Досега трябва да можете просто да копирате кода от нашия анализатор в урок 5 и да добавите това прекъсване и настройките за превключване и да го стартирате. Упражнение 2: Напишете кода и го стартирайте. Вижте дали на дисплея на анализатора се показва ADCH. Опитайте да натиснете един и същ клавиш няколко пъти. Получавате ли винаги една и съща стойност в ADCH?

Стъпка 8: Начертайте стойностите на натискането на клавиш

Начертайте стойностите на натискането на клавиш
Начертайте стойностите на натискането на клавиш

Това, което трябва да направим сега, е да преобразуваме стойностите в ADCH в числа, съответстващи на натиснатия клавиш. Правим това, като изписваме съдържанието на ADCH за всяко натискане на клавиш и след това го преобразуваме в десетично число, както направих на снимката. В нашата рутина за обработка на прекъсвания ще разгледаме цял набор от стойности като съответстващи на всяко натискане на клавиш, така че ADC да съпостави всичко в този диапазон с дадено натискане на клавиш.

Упражнение 3: Направете това ma-p.webp

Ето какво получих за моя (твоят много вероятно ще бъде различен). Забележете, че съм го настроил с диапазон от стойности за всяко натискане на клавиш.

ADC_int:; Външен анализатор за прекъсване handlerclr; подгответе за нови номера бутони H, ADCH; ADC се актуализира, когато се чете ADCH clccpi бутон H, 240brlo PC+3; ако ADCH е по -голям, това е 1ldi анализатор, 1; така че натоварвайте анализатора с 1rjmp връщане; и бутон за връщане clccpiH, 230; ако ADCH е по -голям, тогава 2brlo PC+3ldi анализатор, 2rjmp бутон за връщане clccpiH, 217brlo PC+3ldi анализатор, 3rjmp връщане clccpi бутон H, 203brlo PC+3ldi анализатор, 4rjmp бутон за връщане clccpiH, 187brlo PC+3ldi анализатор, 5rjmp връщане ccc, 155brlo PC+3ldi анализатор, 6rjmp бутон за връщане clccpiH, 127brlo PC+3ldi анализатор, 255; ще настроим флаш като всички onrjmp бутон за връщане clccpi H, 115brlo PC+3ldi анализатор, 7rjmp връщане clccpi бутон H, 94brlo PC+3ldi анализатор, 8rjmp бутон за връщане clccpiH, 62brlo PC+3ldi анализатор, 9rjmp бутон за връщане clccpiH, 37brlo PC+3ldi анализатор, 0b11110000; звездичката е горната половина на бутона onrjmp връщане clccpiH, 28brlo PC+3ldi анализатор, 0rjmp връщане clccpi бутонH, 17brlo PC+3ldi анализатор, 0b00001111; хеш знак е долната половина onrjmp връщане clccpi бутон H, 5brlo PC+3ldi анализатор, 0b11000011; повторно набиране е отгоре 2 отдолу 2rjmp връщане ldi анализатор, 0b11011011; в противен случай възникна грешка return: reti

Стъпка 9: Код и видео за версия 1

Прикачих моя код за тази първа версия на драйвера на клавиатурата. В този трябва да натиснете клавиша и след това да натиснете бутона, за да накарате ADC да прочете входа от клавиатурата. Това, което предпочитаме, е да няма бутон, а вместо това сигналът за извършване на преобразуването идва от самото натискане на клавиш. Упражнение 3: Съберете и качете този код и го опитайте. Може да се наложи да промените различните прагове на преобразуване, за да съответстват на напреженията при натискане на клавиша, тъй като те вероятно се различават от моите. Какво се случва, ако се опитате да използвате вход от клавиатурата както за ADC0, така и за външен прекъсвач, вместо чрез бутон? Ще прикача и видео на работата на тази първа версия на нашия драйвер за натискане на клавиш. Ще забележите, че в моя код има раздел, инициализиращ указателя на стека. Има различни регистри, които може да искаме да избутаме и да изскачаме от стека, когато манипулираме променливи и какво-не, а има и регистри, които може да искаме да запазим и възстановим по-късно. Например, SREG е регистър, който не се запазва при прекъсвания, така че различните флагове, които са зададени и изчистени в резултат на операции, могат да бъдат променени, ако прекъсване възникне в средата на нещо. Така че най -добре е да натиснете SREG към стека в началото на манипулатор на прекъсване и след това да го извадите отново в края на манипулатора на прекъсване. Поставих го в кода, за да покажа как е инициализиран и да предвидя как ще се нуждаем от него по -късно, но тъй като не ни интересува какво се случва с SREG по време на прекъсвания в нашия код, не използвах стека за това. че съм използвал операцията shift, за да задам различни битове в регистрите при инициализация. Например в реда:

ldi temp, (1 <> sts EICRA, темп

Командата "<<" в първия ред на кода по -горе е операция за смяна. По същество той взема двоичното число 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" и "andi". Те ни позволяват да задаваме битове SET и CLEAR съответно, без да променяме някой от другите битове в регистър. Например, когато използвах

ori temp, (1

тази температура "или" с 0b00000001, която поставя 1 в нулевия бит и оставя всички останали непроменени. Също и когато писахме

andi temp, 0b11111110

това променя нулевия бит на temp на 0 и оставя всички останали непроменени.

Упражнение 4: Трябва да преминете през кода и да се уверите, че разбирате всеки ред. Може да ви е интересно да намерите по -добри методи за правене на неща и да напишете по -добра програма. Има сто начина да кодирате нещата и съм доста уверен, че можете да намерите много по -добър начин от моя. Може също да откриете (не дай Боже!) Грешки и пропуски. В такъв случай със сигурност бих искал да чуя за тях, за да могат да бъдат поправени.

Добре, сега да видим дали можем да се отървем от този излишен бутон …

Стъпка 10: Код за версия 2

Най -простият начин да се отървете от бутона е просто да го премахнете напълно, да забравите входа на PB2 и просто да превключите ADC в "Free Running Mode".

С други думи, просто променете ADCSRB регистъра, така че всички ADTS2, ADTS1 и ADTS0 да са нули.

След това задайте бита ADSC в ADCSRA на 1, което ще започне първото преобразуване.

Сега го качете на вашия микроконтролер и ще откриете, че правилното число се появява на дисплея, докато натискате бутона и само докато натискате бутона. Това е така, защото ADC непрекъснато взема проби от порта ADC0 и показва стойността. Когато свалите пръста си от бутона, "отскачането на бутона" ще доведе до много бързи няколко случайни стойности и след това ще се установи обратно на 0V вход. В нашия код това 0V се появява като 0b11011011 (тъй като натискането на клавиш `0 'вече използва стойността на дисплея 0b00000000)

Това не е решението, което искаме, но поради две причини. Първо не искаме да държим бутона. Искаме да го натиснем веднъж и да покажем номера (или да го използваме в някакъв нов код в по -късен урок). Второ, не искаме непрекъснато да вземаме проби от ADC0. Искаме той да вземе едно четене, да го преобразува и след това да спи, докато ново натискане на клавиш задейства ново преобразуване. Режимът на свободно движение е най -добрият, ако единственото нещо, което искате микроконтролерът да прави, е непрекъснато да чете някакъв аналогов вход - например ако искате да показвате температури в реално време или нещо подобно.

Така че нека намерим друго решение …

Стъпка 11: Как да се отървем от бутона? Версия 3

Как да се отървем от бутона? Версия 3
Как да се отървем от бутона? Версия 3

Има много начини да продължим. Първо бихме могли да добавим хардуер, за да се отървем от бутона. Например, можем да опитаме да поставим транзистор във веригата на изходната линия на натискането на клавиша, така че да отнеме малко струйка от тока от изхода и да изпрати 5V импулс към прекъсващия щифт PD2.

Това обаче най -малкото би било твърде шумно и в най -лошия случай не би позволило достатъчно време за точно отчитане на натискането на клавиш, тъй като изходното напрежение на клавиатурата няма да има време да се стабилизира, преди да бъде уловено отчитането на ADC.

Така че ние по -скоро ще предложим софтуерно решение. Това, което бихме искали да направим, е да добавим прекъсване към пина PD2 и да напишем за него манипулатор на прекъсване, който извиква единично четене на щифта на клавиатурата. С други думи, ние се освобождаваме от прекъсването на автоматичното задействане от ADC и добавяме външно прекъсване, което извиква ADC вътре в него. По този начин сигналът за четене на ADC идва след като PD2 сигналът вече е възникнал и това може да даде на нещата достатъчно време да се стабилизират до точно напрежение, преди да бъде прочетен и преобразуван щифтът PC0. Все още ще имаме прекъсване на завършване на ADC, което извежда резултата на дисплея на анализатора в края.

Има смисъл? Е, нека го направим…

Вижте прикачения нов код.

Виждате следните промени:

  1. Добавихме rjmp на адрес.org 0x0002 за обработка на външното прекъсване INT0
  2. Променихме регистъра EIMSK, за да посочим, че искаме да прекъсваме на пина INT0
  3. Променихме щифта ADATE в регистъра на ADCSRA, за да деактивираме автоматичното задействане
  4. Отървахме се от настройките на ADCSRB, тъй като те са без значение, когато ADATE е изключен
  5. Вече не се налага да нулираме флага на външното задействане, тъй като рутинната програма за прекъсване INT0 прави това автоматично, когато приключи - преди това не сме имали рутина за прекъсване, просто задействахме ADC на сигнал на този пин, така че трябваше да изчистете това знаме на ръка.

Сега в манипулатора на прекъсване ние просто извикваме единична конверсия от ADC.

Упражнение 5: Изпълнете тази версия и вижте какво ще се случи.

Стъпка 12: Код и видео за работната версия

Както видяхме в последната версия, прекъсването на бутона не работи много добре, защото прекъсването се задейства по нарастващ ръб, за да закрепи PD2 и след това манипулаторът на прекъсване извиква преобразуването на ADC. След това обаче ADC получава отчитане на напрежението, преди да се стабилизира и така чете глупости.

Това, от което се нуждаем, е да въведем забавяне между прекъсването на PD2 и отчитането на ADC на PC0. Ще направим това, като добавим таймер/брояч, прекъсване на препълване на брояча и рутина за забавяне. За щастие вече знаем как да направим това от Урок 3! Така че просто ще копираме и поставим съответния код от там.

Дадох получения код и видеоклип, който го показва в действие.

Ще забележите, че показанията не са толкова точни, колкото бихте се надявали. Това вероятно се дължи на редица източници:

  1. ние подслушваме от изхода на напрежението на клавиатурата, за да задействаме на PD2, което влияе на отчитането в PC0.
  2. ние всъщност не знаем колко време да забавим след спусъка, за да получим най -доброто отчитане.
  3. отнема няколко цикъла, за да завърши преобразуването на ADC, което означава, че не можем да стреляме бързо по клавиатурата.
  4. вероятно има шум в самата клавиатура.
  5. и т.н…

Така че, въпреки че успяхме да накараме клавиатурата да работи и сега бихме могли да я използваме в приложения, като използваме стойностите на натискането на клавиши по някакъв друг начин, вместо просто да ги извеждаме на дисплея на анализатора, това не е много точно и е много досадно. Ето защо смятам, че най -добрият начин за свързване на клавиатури е просто да залепите всеки изход от клавиатурата в различен порт и да решите кой клавиш е натиснат от кои портове виждат напрежение. Това е лесно, много бързо и много точно.

Всъщност има само две причини, поради които човек би искал да управлява клавиатура така, както направихме тук:

  1. Той използва само 2 от пиновете на нашия микроконтролер вместо 8.
  2. Това е страхотен проект за показване на различни аспекти на ADC на микроконтролера, който е различен от стандартните неща, които можете да откриете там, като отчитане на температурата, завъртане на потенциометри и т.н. Исках пример за задействани единични показания и външно автоматично задействане а не просто свободно работещ CPU-gobbling режим.

Както и да е, ето ви една последна упражнение:

Упражнение 6: Напишете отново манипулатора за пълно прекъсване на преобразуването на ADC, за да използвате таблица за търсене. Т.е. Така че тества аналоговата стойност с първия елемент в таблицата и ако е по -голям, се връща от прекъсването, ако не е, то увеличава Z към следващия елемент в таблицата и отново се връща към теста. Това ще съкрати кода и ще изчисти рутината за прекъсване и ще я направи по -хубава. (Ще дам възможно решение като следваща стъпка) Упражнение 7: Свържете клавиатурата си към 8 пина на микроконтролера и напишете простия драйвер за нея и изпитайте колко по -хубава е тя. Можете ли да измислите няколко начина за подобряване на нашия метод?

Това е всичко за този урок. Прикачих окончателната версия с указатели. Докато се приближаваме към крайната цел, ще използваме клавиатурата още веднъж в Урок 9, за да покажем как да управляваме седем сегментни дисплея с нея (и да изградим нещо интересно, което използва допълнителните клавиши на клавиатурата на телефона) и след това ще вместо това преминете към контролиране на нещата с натискане на бутони (тъй като този метод се вписва по-добре с крайния продукт, към който се стремим с тези уроци) и просто ще отложим клавиатурата.

До следващия път!

Препоръчано: