Samouczek PIC - od rejestrów do przerwań

Wypróbuj Nasz Instrument Do Eliminowania Problemów





Zanim przejdziemy do najdrobniejszych szczegółów programowania PIC, należałoby najpierw nauczyć się kilku dobrych metod programowania.

Zrozumienie rejestrów

Na początek przypuśćmy, że wpisujesz (średnik) w dowolnym punkcie programu, wszystko, co nastąpi po tym średniku, zostanie zignorowane przez kompilator, dopóki oczywiście karetka nie wróci na tę pozycję.



Powyższa funkcja umożliwia nam dodawanie komentarzy lub uwag w taki sposób, że nie stają się one częścią programu, a jednocześnie ułatwia nam identyfikację programu za pomocą komentarzy obok niego. Umieszczanie komentarzy jest zalecaną praktyką podczas programowania dowolnego układu scalonego.

Kolejną ważną rzeczą w kursie jest przypisanie nazw różnym stałym (nauczysz się ich później szczegółowo). To aso ułatwia zrozumienie, do czego jest napisane lub w odniesieniu do zaangażowanych wartości, zamiast mylić się z zawartymi liczbami.



Powyższe należy wykonać w postaci rzeczywistych nazw do natychmiastowego rozpoznania, na przykład COUNT. Należy zauważyć, że tutaj wszystkie duże litery są używane, aby wyróżnić je, a także wskazać, że jest to wartość stała.


Jak widać, powyższe jest wykonane w formie pudełka wykonanego ze średników, dzięki czemu wygląda czysto. Dodatkowo spróbuj udokumentować program również na papierze, ta praktyka pomoże zrozumieć rzeczy w sposób krokowy.

2. Rejestry.

Rejestr w PIC to obszar, który akceptuje pisemne dane, a także umożliwia odczyt z niego. Możesz porównać to do kartki papieru, na której możesz wizualizować zawartość i dodawać ją, pisząc po niej.

Poniższy rysunek przedstawia typową mapę pliku rejestru osadzoną w PIC16F84. Format nie jest czymś, co jest faktycznie ustawione w PIC, służy po prostu do wskazania, jak bity mogą być rozmieszczone w chipie i zrozumienia kilku związanych z tym poleceń.

Widać, że jest on zasadniczo podzielony na Bank 0 i Bank 1. Bank 1 jest odpowiedzialny za kontrolowanie faktycznej pracy PIC, na przykład przekazuje do PIC, które bity w Porcie A są przypisane jako wejścia, a które są jako wyjścia.

Bank 2 służy tylko do manipulowania informacjami.

Zrozummy to na następującym przykładzie:

Załóżmy, że chcemy przypisać jeden bit na wysokim PortA. W tym celu musielibyśmy najpierw przejść do banku 1, aby ustawić określony bit lub pin w porcie A w postaci wyjścia. Następnie wracamy do banku 0 i dostarczamy logikę 1 (bit 1) do tego konkretnego pinu.

Najpopularniejsze rejestry, których chcielibyśmy używać w Banku 1 to STATUS, TRISA i TRISB.

STATUS pomaga nam wrócić do banku 0, TRISA pozwala nam wybrać, które piny w porcie A są wyjściami, a które mogą być wejściami, podczas gdy TRISB ułatwia wybór między pinem wyjściowym i wejściowym w porcie B. Rejestr SELECT w BANKU 0 pozwala użytkownikowi przerzucić do banku 1.

Podsumujmy całą koncepcję następującym opisem:

STATUS:

Aby przejść z banku 0 do banku 1, wydajemy polecenie rejestrowi STATUS. Jest to realizowane poprzez ustawienie bitu # 5 rejestru STATUS na 1. Aby wrócić do banku 0, przypisujemy bit 5 rejestru STATUS do 0. Rejestr STATUS jest umieszczony pod adresem 03h, tutaj h oznacza tat numer może być w formacie szesnastkowym.

TRISA i TRISB:

Znajdują się one odpowiednio pod adresami 85h i 86h. Aby zaprogramować pin jako wyjście lub wejście, po prostu dostarczamy zero lub jedynkę do określonego bitu w rejestrze. Teraz można to zrobić na dwa sposoby, binarnie lub szesnastkowo. W przypadku, gdy ktoś nie jest w stanie przeliczyć parametru, może skorzystać z kalkulatora naukowego w celu wprowadzenia wartości.

Teraz mamy 5 pinów w Porcie A, co odpowiada 5 pinom. Jeśli zamierzamy naprawić jeden z pinów jako wejścia, dostarczamy „1” do konkretnego bitu.

Gdybyśmy chcieli przypisać jeden z pinów jako wyjścia, ustawilibyśmy określony pin na „0”. Bity są wspomagane dokładnością odpowiadającą bitom, lub dokładniej bit 0 to RA0, bit 1 to RA1, bit 2 = RA2 i tak dalej. Zrozummy to w ten sposób:

Załóżmy, że chcesz naprawić RA0, RA3 i RA4 jako wyjścia, podczas gdy RA1 / RA2 jako i / ps, zrobiłbyś to, wysyłając 00110 (06h). Sprawdź, czy bit 0 jest skierowany w prawo, jak pokazano tutaj:

Port A Pin RA4 RA3 RA2 RA1 RA0

Numer bitu 4 3 2 1 0

Binarny 0 0 1 1 0

To samo dotyczy TRISB.

PORTA i PORTB

Aby zapewnić wysoki poziom jednego z pinów wyjściowych, po prostu oferujemy „1” dla odpowiedniego bitu w naszym rejestrze PORTA lub PORTB. Identyczna procedura może być zastosowana również dla rejestrów TRISA i TRISB. Zanim przejdziemy do naszego pierwszego przykładowego kodowania, po prostu zrozummy zbiór większej liczby rejestrów, a mianowicie: w i f.

W i F.

Rejestr W jest zwykłym rejestrem, który umożliwia przypisanie dowolnej wybranej wartości. Gdy tylko przypiszesz jasność do W, możesz kontynuować, dodając ją do innej wartości lub po prostu ją przesunąć. Po przypisaniu innej wartości szczegóły zostaną po prostu nadpisane na W.

Rejestr F przekazuje swoją pisemną sprawę do rejestru. Wymagalibyśmy, aby ten rejestr F przypisywał wartość do rejestru, może znajdować się nad rejestrami STATUS lub TRISA, ponieważ nie pozwolą nam one na umieszczenie wartości bezpośrednio nad nimi. Przykładowy program

Przeanalizujmy następujący przykładowy kod, który pokaże nam, jak powyższa instrukcja jest zaimplementowana, a także będzie świadkiem kilku instrukcji w kursie.

Zacznijmy od naprawienia portu A, jak omówiono powyżej.

W tym celu musimy przejść z banku 0 do banku 1, odbywa się to poprzez ustawienie rejestru STATUS znajdującego się pod adresem 03h, bit 5 do 1.

BSF 03h, 5

BSF oznacza zestaw bitów F. Po tej instrukcji używamy dwóch liczb - 03h, która jest adresem rejestru STATUS, oraz liczby 5, która odpowiada numerowi bitu.

Tak więc mówimy „Ustaw bit 5 w adresie 03h na 1”.

Jesteśmy teraz w banku 1.

MOVLW 00110b

Wstawiamy wartość binarną 00110 (litera b oznacza, że ​​liczba jest binarna) do naszego rejestru ogólnego przeznaczenia W. Mógłbym oczywiście zrobić to w postaci szesnastkowej, w takim przypadku nasza instrukcja wyglądałaby następująco:

MOVLW 06h

Albo działa. MOVLW oznacza „Przenieś wartość literalną do W”, co w języku angielskim oznacza umieszczenie wartości, która następuje bezpośrednio w rejestrze W.

Teraz musimy umieścić tę wartość w naszym rejestrze TRISA, aby skonfigurować port:

MOVWF 85h

Ta instrukcja wskazuje „Przenieś zawartość W do następującego adresu rejestru”, w tym przypadku adres odnosi się do TRISA.

Nasz rejestr TRISA w tym miejscu nosi cyfrę 00110 lub jest przedstawiony graficznie:

Port A Pin RA4 RA3 RA2 RA1 RA0

Binarny 0 0 1 1 0

Wejście / wyjście O O I I O

Więc teraz mamy nasze piny Port A, musimy wrócić do banku 0, aby dostosować jedną z informacji.

BCF 03h, 5

Ta instrukcja wykonuje odwrotność BSF. Oznacza to „Bit Clear F”. Para liczb, które odpowiadają, to adres rejestru, tutaj rejestr STATUS, a także liczba bitów, w tym przypadku bit pięć. To, co dokładnie zakończyliśmy obecnie, to zdefiniowany bit pięć na naszym

Rejestr STATUS na 0

W tym momencie wróciliśmy do banku 0.
Poniżej znajduje się kod w jednym bloku:

BSF 03h, 5 Przejdź do banku 1
MOVLW 06h Umieść 00110 w W.
MOVWF 85h Przenieś 00110 na TRISA
BCF 03h, 5 Wróć do banku 0

W ostatniej instrukcji potwierdziliśmy sposób ustalenia pinów portu IO na PIC, aby były prawdopodobnie wejściowe lub wyjściowe.

