Spisu treści:

Samouczek asemblera AVR 6: 3 kroki
Samouczek asemblera AVR 6: 3 kroki

Wideo: Samouczek asemblera AVR 6: 3 kroki

Wideo: Samouczek asemblera AVR 6: 3 kroki
Wideo: ЯЗЫК АССЕМБЛЕРА за 3 МИНУТЫ 2024, Listopad
Anonim
Samouczek asemblera AVR 6
Samouczek asemblera AVR 6

Witamy w samouczku 6!

Dzisiejszy samouczek będzie krótki, w którym opracujemy prostą metodę przesyłania danych między jednym atmega328p a drugim przy użyciu dwóch łączących je portów. Następnie weźmiemy kostkę do gry z samouczka 4 i Register Analyzer z samouczka 5, połączymy je ze sobą i użyjemy naszej metody, aby przekazać wynik rzutu kostką z rolki do analizatora. Następnie wydrukujemy rolkę w formacie binarnym, używając diod LED, które skonstruowaliśmy dla analizatora w samouczku 5. Gdy już to zadziała, będziemy mogli skonstruować kolejny element naszego ogólnego projektu w następnym samouczku.

W tym samouczku będziesz potrzebować:

  1. Twoja płyta prototypowa
  2. Twoja rolka do gry w kości z samouczka 4
  3. Twój analizator rejestrów z samouczka 5
  4. Dwa przewody łączące
  5. Kopia pełnego arkusza danych (wersja 2014):

    www.atmel.com/images/Atmel-8271-8-bit-AVR-M…

  6. Kopia instrukcji zestawu instrukcji (wersja 2014):

    www.atmel.com/images/atmel-0856-avr-instruc…

Oto link do pełnej kolekcji moich samouczków asemblera AVR:

Krok 1: Jak możemy skłonić dwa mikrokontrolery do komunikowania się ze sobą?

Jak sprawić, by dwa mikrokontrolery porozmawiały ze sobą?
Jak sprawić, by dwa mikrokontrolery porozmawiały ze sobą?

Ponieważ zaczynamy rozszerzać nasz projekt, aby nasz pojedynczy produkt końcowy składał się z kolekcji mniejszych części, będziemy potrzebować więcej pinów niż może dostarczyć pojedynczy Atmega328P. Dlatego zamierzamy wykonać każdą część całego projektu na osobnym mikrokontrolerze, a następnie udostępnić dane między nimi. Problem, który musimy rozwiązać, polega na tym, jak wymyślić prosty sposób, aby kontrolery komunikowały się ze sobą i przesyłały między sobą dane? Cóż, jedną rzeczą w tych kontrolerach jest to, że każdy z nich wykonuje 16 milionów instrukcji na sekundę. Jest to bardzo dokładny czas, więc możemy wykorzystać ten czas do przesyłania danych. Jeśli użyjemy opóźnień milisekundowych do utworzenia danych, to tak naprawdę nie musimy być aż tak dokładni, ponieważ procesor wykonuje 16 000 instrukcji w ciągu jednej milisekundy. Innymi słowy, milisekunda to dla procesora wieczność. Spróbujmy więc z rzutami kostką. Chcę przesłać wynik rzutu kostką z chipa rolki kości do chipa analizatora. Załóżmy, że stoisz po drugiej stronie ulicy i chcę ci zasygnalizować wynik mojego rzutu kostką. Jedyne, co mógłbym zrobić, gdybyśmy oboje mieli zegarek, to włączyć latarkę, a kiedy jesteś gotowy na odebranie moich danych, włączasz latarkę i oboje uruchamiamy nasze zegary. Potem włączam latarkę dokładnie przez milisekundy, gdy rzuca się kostką, a potem wyłączam. Więc gdybym wykręcił 12, utrzymywałbym światło przez 12 milisekund. Teraz problem z powyższym polega na tym, że dla ciebie i dla mnie nie ma możliwości, abyśmy byli w stanie zmierzyć czas wystarczająco dokładnie, aby odróżnić 5 milisekund od 12 milisekundy. Ale co z tym: Załóżmy, że postanowiliśmy, że będę mieć włączone światło przez rok dla każdej liczby na kostce? Wtedy, jeśli wyrzucę 12, będę świecić na ciebie przez 12 lat i myślę, że zgodzisz się, że nie ma możliwości, że popełnisz błąd w prawidłowym ustaleniu liczby? Możesz zrobić sobie przerwę i pograć w baseball, możesz nawet pograć w kości w Vegas przez 6 miesięcy, o ile w pewnym momencie w ciągu roku spojrzałeś na drugą stronę ulicy, aby sprawdzić, czy świeci się światło, nie przegapisz liczenia. Cóż, dokładnie to robimy dla mikrokontrolerów! Jedna milisekunda dla procesora to jak rok. Jeśli więc włączę sygnał na 12 milisekund, to prawie nie ma szans, że inny mikrokontroler pomyli go na 10 czy 11, bez względu na to, jakie przerwania i co w międzyczasie się nie wydarzy. Dla mikrokontrolerów milisekunda to wieczność. Oto, co zrobimy. Najpierw wybierzemy dwa porty na kontrolerze, które będą naszymi portami komunikacyjnymi. Użyję PD6 do odbioru danych (możemy nazwać go Rx, jeśli chcemy) i wybiorę PD7 do przesyłania danych (możemy go nazwać Tx, jeśli chcemy). Chip analizatora będzie okresowo sprawdzał pin Rx i jeśli zobaczy sygnał, przejdzie do „podprogramu komunikacyjnego”, a następnie prześle sygnał zwrotny do rolki, mówiąc, że jest gotowy do odbioru. Oboje rozpoczną odliczanie czasu, a kostka do gry prześle sygnał (tj. 5V) przez milisekundę na liczbę na kostce. Więc jeśli rolka byłaby podwójną szóstką lub 12, wtedy kostka do gry ustawiłaby PD7 na 5V na 12 milisekund, a następnie ustawiłaby ją z powrotem na 0V. Analizator będzie sprawdzał swój pin PD6 co milisekundę, licząc za każdym razem, a kiedy wróci do 0V, wyświetla wynikowy numer na wyświetlaczu analizatora, pokazując dwanaście binarnie na diodach LED. Taki jest plan. Zobaczmy, czy uda nam się to zaimplementować.

