ATMEL AVR микроконтролери - първи стъпки

Тук е мястото да споделим полезна техническа информация

Re: ATMEL AVR микроконтролери - първи стъпки

Мнениеот Gogo55 » 24 Дек 2010 23:54

И така,вече направихме нещо,но не можем да го асимилираме защото имаме неяснотии.В краина сметка нашия микроконтролер вече не е парче пластмаса.Сега от него свети един светодиод, и даже мига...тоест имаме успех все пак :).Когато аз размигах първия си светодиод бях много щастлив-има една поговорка:"Колко малко му трябва на човек да е щастлив-парче хляб, малко сол , една малка 7 метрова яхта, и една малка триетажна вила в Маями :lol: .
Сега ще поговорим за алгоритмите.
Алгоритъм-това е една последователност от команди.
Линеен алгоритъм-това е такъв алгоритъм в който командите се изпълняват последователно една след друга-точно линеино.
Пример за линеен алгоритъм:
1.Прибери се в къщи
2.направи си кафе
3.запали си цигара
4.изпуши си цигарата с кеф и си пии кафето..... и т.н.
Нелинеен алгоритъм/променлив,диференциален/алгоритъм,тои изглежда така:
1.прибери се в къщи
2.направи си кафе.
3.ако има цигара я вземи,ако няма цигара ,си направи ядене
4.ако е имало цигара я запали и изпуши пиеики си кафето,ако е нямало цигара се наяж.
Диференциалния алгоритъм се отличава от линеиния алгоритъм по това че според някакви обстоятелства,то тои може да се изпълни по няколко различни начина.....Линеиния алгоритъм от началото до края се изпълнява по една последователност и по един начин.
Диференциалния алгоритъм се създава от различни каманди :
Ако(таковата) - тогава(ще го таковаме), иначе(няма да го таковаме) :)
В ассемблера също има такива команди.Сега ще разгледаме някои от тях.
brne (Branch if Not Equal) - преход към метката, ако резултата от предишното действие – не е нула

Пример:
brne Label - премини към метке Label.
Още не сме разказали за метките!
Метка значи някакво място в програмата,позволяващо в един свободно избран момент да се прескочи директно в това място като не се изпълняват опарациите преди него.
Всяка метка има свое единствено и неповторимо име вътре в една програма.И тъи като асамблера е нечувствителен към регистрите,затова думи като Label,label,LABEL-за компилатора са напълно еднакви,за разлика от С.
В асамблера метката се поставя така:

...
and Temp1,Temp3
Label: ldi Temp1,100
mov Temp,Temp1
...
Тогава при преход на метка Label,програмата започва да изпълнява команда”ldi Temp1,100”.
Разбира се на метка може да се отиде не само по условие,но и „просто еи така за кеф”.Такъв преход се нарича безусловен:
rjmp - безусловен преход към метката

Пример:
rjmp Label
И за пълна красота ,ето още няколко условни прехода:

breq - (Branch if Equal)преход, ако резултата от предишното действие - нула
brmi - (Branch if Minus) преход, ако резултата е отрицателен. (При това, числото 0 се счита за положително.)
brpl - (Branch if Plus) преход, ако резултата е положителен
това е,сега може да напишем нашия алгоритъм.
Но преди това ето още две команди:

inc - (Increment) увеличаване на значението на РОН на 1 (инкремент)
dec - (Decrement) намаляване на значението на 1 (декремент).

Пример:
inc Temp2
dec Temp3
а сега да видим как работи тази програма:
ldi Temp,0

Loop: dec Temp
brne Loop
Първо сме инициализирали Temp с числото 0.После от Temp се вади 1.Неговото значение става -1/казано по друг начин,255/След това проверяваме дали не се е получила 0.Тъи като числото 255 не е равно на 0,отново отиваме на операцията декремент.
Значението на Temp се намалява още с 1.Сега то е 244.Но това също не е 0,и отново отиваме в началото....И така до тогава,докато в един прекрасен момент в отговор се получи 0.Когато всичкото това свърши излизаме от цикъла и продължаваме напред-тоест надоло по сорс кода на програмата...
Това което гледахме да сега,се нарича цикъл със задръжки.
Защо?Защото тази част от програмата по същност нищо не прави,но изпълнява процесорните тактове-минава време демек.Този цикъл ще ни трябва много пъти във всяка една програма.Този цикъл определя времето за деиствие или бездеиствие –тоест скороста с която ще се изпълни дадено деиствие.
Може да се правят няколко цикъла на задръжка:
ldi Temp1,0
ldi Temp2,0
ldi Temp3,100

Loop: dec Temp1
brne Loop

dec Temp2
brne Loop

dec Temp3
brne Loop
Сега вече имаме нужните знания,за да напишем програма за бягаща светлина или за мигалка.
Пишем!

.cseg
.org 0

ldi Temp,0b11111111 ;настройкана всичките крачета от порт B
out DDRB,Temp ;порт В на изход
;DDRB-таз команда превключва порт Б на изход.
Begin: ldi Temp,0b00000001 ;светка 1-я светодиод-където има 1
out PortB,Temp ;порт В го кръщаваме Temp