Dzięki temu kursowi pomogę Ci w wysyłaniu danych do portów.

Wysyłanie danych do portów

W kolejnym samouczku zamierzamy zakończyć, włączając i wyłączając diodę LED, która składa się z pełnego opisu programu i prostego schematu obwodu, abyś mógł zobaczyć, jak PIC wykonuje dokładnie to, czego oczekujemy.

Nie próbuj składać i programować swojego PIC z poniższymi wynikami, ponieważ są one tylko ilustracjami. Początkowo ustawimy Port A bit 2 jako wyjście:

Można to rozpoznać po poprzedniej instrukcji. Jedyną różnicą może być: Naprawiliśmy każdy bit pinów na A jako wyjście, dostarczając 0h do rejestru trójstanowego. Więc co teraz musi zrobić, to włączyć diodę LED.

Osiągamy to, ustawiając jeden z pinów (ten z podłączoną diodą LED) jako wysoki. Inaczej mówiąc, nakładamy „1” na pinezkę. Dokładnie tak to się robi (zwróć uwagę na komentarze, aby wyjaśnić każdy wiersz):

Dlatego teraz dokonaliśmy jednorazowego włączenia i wyłączenia diody LED. Chcemy, aby dioda LED włączała się, a następnie wyłączała.

Osiągamy to poprzez uzyskanie programu powrotu do początku. Osiągamy to, początkowo ustanawiając tag na początku naszego programu, a następnie informując program, aby tam powrócił. Etykietę określamy dość prosto.

Wpisujemy termin, mówimy START, następnie wpisujemy kod:

Jak pokazano, od razu na początku programu wspomnieliśmy o wyrażeniu „Start”.

Następnie, na samym końcu programu, wyraźnie wspomnieliśmy o „goto Start”. Instrukcja „goto” wykonuje dokładnie to, co deklaruje.

Ten program konsekwentnie włączał i wyłączał diodę LED za każdym razem, gdy włączamy obwód, mając tendencję do wyłączania się, gdy usuniemy prąd. Może powinniśmy jeszcze raz sprawdzić nasz program:

Z pewnością pominęliśmy komentarze, ale nadal możemy przestrzegać instrukcji i liczb.

Może to być nieco zagadkowe później, jeśli spróbujesz rozwiązać problem z programem i podczas pisania kodu zapamiętałeś wszystkie adresy.

Chociaż komentarze mogą być umieszczone, to może być trochę zaśmiecone. Będzie to wymagało nazwania liczb i może być wykonane przez dodatkową instrukcję: „equ” Instrukcja „equ” sugeruje, że niektóre rzeczy mogą być równe innym.

Może to nie być instrukcja dla PIC, a raczej dla asemblera. Instrukcja ta ułatwia przypisanie nazwy do lokalizacji adresowej rejestru lub stałej do terminu programistycznego.

Ustalimy kilka stałych dla naszego programu, a także zobaczymy, jak bardzo prosty jest on w czytaniu programu.

Od teraz ustaliliśmy stałe wartości, możemy kontynuować, ustawiając je w naszym programie. Przed użyciem należy wyznaczyć stałe wartości.

dlatego upewnij się, że zawsze umieszczasz je na początku programu. Program ponownie przepiszemy z wyłączeniem komentarzy, aby porównać wcześniejsze oznakowanie z najnowszym.

Być może zauważysz, że stałe umożliwiają nieco łatwiejsze zrozumienie programu, jednak nadal nie mamy komentarzy, nie martw się, ponieważ jeszcze nie skończyliśmy.

Nasz program z migającymi diodami może mieć niewielką wadę.
Każda instrukcja wymaga do zakończenia 1 sekwencji zegara. W przypadku, gdy używamy kryształu 4 MHz, to każda instrukcja wymaga zakończenia 1/4 MHz lub 1uS.

Ponieważ stosowaliśmy tylko pięć instrukcji, dioda LED włączyłaby się, a następnie zgasła w 5uS. Może to być zbyt szybkie, aby ludzie mogli to zauważyć, a ponadto wydaje się, że dioda LED jest całkowicie włączona.

Zamiast tego powinniśmy osiągnąć zahamowanie między włączaniem i wyłączaniem diody LED. Teoria zahamowania polega na tym, że odliczamy od wcześniejszej wielkości, więc kiedy osiągnie zero, przestajemy liczyć.

Wartość zero oznacza zakończenie opóźnienia, a my kontynuujemy proces przez cały program. Dlatego najpierw musimy określić stałą, która będzie używana jako nasz licznik.

Nazwijmy to stałą COUNT. Następnie musimy określić, jak ważna jest liczba, od której należy zacząć liczenie. Z pewnością największa liczba, jaką moglibyśmy uwzględnić, to 255 lub FFh w zapisie szesnastkowym. Jak mówiłem we wcześniejszym samouczku, instrukcja equ przypisuje wyrażenie do sytuacji w rejestrze.

Oznacza to, że bez względu na to, jaką ilość przydzielamy, nasz LICZB będzie pasował do pozycji rejestru. Jeśli spróbujemy wyznaczyć wartość FFh, popełnimy błąd po kompilacji programu.

Powodem jest lokalizacja FFh, dlatego nie możemy uzyskać do niej dostępu. Jak zatem musimy wyznaczyć prawdziwą liczbę? Z pewnością będzie to wymagało niewielkiej ilości bocznej refleksji.

Jeśli przypiszemy na przykład LICZNIK do adresu 08h, wskazywałoby to na podstawowy obiektywny cel rejestru. Domyślnie nietknięte obszary są ustawione na FFh. W konsekwencji, jeśli COUNT prowadzi do 08h, napotkasz wartość FFh podczas pierwszego uruchomienia. Niemniej jednak, ja ty, jak możemy zmienić COUNT na inną liczbę ?, wszystko, co stosujemy, to najpierw „przenieś” wycenę do tego miejsca docelowego.

Na przykład, załóżmy, że chcielibyśmy, aby COUNT miało wartość 85h, nie możemy wspomnieć o COUNT równym 85h, ponieważ jest to pozycja naszego rejestru trójstanowego dla Portu A. Dokładnie to, co osiągamy, jest następujące: movlw 85h Po pierwsze wartość 85h w rejestrze W movwf 08h

Teraz przenieś go do naszego rejestru 08h. Następnie, w przypadku wyrażenia COUNT równa się 08h, COUNT będzie odpowiadać wartości 85h. Czyż nie jest to delikatne? Dlatego początkowo określamy naszą stałą: COUNT equ 08h Następnie musimy zmniejszyć to COUNT o jeden, aż osiągnie zero.

Okazuje się po prostu, że istnieje jedna instrukcja, która ma to za nas zrobić, wykorzystując „goto” i tag.

Instrukcja, którą zamierzamy zastosować, to: DECFSZ COUNT, 1 Ta instrukcja mówi „Zmniejsz rejestr (tutaj jest to COUNT) o liczbę śledzącą przecinek. Jeśli osiągniemy zero, przeskocz o dwa punkty do przodu ”. Najpierw znajdźmy go w akcji, zanim umieścimy go na naszym kursie.

To, co wykonaliśmy, to początkowo ustalenie naszej stałej COUNT na 255. Kolejny segment ustawia tag, zwany LABEL, blisko naszej instrukcji decfsz.

Decfsz COUNT, 1 zmniejsza wartość COUNT o jeden i zachowuje wynik końcowy prosto do COUNT. Ponadto sprawdza, czy COUNT ma wartość 0.

Jeśli tak się nie stanie, w takim przypadku powoduje przejście programu do kolejnej linii. Teraz mamy deklarację „goto”, która odsyła nas z powrotem do instrukcji decfsz.

W przypadku, gdy wartość COUNT jest równa, wówczas instrukcja decfsz powoduje, że nasz program przeskakuje o 2 miejsca do przodu i jest wysyłana do miejsca, w którym zażądaliśmy „Kontynuuj tutaj”.

Dlatego, skoro możesz to zaobserwować, doprowadziliśmy program do siedzenia w jednym miejscu przez określony czas przed kontynuowaniem. Można to nazwać pętlą opóźniającą.

Zrozumienie pętli opóźnienia

W przypadku, gdy potrzebujemy bardziej znaczącego opóźnienia, moglibyśmy kontynuować jedną pętlę za następną. Dodatkowe pętle zwiększają opóźnienie. Przyjmijmy co najmniej dwie, zakładając, że chcemy obserwować błysk diody LED. Umieścimy te pętle opóźniające w naszym programie i zrobimy to, renderując go jako prawdziwy program, wprowadzając komentarze:

Możliwe jest skompilowanie tego programu, po którym zaprogramujemy PIC. Oczywiście upewnij się, że próbujesz sprawdzić obwód, aby sprawdzić, czy rzeczywiście działa. Poniżej znajduje się schemat obwodu, który należy skonstruować, gdy tylko zaprogramujesz PIC.


Dobra robota, mogłeś właściwie skomponować swój pierwszy program PIC, a także skonstruować obwód do włączania i wyłączania diody LED. Do tej pory, na wypadek, gdybyś uczestniczył w tych kursach, mogłeś nauczyć się łącznie siedmiu instrukcji z 35, ale bez wątpienia do tej pory możesz kontrolować porty I / O!