Krok 2: Podprogramy komunikacyjne

Pierwszą rzeczą, którą musimy zrobić, to połączyć dwa kontrolery. Więc weź przewód z PD6 na jednym i podłącz go do PD7 na drugim i na odwrót. Następnie zainicjuj je, ustawiając PD7 na WYJŚCIE na obu i PD6 na WEJŚCIE na obu. Na koniec ustaw je wszystkie na 0V. W szczególności dodaj następujące elementy do sekcji Init lub Reset kodu na każdym mikrokontrolerze:

sbi DDRD, 7; PD7 ustawiony na wyjście

cbi Port D, 7; PD7 początkowo 0V cbi DDRD, 6; PD6 ustawiony na wejście cbi PortD, 6; PD6 początkowo 0V clr total; suma na kostkach początkowo 0

Teraz skonfigurujmy podprogram komunikacyjny na chipie kości do gry. Najpierw zdefiniuj nową zmienną na górze o nazwie „total”, która będzie przechowywać całkowitą liczbę wyrzuconą na parę kostek i zainicjować ją na zero.

Następnie napisz podprogram do komunikacji z analizatorem:

porozumieć się:

cbi Port D, 7 sbi Port D, 7; Wyślij gotowy sygnał oczekiwania: sbic PinD, 6; odczytaj PinD i pomiń, jeśli 0V rjmp czekaj opóźnienie 8; opóźnienie synchronizacji (znalazłem to eksperymentalnie) wyślij: dec całkowite opóźnienie 2; opóźnienie dla każdej liczby matryc cpi total, 0; 0 tutaj oznacza "całkowitą" liczbę wysłanych opóźnień breq PC+2 rjmp send cbi PortD, 7; PD7 do 0V clr łącznie; zresetuj sumę kości do 0 ret

W analizatorze do podprogramu komunikacji dodajemy wywołanie wywołania z procedury głównej:

analizator CLR; przygotuj się na nowy numer

sbic PinD, 6; sprawdź PD6 dla sygnału 5V rcall; jeśli 5V przejdź do komunikacji z analizatorem mov, suma; wyjście do analizatora wyświetla analizator wywołania