ldi Temp1,0 ;задържане чрез цикли,темп1 и темп2 ги
;правим=0,и почва цикъл да се намялят
;от 0/255/ надоло през -244,-243,-242 и т.н
;докато отново станат нула.
ldi Temp2,0
ldi Temp3,100

Loop1: dec Temp1
brne Loop1 ;когато темп1 стане нула отново,продлъжава прогр
;амата надоло

dec Temp2
brne Loop1

dec Temp3
brne Loop1



ldi Temp,0b00000010 ;светкаме 2-я светодиод
out PortB,Temp

ldi Temp1,0 ;задържаме
ldi Temp2,0
ldi Temp3,10

Loop2: dec Temp1
brne Loop2

dec Temp2
brne Loop2

dec Temp3
brne Loop2



ldi Temp,0b00000100 ;светкаме 3-я светодиод
out PortB,Temp

ldi Temp1,0 ;задържаме
ldi Temp2,0
ldi Temp3,10


Loop3: dec Temp1
brne Loop3

dec Temp2
brne Loop3

dec Temp3
brne Loop3



ldi Temp,0b00001000 ;светка 4-я светодиод
out PortB,Temp

ldi Temp1,0 ;задържаме
ldi Temp2,0
ldi Temp3,10

Loop4: dec Temp1
brne Loop4

dec Temp2
brne Loop4

dec Temp3
brne Loop4


rjmp Begin ;ржумп-веднага да отиде на бегин
;значи цикъла на програмата почва отново

Програмата е написана само за 4 светодиода.Мисля че да се допише и за останалите 4 от този порт няма да е голяма трудност.
И така както до сега:компилираме,шием,гледаме умно...Ако искаме да разберем колко точно е един цикъл или машинен такт то пишем темп1,1 и мерим с осцилоскопа колко мкс идва, после пишем темп1,100 и пак мерим и правим сравнение и т.н.
Викам си че без излишни коментарии се разбира че програмата стана прекалено голяма.По натам ще видим как да я намалим от към писане и когато привършим с асамблера и минем на беисик примерно това което сега е десетина реда може да го направим с 2 реда примерно но всяко нещо с времето си.
Gogo55
Администратор
 
Мнения: 496
Регистриран на: 30 Яну 2010 05:17

Re: ATMEL AVR микроконтролери - първи стъпки

Мнениеот Gogo55 » 25 Дек 2010 00:27

Създаване на функции в Асамблера.Мигалка V1.1
На сегашния момент при нас вече бяга светлинатаи ние и се радваме.Обаче програмата е прекалено голяма.Ето как изглежда неиния алгоритъм/без настроики на портовете:
1.Изход 00000001
2.Пауза 1
3.Изход 00000010
4.Пауза 2
5.Изход 00000100
6.Пауза 3
7.Изход 00001000
8.Пауза 4
9.Отиди в началото
А сега вижте:всичките паузи са напълно еднакви като две капки вода.Тогава защо да преписваме едно и също всеки път?Трябва да се напише паузата един път,а след това се обръщаме към нея толкова пъти колкото е нужно!
Тези който са учили езици от високо ниво за запознати с понятието „функция”.Така,на нас ни трябва да оформим паузата именно като функция.
За това се запознаваме с още някои нови команди:
rcall - (Relative Call) - извиква подпрограмата

ret – изход от подпрограмата.При това продължава изпълнението на програмата,извикваща дадената подпрограма,от мястото на извикването и. Т.е., с команди,следващи зад команда rcall.

Пример:

;извикваща программа
ldi Temp,45
rcall Delay ;извиква подпрограмма по метка Delay
out PortB,Temp
...

;подпрограмма
Delay: ldi Temp1,0 ;начало на подпрограмма

Loop: dec Temp1
brne Loop
ret ;край подпрограмма.
;Възвръщане към команда out PortB,Temp
Какво е това метка,и как става прехода?
В самото начало,ние говорихме че програмата на контролера е записана в ПЗУ.
Всяка команда си има свои собствен уникален адрес.Има и брояч на адресите,който последователно изкарва командите на дадената програма.
При компилация на кода,компилатора заменя всички наши метки на съответсващите им адреси в ПЗУ,и смята разтоянието от всяка метка до всяка команда,обръщаща се към тази метка.Защо командите се казват rjmp (RELATIVE jump), rcall (RELATIVE call)-защото те не съдържат абсолютния адрес на метките ,а относителния.Има значи число,на което трябва да се увеличи/намали текущия адрес в ПЗУ,за да се окаже на метка.
Когато при изпълнение на програмата,процесора се натъкне,да кажем на команда rjmp,тои взима от нея число и го прибавя към значението на брояча на адреси в ПЗУ...
Командата rcall се отличава от rjmp само по това ,че преди да измени текущото състояние на брояча,то се записва в ОЗУ.Нататък-прибавяме константа и преминаваме към изпълнение на програмата.
Команда ret в края на подпрограмата,зарежда в брояча адрес от ОЗУ,тогава се връщаме там от където сме тръгнали.това е всичко..
За да може командата rcall да се изпълни,ние трябва да инициализираме стека.това значи да поставим указател на стека.
Какво е това нещо-СТЕК?
Това е една хитра памет,в която данните се скриват както вещи в раница:един зад друг.Който се е опитвал да извади нещо от дъното на дълга раница ще разбере.За да се добере до нужния баит в стека,може да се направи само едно нещо-да се извади всичко навън.Такава организация на памета се нарича „FILO”- "First In - Last Out"/първи си влезнал,последен ще излезнеш/.
Още стека може да се сравни с градския реис в час-пик....
И така,за да почне да работи стека,ние трябва да кажем адрес в ОЗУ,който да стане „дъно на раницата”.Всеки следващ баит ще се съхранява в клетка на паметта с адрес по малък с 1 от предишния.Обикновенно ,указателя на стека се поставя на последния адрес в ОЗУ.Това се прави така:
ldi Temp,RamEnd ;зареди в Темп адрес на последната клетка в ОЗУ
out SPL,Temp ;въведи в SPL значение от Temp
RamEnd – това е константа,равна на значението на последния адрес в ОЗУ.тя се инициализира в фаила def.inc.
SPL – това е регъстър на указателя на стека, Stack Pointer Low.

Защо LOW?Работата е там че в микроконтролера 2313 разрядноста на адреса в ОЗУ не превишава 8 бит.Значи и указателя на стека трябва да е 8 битов.За неговото съхранение съответно се използва един 8битов регъстър.В някои други контролери обема на ОЗУ е по-голям,и за неговата адресация се използват два 8 битни регъстъра.
Съответно младшите разряди на указателя на стека в този случаи ще се съхраняват в регъстъра SPL,а старшите в-SPH (Stack Pointer High).Целта е унификация на кода за всички контролери,в 2313 в SPL са оставили на края буква L,защото никъкъв SPH в този контролер няма и не може да има.
Това беше лирическо отклонение което трябваше да преживеете...
И така ,даите да препишем нашата програма,да отделим паузите като отделна подпрограма/функция ако искаме/.
Командите за изход на регистрите в порта също ще изнесем в подпрограма на пауза:
Тя вече ще се повтаря без изменения.
.cseg
.org 0

ldi Temp,RamEnd ;инициализация стека
out SPL,Temp

ldi Temp,0b11111111 ;настройка на портовете
out DDRB,Temp

Begin: ldi Temp,0b00000001 ;изход на индикация-свети първия светодиод Урааа
rcall Delay ;извикване на подпрограмма Пауза

ldi Temp,0b00000010 ;изход на индикация-светна и втория
rcall Delay ;извикване на подпрограмма Пауза

ldi Temp,0b00000100
rcall Delay

ldi Temp,0b00001000
rcall Delay

ldi Temp,0b00010000
rcall Delay

ldi Temp,0b00100000
rcall Delay

ldi Temp,0b01000000
rcall Delay

ldi Temp,0b10000000
rcall Delay

rjmp Begin ;бегом на бегин!


;****************************************************
;подпрограма Пауза:

Delay: out PortB,Temp

ldi Temp1,0
ldi Temp2,0
ldi Temp3,10

Loop: dec Temp1
brne Loop

dec Temp2
brne Loop

dec Temp3
brne Loop

ret
Сега нашата програма стана много по компактна и даже всичките 8 светодиода мигат последователно един след друг.Но не си мислете че не може да стане още по малка ;)
Прикачам схемата ако има нещо неясно за всеки случаи, както и целия проект със сорс кода и симулацията в протеус7.7 като .рар
Прикачени файлове
snim Migalka1.1.jpg
MigalkaV1.rar
(14.62 KiB) 346 пъти
Gogo55
Администратор
 
Мнения: 496
Регистриран на: 30 Яну 2010 05:17

Re: ATMEL AVR микроконтролери - първи стъпки

Мнениеот Чефо » 28 Дек 2010 20:13

Ето какво прави и как изглежда мигалката в завършен вид без претенции за професионализъм.
http://www.youtube.com/watch?v=VSVPMiUe16Q
Прикачени файлове
P1040323.JPG
Чефо
интересуващ се
 
Мнения: 233
Регистриран на: 31 Яну 2010 12:00

Re: ATMEL AVR микроконтролери - първи стъпки

Мнениеот alek0630 » 20 Ное 2011 02:21

up :arrow: ;)
alek0630
новак
 
Мнения: 2
Регистриран на: 19 Дек 2010 12:25

Re: ATMEL AVR микроконтролери - първи стъпки

Мнениеот pulsar » 24 Дек 2012 08:53

Много полезно и разбираемо написано!
:arrow:
pulsar
новак
 
Мнения: 2
Регистриран на: 22 Дек 2012 19:33

Предишна

Назад към Книги и информация

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 1 госта

cron