Czy spróbowałbyś zmienić pętle opóźnień, aby przyspieszyć miganie diody LED - jaka jest minimalna wartość COUNT, aby zasadniczo zobaczyć błysk diody? A może będziesz chciał dołączyć trzecią lub dodatkowe pętle opóźniające po początkowej, aby ustabilizować diodę LED. unikalna stała dla każdej pętli opóźnienia.

Możesz wtedy potencjalnie bawić się pętlami opóźnienia, aby renderować lampę błyskową LED z określoną prędkością, na przykład po sekundzie. W następnej instrukcji zobaczmy, w jaki sposób jesteśmy w stanie wykorzystać coś znanego jako podprocedura do utrzymania programu w zwartej i podstawowej formie. Podprogram jest integralną częścią kodu lub programu, do którego można się odnosić i kiedy może być potrzebny. Podprogramy są stosowane w przypadkach, gdy często wykonujesz tę samą funkcję.

Co to są podprogramy

Korzyści z zastosowania podprogramu są takie, że prawdopodobnie łatwiej będzie zmodyfikować wartość raz w podprogramie zamiast, powiedzmy, dziesięciokrotnie w całym programie, jak również znacznie przyczynia się do zmniejszenia poziomu pamięci, którą program zużywa wewnątrz FOTKA. Sprawdzimy podprogram:

Początkowo musimy podać oznaczenie naszemu podprogramowi, aw tej sytuacji wybraliśmy ROUTINE. Po tym wpisujemy kod, który chcielibyśmy normalnie przeprowadzić. Dlatego wybraliśmy opóźnienie w naszym programie z migającymi diodami. Na koniec kończymy podprogram, wpisując instrukcję RETURN.

Aby rozpocząć podprogram z dowolnego miejsca w naszym programie, szybko wpisujemy instrukcję CALL, a następnie oznaczenie podprogramu.

Rozważymy to nieco bardziej szczegółowo. Gdy dojdziemy do sekcji naszego programu, która wywołuje xxx, w której xxx jest nazwą naszego podprogramu, program przeskakuje w dowolne miejsce, w którym jest zainstalowany podprogram xxx. Wykonywane są instrukcje wewnątrz podprogramu.

Za każdym razem, gdy wykonywana jest instrukcja RETURN, program przeskakuje powracając do naszego programu głównego do instrukcji następującej po naszej instrukcji CALL xxx.

Możliwe jest kilkakrotne wywołanie podobnego podprogramu, jak chcesz, co wyjaśnia, dlaczego użycie podprogramów skraca ogólny czas trwania naszego programu.

Niemniej jednak jest kilka czynników, o których powinieneś wiedzieć. Początkowo, tak jak w przypadku naszego programu głównego, wszelkie określone stałe muszą zostać potwierdzone, zanim będzie można ich użyć.

Mogą one być ewentualnie potwierdzone w samym podprogramie lub bezpośrednio na początku programu głównego. Proponuję, abyś uznał wszystko na początku swojego głównego programu, ponieważ wtedy rozpoznasz, że sprawy są w identycznej pozycji. Następnie należy się upewnić, że program główny pomija podprogram.

Sugeruję z tego, że jeśli umieścisz podprogram bezpośrednio na końcu swojego programu podstawowego, z wyjątkiem sytuacji, gdy użyjesz deklaracji 'Goto', aby skoczyć z miejsca, w którym znajduje się podprogram, program będzie kontynuował i zaimplementował podprogram niezależnie od tego, czy wymagać tego lub w inny sposób.

PIC nie rozróżnia podprogramu i programu głównego. Sprawdzimy nasz program z migającymi diodami, jednak tym razem użyjemy podprogramu dla pętli opóźnienia. W idealnym przypadku odkryjesz, o ile mniej skomplikowany wydaje się program, a także możesz dowiedzieć się, jak podprogram jest stosowany w praktyce.

Ostatecznie możesz zauważyć, że wykorzystując podprogram dla naszej pętli opóźnienia, mogliśmy zmniejszyć wymiary programu.

Za każdym razem, gdy pożądamy opóźnienia, prawdopodobnie gdy dioda LED jest włączona lub wyłączona, w zasadzie wywołujemy podprogram opóźnienia. Po zakończeniu podprogramu program prowadzi z powrotem do wiersza następującego po naszej instrukcji „Call”. Na powyższej ilustracji włączamy diodę LED.

Następnie kontaktujemy się z podprogramem. Program następnie wraca, abyśmy mogli wyłączyć diodę. Ponownie wywołujemy podprogram, na wypadek gdyby podprogram mógł się zakończyć, program wraca i następną instrukcją, którą rozpoznaje, jest „goto Start”. Dla każdego, kto może być zaintrygowany, nasz pierwszy program miał 120 bajtów.

Używając podprogramu, mogliśmy zmniejszyć rozmiar naszego programu do 103 bajtów. To nie może brzmieć tak fantastycznie, jednak biorąc pod uwagę fakt, że w PIC mamy łącznie tylko 1024 bajty, każda niewielka ilość jest korzystna.

W następnym instruktażu przejrzyjmy odczyty z portów.

Do tej pory komponowaliśmy do Port A, aby móc włączać i wyłączać diodę LED. W tym momencie zobaczymy, jak zamierzamy odczytać piny I / O na portach.

Czytanie portów wejścia / wyjścia

Ma to na celu zapewnienie, że będziemy w stanie podłączyć zewnętrzny obwód i wpływać na określone przez niego wyjścia.

Jeśli pamiętasz z naszych wcześniejszych kursów, jeśli chcesz ustawić porty we / wy, musieliśmy przeskoczyć z banku 0 do banku 1. Zrobimy to na początku:

W tym momencie ustaliliśmy wejście bitu 0 portu A. musimy teraz sprawdzić, czy szpilka jest wysoka czy niska. Aby to osiągnąć, można wykorzystać tylko jedną z dwóch instrukcji:

BTFSC i BTFSS.

Instrukcja BTFSC oznacza „Wykonaj test bitowy na rejestrze, a także na bitu, który wyznaczamy.

Jeśli jest to 0, w takim przypadku pomijamy kolejną instrukcję ”. BTFSS oznacza „Wykonaj test bitowy w rejestrze i ustalmy bit. Jeśli jest ustawiony na 1, pomijamy kolejną instrukcję.

To, który z nich wykorzystamy, zależy dokładnie od tego, jak chcemy, aby nasz program reagował podczas studiowania danych wejściowych. Na przykład, w przypadku, gdy oczekujemy tylko, że dane wejściowe będą równe 1, możemy użyć instrukcji BTFSS w następujący sposób:

Kod tutaj:

BTFSS PortA, 0 Idź do startu Kontynuuj tutaj:
:

Program po prostu przełączy się na „Kontynuuj tutaj”, pod warunkiem, że bit 0 w PortA jest ustawiony na 1.

Obecnie napiszemy program, który może wywoływać diodę LED z jedną szybkością, jednak jeśli przełącznik zostanie zamknięty, będzie migać dioda LED dwa razy wolniej.

Być może jest możliwe wykonanie tego programu samodzielnie, jednak w jakiś sposób włączyliśmy ten program.

Możesz spróbować i napisać cały program, aby sprawdzić, czy rozumiesz zasady. Będziemy używać równoważnego obwodu, jak poprzednio, z włączeniem przełącznika RA0 PIC i dodatniej szyny naszego zasilania.

To, co tutaj osiągnęliśmy, to włączenie diody LED. Następnie ustalam, czy przełącznik jest wyłączony.

W przypadku, gdy jest ograniczony, następnie łączę się z naszym podprogramem opóźnienia. To zapewnia nam takie samo opóźnienie jak poprzednio, jednak w tym momencie kontaktujemy się z nim dwa razy.

To samo dotyczy sytuacji, gdy dioda LED jest wyłączona. W przypadku, gdy przełącznik nie jest zamknięty, mamy nasze poprzednie zarejestrowane okresy włączenia i wyłączenia.

Czy stosowałeś się do tych lekcji od samego początku, być może chciałbyś zrozumieć, że odkryłeś obecnie dziesięć z 35 instrukcji dla PIC 16F84! A każdego z nich można się nauczyć, po prostu włączając i wyłączając diodę LED.

Do tej pory skomponowaliśmy PIC miganie i włączanie i wyłączanie diody LED.

Następnie byliśmy w stanie z naszym PIC, włączając przełącznik, zmieniając w ten sposób prędkość flashowania.

Efektywne wykorzystanie miejsca w pamięci

Jedynym problemem jest to, że program jest dość długi i raczej nieefektywny pod względem miejsca w pamięci. Wydawało się w porządku, kiedy dołączałem polecenia po raz pierwszy, jednak powinien być łatwiejszy sposób wykonania tego. Na szczęście, przeanalizujemy, jak dosłownie włączaliśmy i wyłączaliśmy diodę LED.

movlw 02hmovwf PORTAmovlw 00hmovlw PORTA

Najpierw wypchaliśmy nasz rejestr w 02h, po czym przenieśliśmy go do naszego rejestru PortA, aby włączyć diodę LED. Aby go wyłączyć, spakowaliśmy w 00h, po czym przenieśliśmy go do naszego rejestru PortA.

