💡 Zapal diodę LED (Asembler 8051)

Pierwszy praktyczny projekt w asemblerze

1. Cel lekcji i co dziś zrobimy

To jest Twoje pierwsze praktyczne ćwiczenie w asemblerze 8051: zapalanie diody LED. Brzmi prosto, ale w tej jednej czynności kryją się absolutne podstawy pracy z mikrokontrolerem: porty I/O, zapis do rejestrów SFR, adresowanie bitów i pętla programu.

W tej lekcji pracujemy w symulatorze EdSim51. Jeśli używasz fizycznej płytki, zasada działania jest ta sama, ale podłączenie LED (czy jest „do plusa” czy „do masy”) może odwrócić logikę: LED może świecić dla 0 zamiast dla 1.

2. Szybka powtórka: system binarny i szesnastkowy

Mikrokontroler jest 8-bitowy – większość danych to bajty (8 bitów). Porty P0–P3 też są 8-bitowe, czyli jeden port to 8 linii: np. P1.0…P1.7.

2.1. Jak czytać zapis szesnastkowy?

Zapis hex (szesnastkowy) rozpoznasz po literze h na końcu (w asemblerze 8051). Przykłady:

Binarnie (8 bitów) Hex Dziesiętnie Znaczenie dla portu
0000 0000 00h 0 wszystkie piny = 0
1111 1111 0FFh 255 wszystkie piny = 1
0000 0001 01h 1 tylko bit 0 = 1 (np. P1.0)
1000 0000 80h 128 tylko bit 7 = 1 (np. P1.7)
0001 0000 10h 16 tylko bit 4 = 1 (np. P1.4)
Zapamiętaj: 0FFh to „osiem jedynek”, a 00h to „osiem zer”. To przyspiesza ustawianie całych portów jednym ruchem.

2.2. „Bit” kontra „bajt”

3. Jak jest podłączona dioda w EdSim51?

W naszej wersji sprzętowej LED jest podłączona anodą do +5V (przez rezystor), a katodą do pinu mikrokontrolera. To oznacza logikę active-low: 0 na pinie zapala LED, a 1 ją gasi.

W EdSim51 masz gotowe diody LED podłączone do portu (zwykle do P1). W zależności od symulatora/ustawień, LED może być „aktywna stanem niskim” (świeci dla 0) albo „aktywna stanem wysokim” (świeci dla 1).

Jeśli LED świeci odwrotnie niż oczekujesz: nie panikuj. To nie błąd w kodzie, tylko kwestia połączenia. Wtedy zamieniasz SETBCLR (albo 0FFh ↔ 00h).
EdSim51 – panel diod LED
EdSim51 – panel diod LED
1.png (zrzut/pogląd panelu LED i informacji, do którego portu są podłączone).

4. Program 1: Zapal jedną diodę (P1.0)

Najprostszy możliwy program w asemblerze 8051 robi dwie rzeczy:

  1. ustawia stan pinu (np. P1.0),
  2. zatrzymuje się w pętli nieskończonej, żeby efekt był widoczny.

4.1. Kod (wersja startowa)

; =========================================
; Lekcja 3 – Program 1: LED ON na P1.0
; =========================================

ORG 0000h          ; początek programu (wektor resetu)

; 1) Ustaw pin P1.0 w stan 0 (LED ON – połączenie katodą do pinu, active-low)
CLR P1.0

; 2) Pętla nieskończona – program „stoi”
LOOP:
SJMP LOOP

END

4.2. Co oznaczają te linie?

Dlaczego pętla nieskończona? Gdyby program „dobiegł do końca”, CPU i tak wykonywałby dalej (czyli wszedłby w losowe dane/pamięć). W mikrokontrolerach zwykle zawsze jest pętla główna.

5. Program 2: Zgaś diodę (P1.0)

Analogicznie możemy wymusić stan wysoki na pinie (LED zgaśnie przy logice active-low):

; Program 2: LED OFF na P1.0

ORG 0000h
SETB P1.0        ; ustaw bit P1.0 = 1 (LED OFF przy aktywacji stanem niskim)

HERE:
SJMP HERE
END
Uwaga o logice: w naszej konfiguracji (LED katodą do pinu) „zapal” = CLR, a „zgaś” = SETB. Jeśli u Ciebie działa odwrotnie, masz inny sposób podłączenia LED.

