Lekcja 8: Pierwsza lekcja praktyczna – Blink LED (bare-metal AVR)

Od tej lekcji zaczynasz prawdziwe programowanie mikrokontrolera AVR. Bez Arduino, bez bibliotek wysokiego poziomu – dokładnie tak, jak robi się to w systemach wbudowanych.

1) Cel lekcji

To jest lekcja przejściowa: kończy teorię i otwiera część praktyczną kursu. Jej zadaniem nie jest tylko „miganie diodą”, ale:

  • sprawdzenie całego toolchainu (edytor → kompilator → HEX → programator),
  • nauczenie pracy na rejestrach GPIO,
  • zrozumienie operacji bitowych w praktyce,
  • nabranie nawyku testowania sprzętu prostym kodem.
Blink LED = test poprawności środowiska.
Jeśli to działa, każde kolejne ćwiczenie będzie działać.

2) Przypomnienie: co fizycznie robisz?

Mikrokontroler nie „zapala LED-a” – on:

  • ustawia pin jako wyjście,
  • wystawia na nim stan logiczny 1 lub 0,
  • robi to w pętli nieskończonej.

Dioda LED jest tylko wizualnym wskaźnikiem stanu pinu.

3) Minimalny kod – absolutna baza

#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
    DDRB |= (1 << PB0);   // PB0 jako wyjście

    while (1)
    {
        PORTB |= (1 << PB0);   // LED ON
        _delay_ms(500);

        PORTB &= ~(1 << PB0); // LED OFF
        _delay_ms(500);
    }
}
To jest najprostszy poprawny program AVR.
Nie ma tu funkcji, zmiennych globalnych ani timerów – tylko rejestry i pętla.

4) Wersja „czytelna” – dobra praktyka

Od początku uczysz się pisać kod, który da się czytać i rozwijać.

#define LED_DDR   DDRB
#define LED_PORT  PORTB
#define LED_PIN   PB0

Dzięki temu:

  • łatwo zmienisz pin,
  • łatwo dodasz kolejne diody,
  • kod będzie czytelny dla uczniów.

5) Operacje bitowe – MUSISZ to rozumieć

(1 << n)      // maska bitu
X |= maska     // ustawienie bitu
X &= ~maska    // wyzerowanie bitu
X ^= maska     // przełączenie bitu
Najczęstszy błąd:
Używanie = zamiast |= powoduje nadpisanie całego rejestru.

6) Alternatywny Blink – TOGGLE

Ten sam efekt, ale krótszy kod:

while (1)
{
    PORTB ^= (1 << PB0);  // zmiana stanu
    _delay_ms(500);
}

To jest często spotykany wzorzec w systemach embedded.

7) Zadania praktyczne – poziom podstawowy

  1. Zmień czas migania na 100 ms.
  2. Sprawdź, co się stanie przy 10 ms.
  3. Zrób miganie: 3 szybkie błyski + 1 sekunda przerwy.

8) Zadania praktyczne – poziom średni

  1. Podłącz drugą LED do PB1 i migaj nimi naprzemiennie.
  2. Zrób „licznik” – LED miga coraz szybciej.
  3. Użyj zmiennej do przechowywania czasu opóźnienia.

9) Zadanie rozszerzające (dla ambitnych)

Spróbuj:

  • zrobić funkcję blink(uint8_t count),
  • która miga LED-em określoną liczbę razy,
  • a następnie wraca do pętli głównej.
Jeśli potrafisz to zrobić – jesteś gotowy na przyciski i logikę.