Pomiędzy tymi wszystkimi procedurami byliśmy zmuszeni skontaktować się z podprogramem, aby upewnić się, że możemy obserwować miganie diody LED.

Dlatego musieliśmy kilka razy przesłać dwa zestawy informacji (raz do rejestru w, a następnie do PORTA), a także dwukrotnie wywołać podprogram (raz na włączanie, a raz na wyłączanie). Jak więc możemy to osiągnąć dzięki dodatkowej wydajności? Bardzo prosta.

Używamy innej instrukcji znanej jako XORF. Instrukcja XORF działa z funkcją Exclusive OR na rejestrze, którą określamy na podstawie podanych przez nas informacji. Uważam, że zanim przejdziemy dalej, muszę wyjaśnić, czym na świecie jest ekskluzywna sala operacyjna. W przypadku, gdy mamy dwa wejścia i jedno wyjście, wejście może mieć wartość 1 tylko wtedy, gdy i tak długo, jak te dwa wejścia się różnią. Chociaż są one takie same, wynik prawdopodobnie będzie równy 0. Poniżej znajduje się tabela prawdy dla osób, które zdecydują się je sprawdzić:

A B F0 0 00 1 11 0 11 1 0

W tym miejscu sprawdzimy, co się stanie, jeśli wyrenderujemy B tak, jak nasze wcześniejsze wyjście, i po prostu zmienimy wartość A:

A B F
0 0 0
0 0 0
1 0 1
1 1 0
1 0 1

Jeśli utrzymamy wartość A taką samą jak 1 i wyłączymy LUB ją z wyjściem, wyjście będzie się przełączać. Jeśli nie możesz tego zauważyć z tabeli prawdy, poniżej możesz zobaczyć, jak używa pliku binarnego:

0 Wyjście prądowe
EX-OR z 1 1 nowym wyjściem
EX-OR Z 1 0 nowym wyjściem

Być może okaże się, że przez wyłączne OR na wyjściu z 1, będziemy teraz przełączać wyjście z 0 na 1 na 0.
Stąd, aby włączyć i wyłączyć naszą diodę LED, wystarczy kilka zdań:

MOVLW 02h
DRZWI XORWF, 1

To, co dokładnie osiągniemy, to dodanie naszego rejestru w o numerze 02h. W tym przypadku jesteśmy wyłącznym ORingiem tego numeru bez względu na to, co jest na naszej PortA. W przypadku, gdy bit 1 jest 1, zmieni się na 0. W przypadku, gdy bit 1 jest 0, zamieni się na 1. Przeanalizujmy ten kod raz lub dwa razy, aby wyświetlić, jak działa binarnie:

DRZWI
00010
xorwf 00000
xorwf 00010
xorwf 00000
xorwf 00010

W rzeczywistości nie musimy za każdym razem ładować tej samej wartości do naszego rejestru w, dlatego można to zrobić tylko raz na początku i po prostu wrócić do naszego polecenia toggle. Ponadto nie powinniśmy ustalać wartości w naszym rejestrze PortA. Powód? Z pewnością, ponieważ w przypadku włączenia jest to 1, możemy łatwo to przełączyć. Ja, alternatywnie 0 po włączeniu, nawet teraz byśmy to przełączali.

Dlatego chciałbyś zobaczyć nasz nowo utworzony kod. Pierwsza z nich reprezentuje migający kod naszej diody, a druga przedstawia ten z dodatkiem przełącznika:

Żałujmy, że nie udało Ci się stwierdzić, że korzystając z jednej prostej instrukcji, ograniczyliśmy teraz skalę naszego programu. Prawda jest taka, że ​​aby pokazać, o ile moglibyśmy zredukować nasze programy, zademonstrowaliśmy dwa programy, co zostało skomponowane i ich wymiary w poniższej tabeli:

Program Zmień wymiary (bajty)
Migająca dioda LED Original 120
Migający podprogram LED Dodano 103
Używana funkcja migającej diody LED XOR 91
LED z przełącznikiem oryginalny 132
Dioda LED z funkcją przełącznika XOR 124.

Dlatego nie tylko odkryliśmy kilka nowatorskich instrukcji, ale z pewnością dodatkowo zmniejszyliśmy rozmiar naszych skryptów!

Poniżej przeanalizujemy, jak możesz poruszać pojedynczymi bitami, przeprowadzać proste arytmetyki, a także tabele danych.

Menedżerowie logiczni

W ostatnim samouczku przedstawiłem operację Exclusive OR. Funkcja ExOR rozumiana jest jako operator logiczny.

W tym samouczku wyjaśnię dodatkowe operatory logiczne promowane przez PIC. W programach punktowych nie będzie żadnego przypadku, jednak nauczymy się prostych metod używania operatorów, stosując małe obszary kodu.

AND Funkcja AND w zasadzie analizuje dwa bity i podaje 1, jeśli są takie same, oraz 0, jeśli są różne. Na przykład, gdybyśmy wspomnieli 1 AND 1, wynikiem jest 1, podczas gdy w przypadku, gdy zadeklarowaliśmy 1 AND 0, konsekwencją byłoby 0.

Nie trzeba dodawać, że jesteśmy w stanie również oceniać słowa, a cała funkcja AND, którą wykonuje, polega na przeglądaniu tych dwóch terminów po kawałku. Poniższy przykład ilustruje dwa 8-bitowe słowa połączone operatorem AND wraz z produktem:

11001011
AND 10110011
Równa się 10000011

Mam nadzieję, że się zgadzasz, wynik będzie po prostu posiadał 1, gdy 2 1s ręka w rękę ze sobą w parze słów. Możemy na przykład wykorzystać funkcję AND do weryfikacji portów.

W przypadku, gdy sprawdzamy kilka pinów I / O, które są połączone z obwodem, i powinniśmy mieć oko na szczególną sytuację, w której tylko kilka pinów jest wysokich, w takim przypadku jesteśmy w stanie prawie odczytać port, po którym ORAZ wynik z warunkiem, dla którego badaliśmy, identyczny z powyższym przykładem.

PIC dostarcza nam dwa składniki AND.
Są to ANDLW i ANDWF. ANDLW pozwala nam wykonać funkcję AND ze szczegółami rejestru W i określoną przez nas kwotą.

Składnia jest następująca: ANDLW, gdzie jest dokładnie to, do czego zmierzamy ORAZ zawartość W z.

Konsekwencje funkcji AND byłyby przechowywane bezpośrednio w rejestrze W.
ANDWF pozwala nam wykonać funkcję AND na rejestrze W i innym rejestrze, na przykład PORT. Składnia to: ANDWF, d w którym jest rejestrem, do którego jesteśmy entuzjastami, np. PORTA, id pokazuje PIC, w którym należy umieścić wynik. Jeśli d = 0, wynik jest umieszczany w rejestrze W, a dla d = 1 wynik końcowy jest zapisywany w określonym przez nas rejestrze. Dwie części kodu poniżej przedstawiają dobry przykład każdej funkcji AND.

Początkiem jest zbadanie statusu PORTA, w którym musimy sprawdzić, czy wejścia wynoszą 1100. Wynik możemy umieścić z powrotem w rejestrze W

Movlw 1100
ANDWF 05h, 0 Druga ilustracja może teraz weryfikować zawartość rejestru W:
ANDLW 1100

LUB

Do tej pory odkryliśmy jedną funkcję OR, a dokładniej XOR. To rozwija się w 1, jeśli dwa bity nie są takie same, ale są różne. Możesz znaleźć inną funkcję OR o nazwie IOR, która jest operacją OR. Ta funkcja wygeneruje 1 w przypadku, gdy którykolwiek z bitów jest równy 1, ale dodatkowo, jeśli każdy bit ma wartość 1. Poniżej znajduje się przejrzysta tabela prawdy, aby to zilustrować:

A B O / P
0 0 0
0 1 1
1 0 1
1 1 1

Co to są operatory arytmetyczne

DODAJ

Ta funkcja realizuje to, co zwykle twierdzi. Wnosi dwie liczby! Jeśli konsekwencja dodania dwóch cyfr przekroczy 8 bitów, wówczas prawdopodobnie zostanie ustawiona flaga CARRY. Flaga CARRY znajduje się pod adresem 03h bit 0.

Kiedy ten bit jest zaplanowany, te dwie cyfry przekroczyły 8 bitów. Gdy jest to 0, w takim przypadku konsekwencja mieści się w granicach 8 bitów. Tak jak poprzednio, PIC dostarcza nam dwa style ADD, konkretnie ADDLW i ADDWF. Jak można się było spodziewać, jest to bardzo podobne do powyższej funkcji. ADDLW oferuje zawartość rejestru W zgodnie z ustaleniami. Składnia jest następująca: ADDLW ADDWF dodaje zawartość rejestru W i inny wyznaczony przez nas rejestr.

Składnia jest następująca: ADDWF, d jest gdzie

POD

W tym momencie myślę, że nie możesz przypuszczać, co wykonuje ta funkcja! Rzeczywiście, podejrzewasz to, ta funkcja
odejmuje jeden bit od drugiego. Ponownie PIC zapewnia nam 2 smaki: SUBLW i SUBWF. Składnia jest dokładnie taka sama jak dla funkcji ADD, poza tym, że ewidentnie wpisujesz SUB zamiast ADD!

Przyrost W przypadku, gdy chcielibyśmy dołączyć 1 do liczby w PIC, moglibyśmy bezwzględnie skorzystać z funkcji ADD i wykorzystać numer jeden. ~ Trudność polega na tym, że musimy najpierw umieścić liczbę w rejestrze W, a następnie użyć kontrolki ADDLW 1, aby ją zwiększyć. W przypadku, gdy chcieliśmy dodać 1 do rejestru, może być jeszcze gorzej. Najpierw musimy umieścić numer 1 w rejestrze W, a następnie użyć ADDWF, 1. Dlatego na przykład, aby dołączyć 1 do lokalizacji 0C, musielibyśmy posiadać następującą część skryptu:

movlw 01
addwf 0c, 1

Istnieje łatwiejszy sposób przeprowadzenia tego. Możemy wykonać polecenie INCF. Składnia jest następująca: INCF, d gdzie jest rejestrem lub miejscem, którego jesteśmy zainteresowani, a d pokazuje PIC, w którym należy umieścić wynik. W przypadku, gdy d = 0, wynik znajduje się w rejestrze W, a w przypadku d = 1, konsekwencja jest zapisywana w określonym przez nas rejestrze.

Korzystając z tej indywidualnej instrukcji, jesteśmy w stanie faktycznie wykonać pięćdziesiąt procent kodowania. W przypadku, gdybyśmy chcieli przywrócić wynik do rejestru W, w takim przypadku wykorzystując powyższą instancję, moglibyśmy musieli dołączyć dodatkowe polecenie, aby przesunąć pozycje z 0C z powrotem do rejestru W, po czym umieścić rejestr 0C z powrotem na nie ważne, co to było.

Istnieje polecenie inkrementacji. To jest INCFSZ. To polecenie może zwiększyć rejestr, który określamy, jednak jeśli rejestr będzie równy 0 po zwiększeniu (który nastąpi, gdy włączymy 1 do 127), po czym PIC prawdopodobnie pominie kolejną instrukcję. Poniższy kod odzwierciedla to:

Pętla incfsz 0C
Idź do pętli
:
:
Pozostała część programu.

W powyższej części kodu 0C będzie zwiększane o 1. Następnie posiadamy instrukcję, która informuje PIC, aby powrócił do naszego znacznika o nazwie Loop i ponownie zwiększył 0C o 1. Trwa to aż 0C równa się 127. W tej sytuacji, gdy zwiększymy 0C o 1, 0C będzie teraz odpowiadać 0. Nasza instrukcja INCFSZ może bardzo dobrze poinformować PIC, aby pominął następną instrukcję, którą w tym przypadku jest deklaracja goto, stąd PIC będzie kontynuował realizację pozostałej części programu.

Zmniejszenie

Omówiliśmy już funkcję dekrementacji we wcześniejszych treningach, dlatego nie będę jej już więcej poprawiać.

Komplement

Końcowa instrukcja w tej dyskusji odwróciłaby każdy określony przez nas bit w rejestrze. Składnia to: COMF, d gdzie

Zrozumienie operacji na bitach

Można to wykorzystać na przykład do szybkiej zamiany pinów portu z wyjścia na wejście i tak dalej. Funkcje bitowe pozwalają nam kształtować pojedynczy bit w wyrażeniu. Pozwalają nam kontynuować, ustawiać i pozbywać się pojedynczych bitów w rejestrach lub liczbach, które ustalamy.

Na zakończenie tego kursu ujawnimy program przeznaczony do tworzenia zestawu sekwencyjnych świateł, które poruszają się do przodu, a następnie do tyłu. Zauważyliśmy, że zostało to osiągnięte wcześniej, gdy zbadaliśmy wyłączną funkcję OR, w której wykonaliśmy wyłączną OR na porty za pomocą wyrażenia. Zauważyliśmy teraz kilka funkcji bitowych, kiedy ustalamy porty na PIC, i

Powtórzę tutaj ich wykorzystanie.

BCF

Ta instrukcja zetrze trochę, którą zastrzegamy w wyznaczonym przez nas rejestrze. Składnia
jest:
BCF,

Zastosowaliśmy to wcześniej, aby zmienić stronę 1 na stronę 0, usuwając trochę z rejestru STATUS. Możemy również użyć go do ustawienia bitu na 0 w dowolnym innym rejestrze / lokalizacji. Na przykład, gdybyśmy chcieli ustawić trzeci bit w 11001101 zapisany w sekcji 0C na 0, możemy
wstawić:

BCF 0C, 03

BSF

Ta instrukcja naprawi każdy bit, który ustalimy na 1 w każdym wskazanym przez nas rejestrze. Wykorzystaliśmy to wcześniej, aby przejść od strony 0 do strony 1. Składnia jest następująca: BSF i jest używana dokładnie w taki sam sposób, jak powyżej BCF.

BTFSC Do tej pory mogliśmy ustawić lub wyczyścić trochę w rejestrze. Wyobraź sobie jednak, że musimy po prostu sprawdzić, czy bit ma wartość 1 czy 0 w rejestrze?

Z pewnością można skorzystać z BTFSC. Wskazuje rejestr testu bitowego F i pomiń, jeśli jest czysty. Ta instrukcja przeanalizuje bit, który wyznaczamy w rejestrze. W przypadku, gdy bit ma wartość 0, instrukcja poinformuje PIC o pominięciu kolejnej instrukcji.

Możemy wykorzystać tę instrukcję na wypadek, gdybyśmy chcieli sprawdzić flagę, na przykład flagę przeniesienia. Dzięki temu nie musimy czytać rejestru STATUS i szukać poszczególnych bitów, aby dowiedzieć się, które flagi są naprawione. 29 Na przykład, gdybyśmy chcieli sprawdzić, czy flaga Carry została ustawiona na 1 po dodaniu 2 cyfr, moglibyśmy wpisać:

BTFSC 03h, 0
kontynuuj tutaj, jeśli ustawione na 1
lub tutaj, jeśli ustawione na 0

W przypadku, gdy stan bitu wynosi 1, w takim przypadku instrukcja następująca po BTFSC byłaby zakończona. W przypadku ustawienia na 0, w takim przypadku kolejna instrukcja jest pomijana. Poniższa część kodu pokazuje, w których może być wykorzystana:

Pętla:
:
:
BTFSC 03,0
Idź do pętli

W powyższym kodzie PIC po prostu wyjdzie z pętli w przypadku, gdy bit 0 rejestru STATUS (lub flaga Carry) jest zdefiniowany jako 0. W przeciwnym razie zostanie wykonane polecenie goto.

BTFSS

Ta instrukcja określa rejestr testu bitowego F i pomiń, jeśli jest ustawiony. Może to być porównywalne z instrukcją BTFSC, poza tym, że PIC pominie kolejną instrukcję, jeśli bit, który oceniamy, jest ustawiony na 1 zamiast 0.

CLRF

Ta instrukcja poprawiłaby wszystkie szczegóły rejestru na 0. Składnia jest następująca:

CLRF
Zastosowaliśmy to wcześniej, aby ustawić wyjście portów na 0, stosując CLRF 85h. Ponadto zastosowaliśmy go, aby naprawić porty tak, aby zawierały wszystkie piny na wyjściu za pomocą CLRF
05h.

CLRW

Może to przypominać instrukcję CLRF, z wyjątkiem kasowania rejestru W. Składnia jest dość prosta:

CLRW

RLF i RRF

Te kierunki przetransportowałyby nieco w rejestrze pojedynczą szczelinę w lewo (RLF) lub w prawo (RRF) w rejestrze. Na przykład, gdybyśmy potrzebowali 00000001 i użyliśmy RLF, w takim przypadku moglibyśmy mieć 00000010. W tym momencie, co się dzieje w przypadku, gdy jest 10000000 i zastosowaliśmy instrukcję RLF? Z pewnością 1 byłby umieszczony we fladze nośnej. W przypadku, gdy ponownie zastosowaliśmy instrukcję RLF, cyfra 1 pojawi się ponownie na początku. Podobnie dzieje się w przypadku instrukcji RRF. Przykład w punkcie poniżej pokazuje to dla instrukcji RLF, w której widzimy 8 bitów rejestru, a także flagę przeniesienia:

C 87654321
0 00000001
RLF 0 00000010
RLF 0 00000100
RLF 0 00001000
RLF 0 00010000
RLF 0 00100000
RLF 0 01000000
RLF 0 10000000
RLF 1 00000000
RLF 0 00000001

Przykładowy program

Teraz zobaczymy przykładowy kod, który można skompilować i sterować. Generowałoby to światło sekwencjonowania zaczynające się od bitu 0 portu A, przechodzące do bitu 8 i portu PortB
potem wraca.
Podłącz diody LED do każdego z pinów portu. Będziemy mieć trochę tego
procedur wskazanych w tym samouczku.

TIME EQU 9FH Zmienna dla pętli opóźnienia.
PORTB EQU 06H Adres portu B.
TRISB EQU 86H Port B Adres trójstanowy.
PORTA EQU 05H Adres portu A.
TRISA EQU 85H Port A Adres trójstanowy.
STATUS EQU 03H Rejestr wyboru strony.
COUNT1 EQU 0CH Rejestr pętli.
COUNT2 EQU 0DH Rejestr pętli.