6. Program 3: Ustaw cały port naraz (P1 = FFh / 00h)

Mapowanie portów w EdSim51
EdSim51 – mapowanie portów i peryferiów
Zestawienie pokazuje, które piny portów P0–P3 są przypisane do LED, klawiatury, przełączników, ADC, DAC i pozostałych elementów symulatora.

Czasem zamiast sterować pojedynczym bitem, wygodniej jest ustawić cały port. Wtedy używasz MOV z wartością natychmiastową (#).

; Program 3: Wszystkie LED ON/OFF (na całym porcie P1)

ORG 0000h

MOV P1, #00h      ; LED ON: ustaw wszystkie bity portu P1 na 0 (aktywne 0)
; MOV P1, #0FFh    ; LED OFF: ustaw wszystkie bity na 1

STOP:
SJMP STOP
END

6.1. Co oznacza znak # ?

W asemblerze 8051 znak # oznacza: „to jest wartość, a nie adres”. Czyli MOV P1, #0FFh to dosłownie „wpisz liczbę FFh do rejestru portu P1”.

7. Program 4: Miganie LED (pętla + opóźnienie)

Teraz zrobimy klasykę: LED ma migać. Do tego potrzebujemy:

Uwaga: opóźnienia programowe są proste na start, ale zależą od częstotliwości zegara i czasu instrukcji. W kolejnych lekcjach zrobimy to „profesjonalnie” na timerach.
; =========================================
; Program 4: Miganie LED na P1.0
; =========================================

ORG 0000h

MAIN:
    CLR  P1.0          ; LED ON (aktywne 0)
    ACALL DELAY
    SETB P1.0          ; LED OFF
    ACALL DELAY
    SJMP MAIN

; -----------------------------------------
; Proste opóźnienie: pętla zliczająca
; Używamy rejestru R7 jako licznika.
; -----------------------------------------
DELAY:
    MOV  R7, #200       ; wartość startowa (możesz zmieniać)
D1:
    DJNZ R7, D1         ; dekrementuj i skacz, dopóki R7 != 0
    RET

END

7.1. Jak działa DJNZ?

Instrukcja DJNZ (Decrement and Jump if Not Zero):

Ważne: w powyższym opóźnieniu używamy R7. Jeśli później w programie też chcesz używać R7 do czegoś innego, musisz to uwzględnić (albo użyć innego rejestru, albo odkładać/odtwarzać rejestr).

8. EdSim51 krok po kroku: jak to uruchomić?

  1. Otwórz EdSim51 i przejdź do edytora kodu (asm).
  2. Wklej program (np. „Program 4: Miganie LED”).
  3. Złóż kod (Assemble) – jeśli są błędy, popraw literówki w etykietach lub dyrektywach.
  4. Uruchom (Run) albo wykonuj krokowo (Step), obserwując P1 i diody LED.
  5. Jeśli dioda działa „odwrotnie” (inne podłączenie), zamień SETB i CLR.
EdSim51 – miejsce na kod i przyciski uruchomienia
EdSim51 – edytor kodu i uruchamianie programu

9. Najczęstsze błędy (i szybkie naprawy)

10. Zadania dla ucznia (na ocenę lub do ćwiczeń)

  1. Zmień program tak, aby świeciła dioda P1.3 zamiast P1.0.
    Pamiętaj: LED jest active-low, więc „zapal” = ustaw 0 (CLR).
  2. Ustaw cały port P1 na 0AAh (czyli 1010 1010) i sprawdź, które LED się świecą.
    Wypisz, które bity mają 0 – to one zapalają LED przy katodzie do pinu.
  3. Zrób miganie, ale z inną proporcją: LED ma świecić długo, a gasnąć krótko (np. 3× dłużej ON niż OFF).
    ON = stan 0 na pinie, OFF = stan 1 na pinie.
  4. (Dla chętnych) Zrób „przesuwające się światło”: zapal kolejno P1.0, P1.1, P1.2… P1.7.
    W danej chwili tylko jeden bit ma być 0 (żeby świeciła tylko jedna LED).
Co dalej? W następnej lekcji zrobimy miganie i opóźnienia na timerach, czyli bez „marnowania CPU” na pętle zliczające.