czwartek, 13 sierpień 2020
 
Strona główna Mikrokontrolery 8051 Konstrukcje programowe

Realizacja podstawowych konstrukcji programowych w µK 8051

  1. Instrukcje warunkowe
  2. Instrukcje wyboru
  3. Instrukcje pętli

WSTĘP

We wszystkich strukturach programowych zachodzi potrzeba podejmowania decyzji. Wykorzystuje się tu instrukcje warunkowe. W asemblerze odpowiada to wykonaniu skoku warunkowego. W µK 8051 wszystkie skoki warunkowe są względne krótkie (offset).
Zestaw skoków warunkowych jest następujący:

Skoki proste
        JZ      offset             ;skok, jeżeli A=0
        JNZ     offset             ;skok, jeżeli A≠0
        JC      offset             ;skok, jeżeli C=1
        JNC     offset             ;skok, jeżeli C=0
        JB      bit,offset         ;skok, jeżeli bit=1
        JNB     bit,offset         ;skok, jeżeli bit=0
        JBC     bit,offset         ;skok, jeżeli bit=1 oraz bit←0
Skoki z predekrementacją
        DJNZ    Rn,offset          ;Rn←Rn-1, jeżeli Rn≠0 to skok
        DJNZ    adres,offset       ;(adres)←(adres)-1, jeżeli (adres)≠0 to skok
Skoki z testowaniem wartości i relacji
        CJNE    A,adres,offset     ;jeżeli A<(adres) to C←1, skok, jeżeli A≠(adres)
        CJNE    A,#dana,offset     ;jeżeli A<dana to C←1,    skok, jeżeli A≠dana
        CJNE    Rn,#dana,offset    ;jeżeli Rn<dana to C←1,   skok, jeżeli Rn≠dana
        CJNE    @Ri,#dana,offset   ;jeżeli (Ri)<dana to C←1, skok, jeżeli (Ri)≠dana

INSTRUKCJE WARUNKOWE

  1. Instrukcja warunkowa prosta (IF..THEN..)
    Struktura stosowana, gdy zachodzi potrzeba warunkowego wykonania (lub pominięcia) pewnych operacji. Asembler (w porównaniu do języków wysokiego poziomu) ogranicza zestaw warunków możliwych do testowania. Ponadto zwykle sprawdzany jest warunek pominięcia operacji, a nie wykonania, jak to jest w językach np. C++ czy Pascal (zaznaczyłem to na sieci działań obok).

    Przykłady:

    jeżeli brak przeniesienia
             :
            JC      DALEJ
             :                    ;ciąg instrukcji wykonywany,
             :                    ;gdy znacznik przeniesienia C=0
    
    DALEJ:   :
    
    jeżeli "k"
             :
            CJNE    A,#'k',DALEJ
             :                    ;ciąg instrukcji wykonywany,
             :                    ;gdy w akumulatorze jest kod litery "k"
    
    DALEJ:   :
    

    W poniższym przykładzie zostaną wykonane instrukcje XRL.. INC.. i SETB.. tylko dla minusa

    jeżeli "-"
             :
            ACALL   DAJ_ZNAK
            CJNE    A,#'-',DALEJ
            XRL     LICZBA,#0FFH
            INC     LICZBA
            SETB    P1.5
    DALEJ:   :
    
    do góry
  2. Instrukcja warunkowa złożona (IF..THEN..ELSE..)
    Jest to rozgałęzienie programu na dwie równoległe ścieżki postępowania. Wymaga to wykonania w programie dwóch skoków, w tym jednego warunkowego.

    Przykłady:

    zero - nie zero
             :
            JZ      ZERO
             :                   ;ciąg instrukcji wykonywany,
             :                   ;gdy ACC≠0
            SJMP    DALEJ
    ZERO:    :                   ;ciąg instrukcji wykonywany,
             :                   ;gdy ACC=0
    DALEJ:   :
    
    równy - nierówny
             :
            CJNE    A,#' ',ZNAK   ;testujemy spację
             :                    ;ciąg instrukcji wykonywany,
             :                    ;gdy ACC=' ' (spacja)
            SJMP    DALEJ
    ZNAK:    :                    ;ciąg instrukcji wykonywany,
             :                    ;gdy ACC zawiera inny znak
    DALEJ:   :
    

    Instrukcja CJNE posiada ciekawą właściwość, pozwalającą na rozgałęzienie potrójne według relacji "<", "=" i ">". Rozbudowana wersja powyższej konstrukcji:

    mniejszy - równy - większy
             :
            CJNE    A,#' ',ZNAK   ;testujemy spację
             :                    ;ciąg instrukcji wykonywany,
             :                    ;gdy ACC=' ' (spacja, kod=20H)
            SJMP    DALEJ
    ZNAK:   JC      STER
             :                    ;ciąg instrukcji wykonywany,
             :                    ;gdy ACC>' ' (znak widoczny, kod>20H)
            SJMP    DALEJ
    STER:    :                    ;ciąg instrukcji wykonywany,
             :                    ;gdy ACC<' ' (znak sterujący, kod<20H)
    DALEJ:   :
    
    do góry

INSTRUKCJE WYBORU

  1. Instrukcja wyboru wielokrotnego (IF..THEN..ELSEIF..THEN..ELSEIF.. )
    Często występuje potrzeba wykonania różnych czynności, zależnie od zawartości jednego z rejestrów. Typowym przykładem jest obsługa kodów klawiatury traktowanej jako różnego typu polecenia sterujące. Np. w kalkulatorze inaczej obsługuje się naciśnięcie klawisza z cyfrą (0..9), przecinkiem(,), działaniem dwuargumentowym ( + - * / ), znakiem równości ( = ) itd. Rozbudowana struktura IF-ELSE-IF.. pozwala na rozpoznawanie dowolnych kodów jak również kodów błędnych (niepasujących do warunków).

    Przykład:

    obsługa klawiszy
            LCALL   DAJ_KLAWISZ   ;ACC=0..15
            CJNE    A,#0,TEST1
             :                    ;obsługa klawisza 0
            SJMP    DALEJ
    TEST1:  CJNE    A,#1,TEST2
             :                    ;obsługa klawisza 1
            SJMP    DALEJ
    TEST2:  CJNE    A,#2,TEST3
             :                    ;obsługa klawisza 2
            SJMP    DALEJ
    TEST3:  CJNE    A,#3,TEST4
             :                    ;obsługa klawisza 3
            SJMP    DALEJ
    TEST4:  CJNE    A,#4,TEST5
             :                    ;obsługa klawisza 4
            SJMP    DALEJ
    TEST5:  CJNE    A,#5,INNE
             :                    ;obsługa klawisza 5
            SJMP    DALEJ
    INNE:    :                    ;obsługa pozostałych klawiszy
    DALEJ:   :
    
    do góry
  2. Instrukcja przełącznika (SWITCH..)
    W mikrokontrolerze 51 występuje instrukcja skoku pod adres zależny od zawartości dwóch rejestrów:
    JMP    @A+DPTR
    Daje ona możliwość realizacji bardzo eleganckiego rozwiązania rozgałęzienia zależnego od zawartości akumulatora:
    - w programie umieszczamy tablicę skoków dwubajtowych (typowo AJMP),
    - do rejestru DPTR wpisujemy adres początku tej tablicy,
    - w akumulatorze jest podwojony numer skoku.
    W porównaniu do poprzedniej struktury (IF-ELSE-IF..) jest to struktura bardziej regularna, szybciej wykonywana, czas wykonywania jest jednakowy dla różnych danych. Ilość rozgałęzień do 128.
    Jej wadą jest brak możliwości testowania zakresów danych, a jedynie pojedyńcze wartości. Oznacza to, że nie da się zrealizować warunku <, > i podobnych.
    przełącznik zależny od akumulatora
             :
            RL      A             ;ACC←ACC×2
            MOV     DPTR,#SKOKI
            JMP     @A+DPTR       ;skok do tablicy
             :
    SKOKI:  AJMP    PROG0         ;tablica skoków
            AJMP    PROG1
            AJMP    PROG2
            AJMP    PROG3
            AJMP    PROG4
            AJMP    PROG5
            AJMP    PROG6
            AJMP    PROG7
            AJMP    PROG8
             :
    

    Jeżeli do powyższej konstrukcji wykonamy skok ACALL lub LCALL, a procedury PROG0, PROG1 itd zakończymy rozkazem RET, to uzyskamy podprogram o działaniu zależnym od akumulatora.

    do góry