STATUS BSF, 5 Przejdź do strony 1
MOVLW 00H i skonfiguruj
MOVWF TRISB oba porty A i B.
MOVLW 00H na wyjście,
MOVWF TRISA, a następnie wróć do
STATUS BCF, 5 strona 0.
Wyczyść port A. MOVLW 00H
DRZWI MOVWF

Początek programu głównego

RUNMOVLW
01H Ustaw pierwszy bit MOVWF
PORTB na porcie B.CALL
OPÓŹNIENIE Poczekaj chwilę ZADZWOŃ
OPÓŹNIENIE
Przesuń bit na porcie B w lewo, a następnie wstrzymaj.RLF
PORTB, 1 ZADZWOŃ
DELAYCALL
DELAYRLF
PORTB, 1 ZADZWOŃ
DELAYCALL
DELAYRLF
PORTB, 1 ZADZWOŃ
DELAYCALL
DELAYRLF
PORTB, 1 ZADZWOŃ
DELAYCALL
DELAYRLF
PORTB, 1 ZADZWOŃ
DELAYCALL
DELAYRLF
PORTB, 1 ZADZWOŃ
DELAYCALL
DELAYRLF
PORTB, 1 ZADZWOŃ
DELAYCALL
DELAYRLF
PORTB, 1 To przenosi bit do flagi przeniesienia
Teraz przejdź do portu A i przesuń kawałek w lewo.RLF
PORTA, 1 Przenosi bit ze flagi zerowej do PortACALL
DELAYCALL DELAYRLF
DRZWI, 1 ZADZWOŃ
DELAYCALL
DELAYRLF
DRZWI, 1 ZADZWOŃ
DELAYCALL
DELAYRLF
DRZWI, 1 ZADZWOŃ
DELAYCALL
OPÓŹNIENIE
Przenieś bit z powrotem na Port ARRF
DRZWI, 1 ZADZWOŃ
DELAYCALL
DELAYRRF
DRZWI, 1 ZADZWOŃ
DELAYCALL
DELAYRRF
DRZWI, 1 ZADZWOŃ
DELAYCALL
DELAYRRF
PORTA, 1 To przenosi bit do flagi zerowej Teraz przesuń bit
z powrotem na Port BRRF
PORTB, 1 ZADZWOŃ
DELAYCALL
DELAYRRF
PORTB, 1 ZADZWOŃ
DELAYCALL
DELAYRRF
PORTB, 1 ZADZWOŃ
DELAYCALL
DELAYRRF
PORTB, 1 ZADZWOŃ
DELAYCALL DELAYRRF
PORTB, 1 ZADZWOŃ
DELAYCALL
DELAYRRF
PORTB, 1 ZADZWOŃ
DELAYCALL
DELAYRRF
PORTB, 1 ZADZWOŃ
DELAYCALL
OPÓŹNIENIE Teraz jesteśmy z powrotem tam, gdzie zaczęliśmy, GOTO
RUN, chodźmy ponownie.

W zestawie uczącym istnieje świetna opcja, która umożliwia korzystanie z tabeli danych.

Tabela danych to po prostu lista cytatów danych, w której wszystko jest przeglądane na podstawie kilku rozważań.
Na przykład możesz mieć obwód, który wykorzystuje PIC, który zlicza liczbę przypadków, w których pin wejściowy staje się wysoki w ciągu 1 sekundy. Następnie możesz wyświetlić numer na 7-segmentowym wyświetlaczu.

Zaraz po uruchomieniu odliczania PIC zaczyna zliczać liczbę przypadków, w których pin jest wysoki. Po 1 sekundzie odwiedza tabelę i spogląda w górę na dane, musi wyświetlić liczbę na wyświetlaczu, która symbolizuje ilość sytuacji, w których pin osiągnął wysoki poziom. Może to być korzystne, ponieważ nie określamy, jaka może być ta liczba, dopóki dowódca statku powietrznego nie dokona swoich szacunków.

Korzystając z tabeli, jesteśmy w stanie pozwolić PIC określić, którą figurę przedstawić. W tym momencie, zanim przejdę do pokazania, jak funkcjonuje tabela danych, być może będę musiał powiedzieć, że PIC utrzymuje ścieżkę lokalizacji w programie, podczas gdy program działa.

Ułatwia to tym, którzy wykonywali pewne programy w języku BASIC. W przeciwnym razie nie martw się, możesz kontynuować naukę teorii. Wyobraź sobie, że istnieje program BASIC podobny do przedstawionego poniżej:

10 LAT K = 0
11 K = K + 1
12 JEŚLI K> 10 TO GOTO 20 INNE GOTO 11
20 DRUKUJ K
21 KONIEC

Program zaczyna się w linii 10. Gdy tylko K jest ustawione na 0, przechodzi następnie do linii 11. Po dodaniu 1 do K przechodzimy do linii 12.

W tym momencie możemy być ciekawi, czy K jest większe niż 10. W takim przypadku udajemy się do linii 20, albo wrócimy do linii 11.

Linia 20 dokumentuje K, a linia 21 kończy program. BASIC wykorzystuje statystyki liniowe, aby pomóc programiście w prowadzeniu rejestru problemów, ponieważ etykiety nie są autoryzowane. PIC używa etykiet, aby uciec między miejscami docelowymi - czy może naprawdę?

Używamy etykiet, aby upewnić się, że jesteśmy świadomi, gdzie są problemy, a także abyśmy byli w stanie poinformować PIC w prosty sposób, gdzie szukać.

Dokładnie to, co się dzieje, to PIC korzysta z wewnętrznego licznika linii zwanego licznikiem programu. Ścieżka licznika programów (w skrócie PC) miejsca docelowego pamięci, w którym znajduje się niniejsza instrukcja.

Za każdym razem, gdy informujemy PIC, aby odwiedził wybraną etykietę, rozumie miejsce w pamięci i dlatego rozszerza komputer, aż zobaczy to miejsce w pamięci. To jest dokładnie ta sama metoda, którą sprawdziliśmy powyżej w programie BASIC. Poniżej znajduje się fragment kodu ze spacjami pamięci lub elementami komputera, obok każdej instrukcji:

Instrukcja PC0000 movlw 03
0001 movwf 0C
0002 Pętla decfsc 0C
0003 Goto Loop
0004 koniec

W powyższej demonstracji ustawiliśmy komputer PC na 0000. Na tym mamy instrukcję movlw 03. Kiedy PIC zaimplementuje te dane, zwiększa komputer PC w celu zeskanowania kolejnej instrukcji. W tym momencie PIC wyświetla movwf 0C. Komputer jest ponownie zwiększany.

Teraz badania PIC decfsc 0C. W przypadku, gdy szczegóły 0C nie są równe 0, w tym przypadku komputer jest zwiększany o 1, a następująca instrukcja, goto Loop, informuje komputer, aby powrócił do pozycji 0003, która jest tą pętlą. W przypadku, gdy szczegółami 0C jest 0, wówczas PC zaleca się zwiększyć o 2, czyli po prostu pominąć kolejną instrukcję.

Zrozumienie tabel danych

Powoduje to umieszczenie komputera PC w pozycji 0004, gdzie program się kończy. Miejsca docelowe są ustalane przez asemblera i generalnie nie powinniśmy przejmować się tym, co robi komputer. Aż do chwili, gdy potrzebujemy przejąć nad tym kontrolę, tak jak robimy to w przypadku korzystania z tabel danych. Najwygodniejszym sposobem opisania działania tabeli danych jest rozpoczęcie od ilustracji.

PC equ 02
movlw 03
tabela połączeń
:
tabela addwf PC
retlw 01
retlw 02
retlw 03
retlw 04
retlw 05
retlw 06
retlw 07
powrót

Początkowa instrukcja polega na przydzieleniu do komputera etykiety adresu licznika programów (02h). Będziemy wkrótce po wpisaniu wartości 03h do rejestru w. Po tym komunikujemy się ze stołem. Pierwsza linia w tabeli podprogramów rozszerza szczegóły rejestru W (03h) do licznika programu.

Powoduje to zwiększenie licznika programu o 3 lub inaczej mówiąc, stymuluje licznik programów do przejścia w dół o 3 wiersze. Gdy licznik dociera o 3 linie w dół, PIC rozpoznaje ponownie instrukcję. To polecenie wysyła następującą po nim wartość do rejestru W, po czym wraca z podprogramu. RETLW zasadniczo oznacza Return, dosłownie do W.

Zobacz, po słowie Return umieściłem przecinek. Ponieważ jesteśmy w podprogramie, wymagamy instrukcji Return na jego powierzchni. Dlatego RET w instrukcji. Po instrukcji RETLW jest liczba i to jest dokładnie to, co jest umieszczane w rejestrze W.

W tym przypadku jest to figura 3. Moglibyśmy wyznaczyć dowolną wielkość do rejestru W, tak długo, jak ta liczba jest połączona z licznikiem programu w podprogramie tabeli, odkryjemy instrukcję retlw. Na powyższej ilustracji oznacza to, że możemy posiadać dowolną liczbę od 1 do 7. W przypadku, gdy przejdziemy poza podprogram, być może uda nam się zakończyć wykonywanie dodatkowej sekcji programu. Z tego powodu zwykle mądrym posunięciem jest umieszczenie tabeli danych dokładnie pod koniec programu PIC, dlatego jeśli w tym przypadku przekroczymy, i tak dojdziemy do zakończenia programu.

