1. Cel lekcji
W poprzednich lekcjach sterowaliśmy pojedynczą diodą i brzęczykiem. Teraz robimy krok w stronę „prawdziwego programu”: będziemy sterować wieloma diodami naraz (całym portem), tworzyć efekty świetlne i organizować kod przy pomocy pętli oraz podprogramów.
Dodatkowo wprowadzimy temat, który odróżnia „początkujący kod” od „sensownego projektu”: tablice (tabele wzorców) – zamiast wymyślać efekty na bieżąco, zapisujemy wzorce w pamięci programu i odtwarzamy je po kolei.
2. Założenia sprzętowe (EdSim51)
Dla przejrzystości przyjmujemy, że diody LED są podłączone do portu P1: P1.0…P1.7. Jeśli u Ciebie LED są na innym porcie, zamień tylko P1 na P2/P0.
Diody LED0–LED7 są podłączone do portu P1, odpowiednio: LED0→P1.0, LED1→P1.1, …, LED7→P1.7. W typowej konfiguracji EdSim51 diody są aktywne stanem niskim (active‑low):
0 na bicie zapala LED, a 1 ją gasi.
| Dioda | Pin 8051 | Stan pinu | Efekt |
|---|---|---|---|
| LED0 | P1.0 | 0 | LED świeci |
| LED1 | P1.1 | 0 | LED świeci |
| LED2 | P1.2 | 0 | LED świeci |
| LED3 | P1.3 | 0 | LED świeci |
| LED4 | P1.4 | 0 | LED świeci |
| LED5 | P1.5 | 0 | LED świeci |
| LED6 | P1.6 | 0 | LED świeci |
| LED7 | P1.7 | 0 | LED świeci |
1.png
3. Pętle w 8051 – dwa podstawowe style
3.1. Pętla nieskończona (program mikrokontrolera „zawsze działa”)
; Pętla nieskończona
LOOP:
SJMP LOOP
3.2. Pętla z licznikiem (DJNZ)
Najważniejsze narzędzie do pętli: DJNZ. To jest „for” w asemblerze:
; R7 = licznik
MOV R7, #10
L1: ; ... kod ...
DJNZ R7, L1
4. Podprogramy – po co i jak?
Podprogram (procedura) to fragment kodu, który wywołujesz wielokrotnie: np. opóźnienie, wyświetlenie wzorca, przejście do następnego kroku animacji. Dzięki temu kod:
- jest krótszy (nie kopiujesz tego samego 10 razy),
- jest czytelniejszy,
- łatwiej go zmieniać (poprawiasz w jednym miejscu).
| Instrukcja | Znaczenie | Uwagi praktyczne |
|---|---|---|
| ACALL nazwa | Wywołanie procedury (call) | Adres powrotu trafia na stos (SP rośnie). |
| RET | Powrót z procedury | Zdejmuje adres powrotu ze stosu. |
5. Projekt: „Biegające światło” (bez tablic)
Zaczniemy od klasycznego efektu: zapala się jedna dioda i „idzie” w prawo. Zrobimy to bez tabel, korzystając z przesunięć bitowych.
5.1. Kluczowa technika: przesuwanie bitu
Jeśli w rejestrze A jest 0000 0001 (czyli 01h), to po przesunięciu w lewo otrzymasz 0000 0010 (czyli 02h), potem 04h, 08h itd.
- RL A – rotate left: przesuwa bity w lewo „w kółko”.
- RR A – rotate right: przesuwa w prawo „w kółko”.
5.2. Kod: biegające światło (RL A)
; =========================================
; Lekcja 5 – Program 1: Biegające światło (bez tablic)
; Port: P1
; =========================================
ORG 0000h
MAIN:
MOV A, #01h ; start: tylko P1.0 = 1
LOOP:
MOV R4, A ; zachowaj wzorzec logiczny
CPL A ; odwróć bity (LED active-low)
MOV P1, A ; wyślij na diody
MOV A, R4 ; przywróć wzorzec logiczny
ACALL DELAY
RL A ; przesuwaj zapaloną diodę w lewo (w kółko)
SJMP LOOP
; --- opóźnienie ---
DELAY:
MOV R6, #60
D1: MOV R7, #200
D2: DJNZ R7, D2
DJNZ R6, D1
RET
END
6. Tablice (tabele wzorców) – jak robią to „poważne” programy
Efekty świetlne często nie wynikają z prostego przesuwania bitu. Czasem chcesz niestandardowe wzorce: naprzemiennie, fala, rozszerzanie, mruganie w rytmie. Wtedy zapisujesz gotowe wartości w tabeli i odtwarzasz je po kolei.
6.1. Gdzie trzymamy tablicę?
Najwygodniej trzymać tablicę w pamięci programu (kodzie). W 8051 czyta się ją instrukcją: MOVC A, @A+DPTR.
1) DPTR wskazuje początek tabeli w pamięci programu,
2) A zawiera indeks (0, 1, 2…),
3) CPU odczytuje bajt z adresu (DPTR + A) i wpisuje go do A.
6.2. Minimalny wzór odczytu z tabeli
; DPTR = adres tabeli MOV DPTR, #TAB MOV A, #0 ; indeks MOVC A, @A+DPTR ; A = TAB[0]
7. Projekt: miganie według tabeli wzorców
Zrobimy efekt oparty o tablicę. Dzięki temu kod jest czysty: pętla bierze kolejny wzorzec i wyświetla go na P1.
7.1. Przykładowa tabela wzorców
Poniżej masz przykładowe wzorce (hex) zapisane „logicznie” (1 = ma świecić). Ponieważ LED są active‑low, kod odwraca je instrukcją CPL A przed wysłaniem na port.
| Wzorzec (hex) | Binarnie | Co to daje na LED? |
|---|---|---|
| 0AAh | 1010 1010 | naprzemiennie (co druga dioda) |
| 055h | 0101 0101 | naprzemiennie (odwrócone) |
| 0F0h | 1111 0000 | górne 4 diody |
| 00Fh | 0000 1111 | dolne 4 diody |
| 081h | 1000 0001 | skrajne diody |
7.2. Kod: efekt z tablicy (MOVC + DPTR)
; =========================================
; Lekcja 5 – Program 2: Wzorce z tabeli (tablica w pamięci programu)
; Port: P1
; =========================================
ORG 0000h
MAIN:
MOV DPTR, #PATTERN_TAB ; wskaźnik na tabelę w pamięci programu
MOV R5, #0 ; indeks wzorca (0..N-1)
NEXT:
MOV A, R5 ; A = indeks
MOVC A, @A+DPTR ; A = PATTERN_TAB[indeks]
MOV R4, A ; zachowaj wzorzec logiczny
CPL A ; odwróć bity (LED active-low)
MOV P1, A ; wyślij na diody
MOV A, R4
ACALL DELAY
INC R5 ; indeks++
CJNE R5, #PATTERN_LEN, NEXT ; jeśli R5 != długość, to bierz następny
MOV R5, #0 ; wróć do początku tablicy
SJMP NEXT
; --- opóźnienie ---
DELAY:
MOV R6, #60
D1: MOV R7, #200
D2: DJNZ R7, D2
DJNZ R6, D1
RET
; --- tablica wzorców w pamięci programu ---
PATTERN_TAB:
DB 0AAh, 055h, 0F0h, 00Fh, 081h, 042h, 024h, 018h
PATTERN_LEN EQU 8
END
8. Mała „zaawansowana technika”: łatwa zmiana efektu bez zmiany kodu
Zauważ, że w Programie 2 możesz całkowicie zmienić efekt świecenia, modyfikując tylko: DB ... w tabeli. Kod sterujący zostaje identyczny. To jest bardzo ważna idea w programowaniu systemów wbudowanych: logika + dane.
9. Jak to uruchomić w EdSim51 (checklista)
- Wklej program (Program 1 lub Program 2) do okna kodu.
- Upewnij się, że diody są na porcie P1 (albo zmień w kodzie P1→P2).
- Naciśnij Assemble, popraw ewentualne literówki w etykietach.
- Uruchom Run i obserwuj LED.
- Jeśli efekt jest „odwrotny”, odwróć wzorce w tabeli (np. 0AAh ↔ 055h).
Wstaw tu obraz 2.png (zrzut: Assemble/Run + podgląd P1, A, DPTR, R5).
10. Zadania dla ucznia
- Biegające światło: w Programie 1 dodaj, żeby co 8 kroków robiło „pauzę” (dłuższe opóźnienie).
- Nowy efekt tablicowy: stwórz tabelę 8 wartości, która robi „rozszerzanie od środka” (np. 18h → 3Ch → 7Eh → FFh → 7Eh → 3Ch → 18h → 00h).
- Zmiana kierunku: zrób dwie tabele – „lewo” i „prawo” – i przełączaj je co pełny cykl.
- Challenge: użyj dwóch różnych opóźnień: szybkie między wzorcami, a po pełnym cyklu długie.