INSTRUKCJE PĘTLI

  1. Pętla nieskończona (AGAIN)
    Jest to pętla wykonywana "w nieskończoność". Najczęściej spotyka się ją jako główną pętlę programu, przy czym jej treść realizuje wszystkie czynności systemu (nie licząc przerwań). W rzeczywistości taka pętla (ale bardzo rozbudowana) występuje we wszystkich systemach operacyjnych.
    Stosuje się również pętlę pustą, która symuluje zatrzymanie pracy procesora.

    Przykłady:

    powtarzaj
             :
    PTL:     :                    ;treść pętli
             :
            SJMP    PTL
    
    pętla pusta
             :
            SJMP    $
    
    do góry
  2. Pętla licznikowa (FOR)
    Jest najczęściej stosowaną pętlą w programowaniu. Treść pętli zostanie wykonana tyle razy, ile wynosi wstępna zawartość rejestru pełniącego rolę licznika. W asemblerze licznik jest zwykle dekrementowany, co wynika z zastosowania bardzo wygodnej instrukcji skoku z predekrementacją:
    DJNZ    rejestr,offset
    Rejestry 8-bitowe umożliwiają realizację do 256 powtórzeń. W przypadku, gdy potrzebujemy większej stosujemy pętle zagnieżdżone.

    Przykłady:

    pętla prosta
             :
            MOV     R5,#56        ;ustawienie licznika pętli
    PTL:     :                    ;treść pętli
             :                    ;powtarzana 56 razy
            DJNZ    R5,PTL
             :
    
    pętle zagnieżdżone
             :
            MOV     R5,#50        ;ustawienie licznika pętli zewnętrznej
    PTLZ:   MOV     R6,#100       ;ustawienie licznika pętli wewnętrznej
    PTLW:    :                    ;treść pętli
             :                    ;powtarzana 50×100=5000 razy
            DJNZ    R6,PTLW
            DJNZ    R5,PTLZ
             :
    
    do góry
  3. Pętla ze sprawdzaniem warunku na początku (WHILE..)
    Jest to pętla o nieokreślonej liczbie powtórzeń, przy czym jej treść może nie być wykonana ani razu. Przed jej rozpoczęciem należy ustalić wartości zmiennych testujących pętlę. Treść pętli powinna wpływać na zmienne wykorzystywane w wyrażeniu testującym jej zakończenie.

    Przykłady:

    wykonuj, dopóki bit=0
             :
    PTL:    JB      P1.5,DALEJ
             :
             :
            SJMP    PTL
    DALEJ:   :
    
    realizacja przekodowania 1z8 → BIN
    ;założenie: w ACC jest kod 1z8 (ACC≠0)
            MOV     R4,#0
    PTL:    JNB     ACC.0,DALEJ
            RR      A
            INC     R4
            SJMP    PTL
    DALEJ:  MOV     A,R4          ;wynik w akumulatorze
    
    do góry
  4. Pętla ze sprawdzaniem warunku na końcu (REPEAT..)
    Jest to pętla o nieokreślonej liczbie powtórzeń, przy czym jej treść wykonywana jest co najmniej raz. Podobnie, jak w pętli WHILE jej treść powinna wpływać na zmienne wykorzystywane w wyrażeniu testującym jej zakończenie.
    Typowym zastosowaniem jest oczekiwanie na jakieś zdarzenie, np. na naciśnięcie określonego klawisza, zmiany stanu znacznika lub linii wejściowej, itp.

    Przykłady:

    powtórz, jeżeli zero
             :
    PTL:     :                    ;treść pętli, powinna wpływać na zawartość
             :                    ;akumulatora, gdyż test: ACC=0
            JZ      PTL
             :
    
    czekaj na plus
             :
    PTL:    ACALL   DAJ_KLAWISZ   ;ACC - kod naciśniętego klawisza
            ACALL   PIKNIJ        ;sygnał dźwiękowy
            CJNE    ACC,#'+',PTL
             :
    
    do góry
© mgr inż. Piotr Kotarski, Kalety