Temat przerwań może być najdłuższy i najtrudniejszy do przejścia.

Nie możesz znaleźć żadnej nieskomplikowanej metody opisywania przerwań, jednak przy odrobinie szczęścia pod koniec tej części możesz być w stanie zastosować przerwania we własnych programach.
Podzieliliśmy tę sekcję na 2 etapy. Ma to na celu umożliwienie podzielenia tematu na sekcje, a także zapewnienie przydatnej instrukcji ułatwiającej zrozumienie.

Czym dokładnie jest przerwanie? Z pewnością, jak wskazuje termin, przerwanie jest techniką lub sygnałem, który uniemożliwia mikroprocesorowi / mikrokontrolerowi wykonanie jakichkolwiek czynności, które mogłyby się wydarzyć.

Pozwólcie, że podam wam codzienną ilustrację. Pomyśl, że relaksujesz się we własnym domu, rozmawiając z inną osobą. Nagle rozlega się dźwięk telefonu.

Przestajesz rozmawiać i chwytasz telefon, aby porozmawiać z dzwoniącym. Po rozmowie telefonicznej decydujesz się powrócić do rozmowy z daną osobą, zanim zadzwoni telefon. Podczas rozmowy z kimś można wziąć pod uwagę główną rutynę, dzwonek telefonu zakłóca rozmowę, a przerwa w rutynie to metoda rozmowy przez telefon.

Kiedy rozmowa telefoniczna dobiega końca, wracasz do swojej podstawowej rutyny czatu. Ta ilustracja jest dokładnie tym, jak przerwać procesor, aby podjąć działanie.

Program główny działa, wykonując określoną funkcję w obwodzie, jednak gdy ma miejsce przerwanie, program główny zatrzymuje się, podczas gdy wykonywana jest inna procedura. procedura kończy się, procesor wraca do procedury podstawowej, tak jak poprzednio.

Zrozumienie przerwań

PIC posiada 4 źródła przerwań. Można je podzielić na kilka grup. Dwa z nich są źródłami przerwań, które mogą być wykorzystane na zewnątrz do PIC, podczas gdy pozostałe dwa to procesy wewnętrzne. Pozwólcie, że wyjaśnię tutaj dwa typy zewnętrzne. Pozostałe dwa zostaną opisane w różnych samouczkach, gdy dojdziemy do timerów i przechowywania danych.

Jeśli sprawdzisz pin-out PIC, zauważysz, że pin 6 to RB0 / INT. W tym momencie RB0 jest wyraźnie bitem 0 portu B. INT oznacza, że ​​można go równie dobrze skonfigurować jako zewnętrzny pin przerwania. Ponadto, piny od 4 do 7 portu B (piny od 10 do 13) mogą być również wykorzystywane do przerwań. Zanim będziemy mogli wykorzystać wyprowadzenia INT lub innego portu B, musimy wykonać dwa zadania. Najpierw musimy poinformować PIC, że użyjemy przerwań.

Następnie musimy wyznaczyć pin B portu, którego będziemy używać jako przerwania, a nie jako pin I / O. Wewnątrz PIC można znaleźć rejestr znany jako INTCON i znajduje się pod adresem 0Bh. W tym rejestrze znajdziesz 8 bitów, które mogą być włączone lub wyłączone. Bit 7 INTCON jest znany jako GIE. To jest Global Interrngupt Enable. Ustalenie tego na 1 informuje PIC, że zastosujemy przerwanie.

Bit 4 INTCON jest znany jako INTE, INTerrupt Enable. Ustawienie tego bitu na 1 przekazuje do PIC, że RB0 będzie pinem przerwania. Konfiguracja bitu 3, zwanego RBIE, informuje PIc, że będziemy używać bitów portu B od 4 do 7. W tym momencie PIC rozumie, kiedy ten pin może być wysoki lub niski, musi zatrzymać to, co wykonuje i kontynuować przerwanie rutyna. W tym momencie musimy poinformować PIC, czy przerwanie prawdopodobnie będzie na zboczu narastającym (0 V do + 5 V) lub opadającym zboczu (+ 5 V do 0 V) ​​transformacji sygnału.

Mówiąc prościej, czy chcemy, aby PIC przerywał za każdym razem, gdy sygnał przechodzi od niskiego do wysokiego, czy od wysokiego do niskiego. Przez zaległości można ustalić, że zostanie to umieszczone na zboczu narastającym.

Wyzwalanie zbocza jest zaplanowane w dodatkowym rejestrze zwanym rejestrem OPTION pod adresem 81h. Bit, co do którego jesteśmy entuzjastami, to bit 6, często nazywany INTEDG.

Ustawienie tego na 1 powoduje, że PIC przerywa pracę na krawędzi montażowej (stan domyślny), a ustawienie na 0 stymuluje PIC do przerwania na krawędzi przesuwnej. Jeśli chcesz, aby PIC aktywował się na zboczu narastającym, z pewnością nie musisz nic robić z tym bitem.

W tym momencie, niestety, rejestr Option znajduje się w banku 1, co oznacza, że ​​lubimy modyfikować z banku 0 do banku 1, ustawiać bit w rejestrze opcji, a następnie wracać do banku 0. Kluczem jest tutaj wykonanie każdego bitu. banku 1 rejestruje się w jednym uderzeniu, na przykład ustanawiając szpilki portu, a następnie wracając do banku 0, jeśli skończysz.

Dobrze, w konsekwencji powiadomiliśmy PIC, który pin prawdopodobnie będzie przerwaniem i gdzie wyzwolić krawędź, co dzieje się w programie i PIC za każdym razem, gdy nastąpi przerwanie? Dzieje się kilka rzeczy. Po pierwsze, planowana jest „flaga”.

Informuje to wewnętrzny procesor PIC, że nastąpiło przerwanie. Następnie licznik programu (o którym mówiłem w poprzednim samouczku) wskazuje konkretny adres w PIC. Szybko sprawdźmy to wszystko indywidualnie. Flaga przerwania W naszym rejestrze INTCON bit 1 jest flagą przerwania, zwaną INTF. W tym momencie, ilekroć pojawi się jakiekolwiek przerwanie, ta flaga prawdopodobnie zostanie ustawiona na 1.

Gdy nie ma przerwania, flaga jest ustawiana na 0. Poza tym wszystko się kończy. W tym momencie możesz się zastanawiać „o co chodzi?” Z pewnością, nawet jeśli ta flaga jest zaplanowana na 1, PIC nie jest w stanie i nie zareaguje na kolejne przerwanie. Dlatego wyraźmy, że wywołujemy przerwanie. Flaga prawdopodobnie zostanie ustawiona na 1, a PIC może przejść do naszej procedury obsługi przerwania.

Gdy ta flaga nie została ustalona na 1, a PIC mógł kontynuować odpowiadanie na przerwanie, to ciągłe pulsowanie pinów mogło utrzymać powrót PIC do początku naszej procedury przerwania i w żadnym wypadku jej nie dokończyć. Wracając do mojej ilustracji z telefonem, jest to podobne do podniesienia telefonu i natychmiast po przystąpieniu do rozmowy zaczyna dzwonić ponownie, ponieważ inna osoba chce z tobą porozmawiać.

Wskazane jest, aby zakończyć jeden dialog, a następnie ponownie chwycić telefon i porozmawiać z kolejną osobą. Możesz znaleźć mały problem z tą flagą. Mimo że PIC szybko ustawia tę flagę na 1, nie ustawia jej ponownie na 0! Tę czynność musi wykonać programista - czyli Ty. Można to osiągnąć bez wysiłku, ponieważ przypuszczam, że należy to osiągnąć po wykonaniu przez PIC procedury przerwania.

Lokalizacja pamięci Za każdym razem, gdy po raz pierwszy włączasz PIC lub w przypadku resetowania, licznik programu podpowiada adres 0000h, co może nastąpić natychmiast na początku pamięci programu. Ale w przypadku przerwania licznik programu wskaże adres 0004h.

Dlatego też, gdy tworzymy nasz program, który będzie miał przerwania, najpierw musimy poinformować PIC, aby przeskoczył adres 0004h i utrzymał procedurę przerwania, która zaczyna się od adresu 0004h dyskretnie od pozostałej części programu.

Może to być bezproblemowe. Początkowo rozpoczynamy nasz program poleceniem znanym jako ORG. To polecenie wskazuje początek lub początek. Trzymamy się tego z adresem. Ponieważ PIC rozpoczyna się pod adresem 0000h, wpisujemy ORG 0000h. Następnie musimy ominąć adres 0004h. Osiągamy to, umieszczając instrukcję GOTO, której towarzyszy etykieta, która zawiera wskazówki dotyczące naszego programu podstawowego.

Następnie stosujemy się do tego polecenia GOTO z jeszcze jednym ORG, w tym momencie z adresem 0004h. Po tym poleceniu wstawimy naszą procedurę przerwania. W tym momencie możemy być w stanie wpisać naszą procedurę przerwania prosto po drugim poleceniu ORG lub możemy ustawić instrukcję GOTO, która wskazuje na procedurę przerwania.