a następnie napisz podprogram komunikacji w następujący sposób:

porozumieć się:

clr suma; zresetuj sumę do 0 opóźnienie 10; opóźnienie pozbycia się odbić sbi PortD, 7; ustaw PB7 na 5V, aby otrzymać sygnał gotowości: opóźnienie 2; czekaj na następną liczbę inc total; przyrost sumy sbic PinD, 6; jeśli PD6 wróci do 0V skończymy odbiór rjmp; w przeciwnym razie wykonaj kopię zapasową w pętli, aby uzyskać więcej danych cbi PortD, 7; zresetuj PD7 po zakończeniu ret

Proszę bardzo! Teraz każdy mikrokontroler jest skonfigurowany do przekazywania wyniku rzutu kostką, a następnie wyświetlania go na analizatorze.

Znacznie wydajniejszy sposób komunikacji zaimplementujemy później, gdy będziemy musieli przenieść zawartość rejestru między kontrolerami, a nie tylko rzut kostką. W takim przypadku nadal będziemy używać tylko dwóch przewodów łączących je, ale użyjemy 1, 1 w znaczeniu „rozpocznij transmisję”; 0, 1 oznacza „1”; 1, 0 oznacza „0”; i wreszcie 0, 0 oznacza „zakończ transmisję”.

Ćwiczenie 1: Sprawdź, czy możesz wdrożyć lepszą metodę i użyj jej do przeniesienia rzutu kostką jako 8-bitowej liczby binarnej.

Dołączę filmik, który pokazuje mój w działaniu.

Krok 3: Wniosek

Wniosek
Wniosek

Załączam pełny kod w celach informacyjnych. Nie jest tak czysty i uporządkowany, jak bym chciał, ale posprzątam go, gdy będziemy go rozwijać w przyszłych samouczkach.

Od teraz będę tylko załączał pliki zawierające kod, zamiast wpisywać go tutaj. Po prostu wpiszemy sekcje, które chcemy omówić.

To był krótki samouczek, w którym wymyśliliśmy prostą metodę informowania naszego mikrokontrolera analizatora, jaki jest wynik naszego rzutu kostką z naszego mikrokontrolera z rolkami, przy użyciu tylko dwóch portów.

Ćwiczenie 2: Zamiast używać sygnału gotowości do pokazania, kiedy kostka jest gotowa do nadawania, a drugiego, gdy analizator jest gotowy do odbioru, użyj „zewnętrznego przerwania” zwanego „przerwaniem zmiany kołka”. Piny atmega328p mogą być używane w ten sposób, dlatego mają obok siebie na schemacie pinów od PCINT0 do PCINT23. Możesz zaimplementować to jako przerwanie w podobny sposób, jak zrobiliśmy to z przerwaniem przepełnienia timera. W tym przypadku „obsługa” przerwania będzie podprogramem, który komunikuje się z kostką do gry. W ten sposób nie musisz faktycznie wywoływać podprogramu komunikacyjnego z main: pojawi się on tam za każdym razem, gdy pojawi się przerwanie pochodzące ze zmiany stanu na tym pinie.

Ćwiczenie 3: Znacznie lepszym sposobem komunikacji i przesyłania danych między jednym mikrokontrolerem a zbiorem innych jest użycie wbudowanego 2-przewodowego interfejsu szeregowego na samym mikrokontrolerze. Spróbuj przeczytać sekcję 22 arkusza danych i zobacz, czy możesz dowiedzieć się, jak to wdrożyć.

Będziemy używać tych bardziej skomplikowanych technik w przyszłości, gdy dodamy kolejne kontrolery.

To, że wszystko, co zrobiliśmy z naszym analizatorem, to pobranie całości rzutu kostką, a następnie wydrukowanie go binarnie za pomocą diod LED, nie jest ważne. Faktem jest, że teraz nasz analizator „wie”, czym jest rzut kostką i może go odpowiednio wykorzystać.

W następnym samouczku zmienimy przeznaczenie naszego „analizatora”, wprowadzając kilka dodatkowych elementów obwodów i wykorzystując rzut kostką w ciekawszy sposób.

Do następnego razu…

Zalecana: