Popularny post kermit Napisano Wrzesień 15, 2012 Popularny post Udostępnij Napisano Wrzesień 15, 2012 Lekcja1: wstęp i pierwszy programik poniższy artykuł jak już się pewnie domyślacie będzie dotyczył programowania mikrokontrolerów z rodziny AVR w języku assembler, czyli języku niskiego poziomu( takim języku który kompilator tłumaczy bezpośrednio na kod bajtowy).Zdecydowałem sie go napisać ,ponieważ chciałbym udowodnić, że jest to język naprawdę ciekawy i użyteczny a zarazem prosty -możliwe, że niektórzy czytający w tym momencie czują się delikatnie zmieszani, ponieważ często moża wyczytać na różncyh forach, że assembler jest językiem nielogicznym czy niezrozumiałym. W tym kursie postaram się udowodnić, że te negatywne opinie nt. Assemblera są co najmniej nie prawdziwe i po poznaniu jego prostych podstaw docenimy jego zalety. No więc po tym krótkim wstępie jako że, pisanie długich wywodów za dobrze mi nie idzie to wypisze punkt po punkcie jakie moim zdaniem są zalety oraz wady assemblera. Zalety: -prosta składnia, właściwie jedyne co musimy zapamiętać to tzw. Mnemoniki, czyli 2, 3 lub 4 literowy kod, oznaczjący konkrteną instrukcje dla naszego procesora, niektórym może wydawać się to awykonalne, ale w rzeczywistości gdy uświadomimi sobie, że mnemoniki są skrótem jakiejś konkretnej instrukcji (np. JMP - jump, CP - compare ) to robi się zdecydowanie łatwiej.Ogólnie mówiąc mamy zdecydowanie mniej róznych dziwnych znaczków, które występują w innych językach, a które często jest trudniej zapamiętać niz mnemoniki. -Teraz UWAGA ,bardzo ważna zaleta asemblera – ucząc się tego języka, tak naprawdę uczymy się nie tylko języka, ale też architektury samego mikrokotnrolera ,co w przyszłości może baaardzo nam sie przydać np. Przy programowaniu w innych językach czy nawet przy programowaniu innych mikrokontrolerów. -Assembler jest świetną podstawą do programowania uC(mikrokontrolera/-ów) w językach wysokiego poziomu, które najpierw są tłumaczone, przez kompilator właśnie do assemblera , dzieki znajomości tego języka łatwiej nam będzie przesiąść się na języki wysokiego poziomu, oraz łatwiej będzie o optymalizację i wykrywanie błędów w takim kodzie (np. C) -assembler daje naprawdę małą objętość kodu wynikowego, żeby zająć pamięć przynajmniej połowy np. Poczciwej atmegi32 muslielibyśmy się naprawdę okropnie namęczyć. -daje nam bardzo dobrą kontrole nad pracą uC, przez co możemy w nim pisać programy które sterują jakimś bardzo czasowo krytycznym procesem. Wypisałem te zalety które akurat przyszły mi do głowy, zapewne można by ich jeszcze trochę wypisać, ale ich odkrywanie pozostawie wam 🙂 No i dla równowagi wady a właściwie jedna, ale dosyć spora wada: -pisanie bardziej skomplikowanych programów zajmuje zdecydowanie więcej czasu, niż w językach wysokopoziomowych nastała pora, aby przejść dalej, a mianowicie w czym będziemy pisali : -Do pisania programów w asm wybrałem dosyć juz leciwe, ale proste w obsłudze i przejrzyste AVR studio 4, ponieważ do pisania naszych programów nic bardziej skomplikowanego nie jest nam potrzebne, a następne wersje AVR studio mają całą mase niepotrzebnych bajerów które właśćiwie powoduja głównie spowolnienie komputera i zajmują kilkanaście razy więcej miejsca na dysku. A co będzimy programowali?: -programowali będziemy jeden z najpopularniejszych mikrokontrolerów z rodziny AVR, a mianowicie Atmege32 zamontowaną na klasycznej płytce stykowej, wybrałem takie rozwiązanie z tego względu, że w odróżnieniu od płytek rozwojowych jest ono dosyć tanie i jeśli ktos nie posaida jeszcze płytki stykowej to raczej nie powinienn mieć problemu z nabyciem takowej, a taka płytka przyda nam się napewno jeszcze wiele razy. Czym programujemy: -ja będe używał programatora AVR isp mkII, ale jeśli ktos posiada inny programator też nie powinienn mieć problemu. Ok, to by było na tyle, pora wziąść się do roboty : pierwszy układ który zmontujemy będzie chyba najprostszy z możliwych, czyli zasilanie, programator oraz dioda podłączona anodą do portu PC0, a katodą przez rezystor do minusa zasilania Gdy już zmontujemy układ według powyższego schematu pora przystąpić do pisania programu, którego zadaniem będzie zapalenie naszej diody LED, myślę, że uruchomienie avr studio jest na tyle banalne i było już wielokrotnie opisywane co gdzie i jak, że mogę pominąć tą część. Przystępujemy więc do pisania programu ,pierwsze co wpisujemy to 5 dyrektyw dla komilatora które będą występowały praktycznie w każdym pisanym przez nas programie asm: .nolist .include "m32def.inc" .list .cseg .org 0 oznaczją one : .nolist – informuje kompilator aby nie kompilował następujących po niej wierszy .include "m32def.inc" – jest to plik który zawiera definicje nazw rejestrów ,co ułatwia bardzo pisanie programów, bo nie musimy odnosić się do fizycznych adresów rejestrów, tylko możemy używać ich nazw (czyli np. Zamiast pisać 0x14, możemy napisać DDRC) .list –informuje kompilator, aby kompilował następujące po tej dyrektywie wiersze. .cseg – czyli skrót od "code segment", informuje kompilator ,że będziemy pisali w segmencie programu. .org 0 – nakazuje, aby program był umieszczony w pamięci począwszy od adresu zerowego. No więc wiemy już co oznaczją dyrektywy teraz pora na program właśćiwy który będzie wyglądał tak: wersja I: .nolist .include "m32def.inc" .list .cseg .org 0 sbi DDRC, 0 //ustawiamy pin 0 portu C jako wyjściowy sbi PORTC, 0 //ustawiamy stan wysoki na pinie 0 portu C najprostszy z możliwych programów, czyli ustawienie bitu w rejestrze I/O* DDRC(data direction register) oraz PORTC, pierwszą instrukcją ustawiamy PORTC 0 jako port wyjściowy ,drugą ustawiamy go w stan wysoki ,aby nasza dioda mogła się zapalić.Następne kroki to : klikamy przycisk F7 na klawiaturze ,aby skomilować program-> wybieramy tools na górze okna programu-> w rozwiniętym okienku wybieramy "program avr"-> klikamy "connect-> w okienku które sie nam pojawi wybieramy nasz programator-> gdy połączymy się z programatorem,wyskoczy nam okno dialogowe w którym wchodzimy w zakładkę program-> w podpunkcie "flash" wybieramy ścieżke do naszego pliku z programem(rozszerzenie .hex) -> klikamy "program" Co dokładnie oznaczają instrukcje, oraz jaka jest ich składnia?: sbi – "set bit in I/O" -czyli ustaw bit w rejestrze "wejśćia/wyjścia"(którym ,czyli np. DDRC , PORTC,lub PINC ) ,"o numerze"(rejestry są ośmiobitowe ,więc wybieramy z przedziału 0-7, w zależności który pin danego portu chcemy ustawić) przeciwieństwem instrukcji "sbi" jest instrukcja "cbi" która zeruje dany pin. Asembler jest językiem w którym wielkość liter nie ma znaczenia, więc instrukcja sbi = SBI, tak samo jest z nazwami rejestrów ddrc = DDRC Wersja II: teraz pora na drugą wersje programu który rówież zapali naszą diodę LED: .nolist .include "m32def.inc" .list .cseg .org 0 ldi R16,0b00000001 out DDRC, R16 out PORTC, R16 najpierw ładujemy stałą 0b00000001 do jednego z rejestrów ogólnego przeznaczenia* w tym wypadku R16 ,następnie zawartość rejestru R16 ładujemy do rejestrów I/O DDRC(tym sposobem w rejestrze DDRC bit nr0 został ustawiony, czyli linia ta została ustawiona jako wyjściowa), następnie tą samą stałą z rejestru R16 ładujemy do rejestru PORTC(sytuacja analogiczna jak z rejestrem DDRC ,tyle że tym razem ustawiamy bit w PORTC, co skutkuje ustawieniem stanu wysokiego na linii 0 portu C) i tu jeszcze jedna sprawa, użyłem w tym wypadku zapisu binarnego stałej ładowanej do rejestru ,aby było widać dokładnie który bit ustawiamy, ale równie dobrze moglibyśmi użyć zapisu szesnastkowego, wyglądało by to tak: .nolist .include "m32def.inc" .list .cseg .org 0 <code/> ldi R16,0x01 out DDRC, R16 out PORTC, R16 lub mojego ulubionego zapisu, wg mnie najwygodzniejszego: .nolist .include "m32def.inc" .list .cseg .org 0 ldi R16, (1<<PINC0) out DDRC, R16 out PORTC, R16 znaczenie poszczególnych instrukcji: ldi – "load immediate" -[załaduj bezpośrednio] "do rejestru ogólnego przeznaczenia" , "stałą K" out – "out port"- [załaduj] "do rejestru" "z rejestru" *od dłuższego czasu używam już słowa rejestr(ogólnego przeznaczenia , wejścia/wyjśćia) i może niektórzy którzy dopiero zaczynją zabawę z mikrokontrolerami mogą nie wiedzieć czym są te rejestry otóż już wyjaśniam: rejestry są to niewielkie komórki pamięci w przypadku rejestrów systemowych(np. Używane przez nas DDRC, PORTC itp.) słuzą one sterowania konkretnymi peryferiami naszego mikrokontrolera np. W przypadku rejestru DDRn ustawienie w nim bitów powoduje ustawienie linii danego portu jako wyjśćie, a zerowanie jako wejśćie . Rejestry ogólnego przeznaczenia(od R16 do R31) są do użytku programisty, można w nich przechowywać, zmienne lub stałe które wykorzystywane będą w programie. Ze względu ,że nasze mikrokontrolery AVR są 8-bitowe to też wszystkie rejestry w nich są również 8-bitowe co oznacza, że największą wartość dziesiętną jaką możemy zaladować do pojedyńczego rejestru to 255. komentarze: wpisać komentarz w języki assembler możemy na 3 soposoby: ";" - znak średnika pozwala nam na napisanie komentarza do końca wiersz "//" -a analogicznie jak w przypadku średnika "/*"możemy pisać komentarz aż do odwołania znakiem "*/" . Zakończenie: Ok więc na tym zakończymy pierwszą część kursu, jeśli się on spodoba opublikuje następne jego części .Prosze pisać co można by jeszcze poprawić, dopisać itp. __________ Komentarz dodany przez: Treker Proszę poprawić interpunkcję. Spacje stawiamy po, a nie przed znakiem interpunkcyjnym. 3 Link do komentarza Share on other sites More sharing options...
Mars Wrzesień 16, 2012 Udostępnij Wrzesień 16, 2012 wziąść teraz pora na drugą wersje programu który będzie który rówież zapali diodę naszą diodę LED Ze względu ,że mikrokontrolery nasze mikrokontrolery AVR są 8-bitowe ldi R20,0x01 out DDRC, R16 out PORTC, R16 Nie bardzo rozumiem ten fragment. Wrzucamy do rejestru R20 jakąś wartość i co z nią? Potem odwołujemy się do R16. Jak to się ma do R20? Link do komentarza Share on other sites More sharing options...
Harnas Wrzesień 16, 2012 Udostępnij Wrzesień 16, 2012 Zapewne jest to błąd. Zamiast R20 powinno być R16. Link do komentarza Share on other sites More sharing options...
kermit Wrzesień 16, 2012 Autor tematu Udostępnij Wrzesień 16, 2012 Już poprawione przepraszam za te błędy, wkradły się one do artykułu z powodu zmęczenia. 😉 Link do komentarza Share on other sites More sharing options...
Polecacz 101 Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Produkcja i montaż PCB - wybierz sprawdzone PCBWay! • Darmowe płytki dla studentów i projektów non-profit • Tylko 5$ za 10 prototypów PCB w 24 godziny • Usługa projektowania PCB na zlecenie • Montaż PCB od 30$ + bezpłatna dostawa i szablony • Darmowe narzędzie do podglądu plików Gerber Zobacz również » Film z fabryki PCBWay
BlackJack Wrzesień 16, 2012 Udostępnij Wrzesień 16, 2012 -Teraz UWAGA ,bardzo ważna zaleta asemblera – ucząc się tego języka, tak naprawdę uczymy się nie tylko języka, ale też architektury samego mikrokotnrolera ,co w przyszłości może baaardzo nam sie przydać np. Przy programowaniu w innych językach czy nawet przy programowaniu innych mikrokontrolerów. Od której należałoby zacząć. Bez przedstawienia architektury danego procesora, nauka ASMa mija się z celem. Same rzucenie paroma przykładami i troszką instrukcji to za mało. ASM wbrew pozorom nie jest taż taki prosty, dla tego powstały języki wysokiego poziomu, O ile zapamiętanie samych instrukcji nie jest jakim niesamowitym wyzwaniem, to wykonywanie operacji złożonych już tak, szczególnie obliczeniowo. No i trzymaj się jakiś zasad pisania. Jak już przyjołeś że stałą do rejestru ładujesz takim sposobem: LDI R16, 0b00000001 to potem nie rób tak LDI R16, 0x01 bez wyjaśnienia tych zapisów, bo początkujący się załamią po pierwszych 2 listingach. Ogólnie wziąłeś sobie na tapetę, bardzo, ale to bardzo trudny do zrobienia dobrze temat. Link do komentarza Share on other sites More sharing options...
Mars Wrzesień 16, 2012 Udostępnij Wrzesień 16, 2012 i tu jeszcze jedna sprawa, użyłem w tym wypadku zapisu binarnego stałej ładowanej do rejestru ,aby było widać dokładnie który bit ustawiamy, ale równie dobrze moglibyśmi użyć zapisu szesnastkowego, wyglądało by to tak: Więc chyba wszystko wyjaśnione? 😉 kermit, poprawisz w końcu te R20? ; D Link do komentarza Share on other sites More sharing options...
BlackJack Wrzesień 16, 2012 Udostępnij Wrzesień 16, 2012 UP A to oddaje honor, nie doczytałem. Link do komentarza Share on other sites More sharing options...
wojakin Sierpień 15, 2016 Udostępnij Sierpień 15, 2016 Witam. Mam pytanie dlaczego używa się rejestrów od r16 wzwyż a nie od r0? Pozdrawiam. Link do komentarza Share on other sites More sharing options...
wn2001 Sierpień 16, 2016 Udostępnij Sierpień 16, 2016 wojakin, Rejestry ogólnego przeznaczenia(od R16 do R31) są do użytku programisty, można w nich przechowywać, zmienne lub stałe które wykorzystywane będą w programie. Link do komentarza Share on other sites More sharing options...
Harnas Sierpień 16, 2016 Udostępnij Sierpień 16, 2016 wn2001, R0 do R15 też, tylko że z tego co dobrze pamiętam niektóre instrukcje m.in. LDI są możliwe tylko na R16-R31 Link do komentarza Share on other sites More sharing options...
wn2001 Sierpień 16, 2016 Udostępnij Sierpień 16, 2016 Harnas, a to przepraszam. Moja wiedza na temat ASM jest znikoma, myślałem jedynie, że mój poprzednik przeoczył ten fragment artykułu, stąd cytat 🙂 Link do komentarza Share on other sites More sharing options...
wojakin Sierpień 28, 2016 Udostępnij Sierpień 28, 2016 Dziękuję za informacje 🙂. Pozdrawiam. Edit: Mam jeszcze pytanie przekazuje do funkcji SPIInt napisanej w asm wartość 8-bitową jako argument z pliku napisanego w c. Z tego co rozumiem adres tej wartości powinien wylądować w rejestrze X ale tak się nie dzieje. Co robię źle? #include <avr/io.h> extern void init (void); extern void SPIInt (uint8_t edata); int main (void) { init(); SPIInt(0xAB); while(1){ } return 0; } #define __SFR_OFFSET 0 #include <avr/io.h> .global init .global SPIInt init: sbi DDRD, 0 ; Set SPI out pin ldi r16,(1<<PB4)|(1<<PB5)|(1<<PB7) out DDRB,r16 ; Enable SPI, enable SPI Interrupt, set Master Mode and set clock rate fck/16 ldi r16,(1<<SPIE)|(1<<SPE)|(1<<MSTR)|(1<<SPR0) out SPCR,r16 ret SPIInt: ld r17,x cpi r17,0xAB breq on reti on: sbi PORTD,0 reti Edit 2: Znalazłem że kompilator wartość podaną jako argument wkłada do rejestru r24. Dla argumentów zawsze ten rejestr obowiązuje? Link do komentarza Share on other sites More sharing options...
Anek40 Listopad 3, 2019 Udostępnij Listopad 3, 2019 Witam Jak wyglądał by ten kod C w j.ASM kwarc 16 MHz ,Attiny 2313A -------------------------------------------------------------------------------------- #include <avr/io.h> #include <util/delay.h> main() { DDRB = (1<<PB3)|(1<<PB4); PORTB|=(1<<PB3); while(1) { PORTB ^= (1<<PB3)|(1<<PB4); _delay_us(128000000); } } Link do komentarza Share on other sites More sharing options...
Treker (Damian Szymański) Listopad 4, 2019 Udostępnij Listopad 4, 2019 @Anek40 witam na forum 🙂 Na czym dokładnie utknąłeś, próbowałeś zdziałać coś samodzielnie w tej kwestii? PS Kody programów należy umieszczać za pomocą odpowiedniego narzędzia dostępnego w edytorze (przycisk "Wstaw kod"). Programy są wtedy prezentowane w czytelny sposób, a ich składania jest kolorowana. Tym razem poprawiłem to za Ciebie, ale pamiętaj o tej opcji w przyszłości. Z góry dziękuję za zrozumienie i pomoc w utrzymaniu porządku 😉 Link do komentarza Share on other sites More sharing options...
Anek40 Listopad 4, 2019 Udostępnij Listopad 4, 2019 Jak w ASM napisać to: PORTB ^= (1<<PB3)|(1<<PB4); _delay_us(128000000); Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Bądź aktywny - zaloguj się lub utwórz konto!
Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony
Utwórz konto w ~20 sekund!
Zarejestruj nowe konto, to proste!
Zarejestruj się »Zaloguj się
Posiadasz własne konto? Użyj go!
Zaloguj się »