To naprawdę jest związane z opcją z Twojej strony. Aby poinformować PIC, który oferuje, doszedł do zakończenia procedury przerwania, musimy ustawić polecenie RTFIE pod koniec procedury. To polecenie oznacza powrót z procedury przerwania. Gdy PIC to zauważa, licznik programu wskazuje ostateczną pozycję, w której PIC znajdował się przed wystąpieniem przerwania. Poniżej utworzyliśmy krótką sekcję kodu, aby wyświetlić powyższe:

Jest kilka rzeczy, o których powinieneś wiedzieć, kiedy używasz przerwań. Na początku wydaje się, że jeśli używasz identycznego rejestru w programie głównym i procedurze przerwań, pamiętaj, że szczegóły rejestru najprawdopodobniej zmienią się, gdy nastąpi przerwanie.

Na przykład, wykorzystajmy rejestr w do przekazywania danych do programu głównego portu A, dlatego też można dodatkowo wykorzystać rejestr w w procedurze przerwania do przenoszenia danych z jednego miejsca docelowego do drugiego.

W przypadku, gdy nie jesteś ostrożny, rejestr w będzie zawierał ostatnią wartość, którą otrzymał, gdy był w procedurze przerwania, więc kiedy wrócisz z przerwania, ta informacja zostanie dostarczona do portu A, a nie wartość, którą posiadałeś wcześniej nastąpiło przerwanie.

Środkiem do tego jest chwilowe zapisanie szczegółów rejestru w przed ponownym wykorzystaniem go w procedurze przerwania. Drugi to fakt, że można znaleźć opóźnienie między momentem, w którym następuje jedno przerwanie, a tym, kiedy może wystąpić następne. Chociaż rozumiesz, PIC posiada zewnętrzny zegar, który może być kryształem lub kombinacją rezystor-kondensator.

Bez względu na częstotliwość tego zegara, PIC dzieli go przez 4, po czym wykorzystuje to do wewnętrznego pomiaru czasu. Na przykład w przypadku, gdy masz kryształ 4 MHz podłączony do swojego PIC, w takim przypadku PIC wykonywałby instrukcje przy 1 MHz. Ten wewnętrzny czas jest znany jako cykl instrukcji. W tym momencie arkusz danych podaje (niewątpliwie drobnym drukiem), że musisz włączyć 3 do 4 rund instrukcji między przerwaniami.

Chciałbym włączyć 4 rundy. Przyczyną opóźnienia jest to, że PIC potrzebuje czasu, aby przeskoczyć do adresu przerwania, flagi i wrócić z procedury przerwania. Dlatego miej to na uwadze, jeśli pracujesz z alternatywnym obwodem, aby aktywować przerwanie dla PIC.

W tym miejscu chodzi o fakt, że jeśli wykorzystasz bity od 4 do 7 portu B jako przerwanie. Nie możesz wybrać określonych pinów w porcie B, aby działały jako przerwanie.

Dlatego, jeśli pozwolisz na te szpilki, prawdopodobnie wszystkie będą dostępne. Dlatego, na przykład, nie możesz po prostu mieć bitów 4 i 5 - bity 6 i 7 będą prawdopodobnie aktywowane w tym samym czasie. Jaki dokładnie jest cel uzyskania czterech bitów reprezentujących przerwanie? Z pewnością możesz mieć obwód podłączony do PIC, na wypadek gdyby którakolwiek z czterech linii osiągnęła wysoki poziom, w takim przypadku może to być problem, na który musisz natychmiast wpłynąć przez PIC.

Przykładem może być alarm bezpieczeństwa w domu, w którym cztery czujniki są połączone ze stykami od 4 do 7 portu B. Dowolny określony czujnik może skłonić PIC do wyzwolenia alarmu, a procedura sygnalizacji alarmu to procedura przerwania. Oszczędza to ciągłe sprawdzanie portów i pozwala dowódcy statku powietrznego na kontynuowanie różnych spraw. W następnym samouczku utworzymy program do obsługi przerwania.

Podczas ostatniego samouczka zajmowaliśmy się wieloma podstawami, dlatego czuję, że nadszedł czas, aby skomponować nasz pierwszy program.

Program, który napiszemy, zliczałby liczbę przypadków, w których włączamy przełącznik, a następnie pokazywałby liczbę.

Program liczyłby od 0 do 9, widoczny na 4 diodach LED w postaci binarnej, wraz z wejściem lub przerwaniem prawdopodobnie będzie na RB0.

Najważniejszą rzeczą, którą musimy zrobić, jest poinformowanie PIC, aby przeskoczył adres, na który wskazuje licznik programu, gdy ma miejsce przerwanie.

Zauważysz, że stosujemy unikalną metodę przedstawiania liczb szesnastkowych. Zanim to się stało, zastosuj F9h, w którym h oznaczono szesnastkowo. Moglibyśmy zapisać to jako 0xF9, czyli strukturę, którą od teraz będziemy używać.

Teraz musimy powiedzieć PIC, że będziemy używać przerwań i używamy styku 6 RB0 jako pinu przerwania:

bsf INTCON, 7GIE - Globalne zezwolenie na przerwanie (1 = włączone)
bsf INTCON, 4INTE - zezwolenie na przerwanie RB0 (1 = włączone)
Na wszelki wypadek wyczyszczę flagę przerwania (nigdy niczego nie ufam!)
bcf INTCON, 1INTF - Wyczyść bit flagi na wszelki wypadek

Obecnie musimy ustanowić nasze 2 porty. Należy pamiętać, że ponieważ teraz używamy RB0 jako styku przerwania, należy to ustawić jako wejście:

Zamierzamy użyć zmiennej o nazwie COUNT do przechowywania liczby zliczeń przełączników. Moglibyśmy po prostu zwiększyć wartość na porcie A, ale zobaczysz, dlaczego używam zmiennej, kiedy piszemy naszą procedurę przerwania.

Dlatego nasz główny program jest złożony i na tym etapie musimy poinformować PIC, jak postępować w przypadku przerwania. W tym przykładzie naszym przerwaniem prawdopodobnie będzie przełącznik. Chcielibyśmy, aby PIC był jednym z regulowanym COUNT za każdym razem, gdy przełącznik jest ograniczony.

Niemniej jednak chcemy tylko pokazać, ile razy przełącznik wyłącza się z 0 do 9. Powyżej stwierdziłem, że możemy po prostu zwiększyć wartość na porcie A za każdym razem, gdy występuje przerwanie. Jednak port A ma 5 bitów, na wypadek, gdybyśmy po prostu zwiększyli port, będziemy mieć największą liczbę 31. Istnieje kilka wyjaśnień, dlaczego zdecydowałem się nie przesuwać do 31.

Początkowo zastosujemy 7-segmentowy ekran, który może co najwyżej przejść od 0 do 15 (od 0 do F w szesnastce). Następnie chciałbym dodatkowo pokazać kilka poleceń arytmetycznych, na które natknąłeś się na kilku ostatnich lekcjach.

Dlatego będziemy kontynuować naszą procedurę przerwań. Obecnie pierwszą rzeczą, którą musimy wykonać, jest krótkie przechowywanie szczegółów naszego rejestru w, ponieważ stosujemy to do przenoszenia zawartości COUNT do PORTA. W przypadku, gdy go nie zapiszemy, w takim przypadku możemy być w stanie podać zupełnie inną liczbę z powodu naszej arytmetyki. Dlatego zróbmy to najpierw:

W tym momencie rozumiemy, czy wartość COUNT wynosi 9 lub więcej. To, co teraz musimy zrobić, to jeśli LICZBA jest większa niż 9, ustaw ją z powrotem na 0 lub wróć do głównego programu, aby upewnić się, że jesteśmy w stanie dostarczyć go do portu A. Polecenie BTFSS, ponieważ rozumiesz, czy następne
instrukcja w przypadku, gdy flaga przeniesienia jest zaplanowana, tj.LICZBA = 10:

Jedyne, co pozostaje do zrobienia, to zbiorcze wprowadzenie i ustalenie wartości naszych stałych, które jesteśmy w stanie wykonać od razu na starcie naszego programu.

Za każdym razem, gdy włączysz przełącznik, diody LED będą liczyć binarnie od 0000 do 1010, a następnie z powrotem do 0000.

Poniższy rysunek przedstawia schemat obwodu zgodny z powyższym wyjaśnionym kodem. Co ciekawe okaże się, że w projekcie uwzględniono kondensator rozrządu. Jest to miła sztuczka, dzięki której możesz uniknąć włączenia kondensatora na wypadek, gdybyś go nie miał w tym czasie.

Tutaj pojemność wchodzi w grę poprzez pojemność rozproszoną na pinie oscylatora i masie.
Oczywiście może się to wydawać niezbyt inteligentnym sposobem na uniknięcie kondensatora w praktyce, ponieważ wartość błądząca może się zmieniać w różnych danych warunkach.

Inną sekcją, którą można zaobserwować w obwodzie, jest sieć potępiająca w przełączniku. Zapobiega to zakłóceniom podczas przełączania mechanicznego i zapobiega pomyleniu PIC, jeśli przełączanie było jednym przełącznikiem lub wieloma przełącznikami.




Poprzedni: Programowalny dwukierunkowy obwód czasowy silnika Dalej: Jak działają obwody Buck-Boost